Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/rpc/net.cpp
Line
Count
Source
1
// Copyright (c) 2009-present 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 <addrman_impl.h>
9
#include <banman.h>
10
#include <chainparams.h>
11
#include <clientversion.h>
12
#include <core_io.h>
13
#include <net_permissions.h>
14
#include <net_processing.h>
15
#include <net_types.h>
16
#include <netbase.h>
17
#include <node/context.h>
18
#include <node/protocol_version.h>
19
#include <node/warnings.h>
20
#include <policy/settings.h>
21
#include <protocol.h>
22
#include <rpc/blockchain.h>
23
#include <rpc/protocol.h>
24
#include <rpc/server_util.h>
25
#include <rpc/util.h>
26
#include <sync.h>
27
#include <univalue.h>
28
#include <util/chaintype.h>
29
#include <util/strencodings.h>
30
#include <util/string.h>
31
#include <util/time.h>
32
#include <util/translation.h>
33
#include <validation.h>
34
35
#include <chrono>
36
#include <optional>
37
#include <stdexcept>
38
#include <string>
39
#include <vector>
40
41
using node::NodeContext;
42
using util::Join;
43
using util::TrimString;
44
45
const std::vector<std::string> CONNECTION_TYPE_DOC{
46
        "outbound-full-relay (default automatic connections)",
47
        "block-relay-only (does not relay transactions or addresses)",
48
        "inbound (initiated by the peer)",
49
        "manual (added via addnode RPC or -addnode/-connect configuration options)",
50
        "addr-fetch (short-lived automatic connection for soliciting addresses)",
51
        "feeler (short-lived automatic connection for testing addresses)"
52
};
53
54
const std::vector<std::string> TRANSPORT_TYPE_DOC{
55
    "detecting (peer could be v1 or v2)",
56
    "v1 (plaintext transport protocol)",
57
    "v2 (BIP324 encrypted transport protocol)"
58
};
59
60
static RPCHelpMan getconnectioncount()
61
22.1k
{
62
22.1k
    return RPCHelpMan{
63
22.1k
        "getconnectioncount",
64
22.1k
        "Returns the number of connections to other nodes.\n",
65
22.1k
                {},
66
22.1k
                RPCResult{
67
22.1k
                    RPCResult::Type::NUM, "", "The connection count"
68
22.1k
                },
69
22.1k
                RPCExamples{
70
22.1k
                    HelpExampleCli("getconnectioncount", "")
71
22.1k
            + HelpExampleRpc("getconnectioncount", "")
72
22.1k
                },
73
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
74
22.1k
{
75
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
76
0
    const CConnman& connman = EnsureConnman(node);
77
78
0
    return connman.GetNodeCount(ConnectionDirection::Both);
79
0
},
80
22.1k
    };
81
22.1k
}
82
83
static RPCHelpMan ping()
84
22.1k
{
85
22.1k
    return RPCHelpMan{
86
22.1k
        "ping",
87
22.1k
        "Requests that a ping be sent to all other nodes, to measure ping time.\n"
88
22.1k
                "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
89
22.1k
                "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
90
22.1k
                {},
91
22.1k
                RPCResult{RPCResult::Type::NONE, "", ""},
92
22.1k
                RPCExamples{
93
22.1k
                    HelpExampleCli("ping", "")
94
22.1k
            + HelpExampleRpc("ping", "")
95
22.1k
                },
96
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
97
22.1k
{
98
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
99
0
    PeerManager& peerman = EnsurePeerman(node);
100
101
    // Request that each node send a ping during next message processing pass
102
0
    peerman.SendPings();
103
0
    return UniValue::VNULL;
104
0
},
105
22.1k
    };
106
22.1k
}
107
108
/** Returns, given services flags, a list of humanly readable (known) network services */
109
static UniValue GetServicesNames(ServiceFlags services)
110
0
{
111
0
    UniValue servicesNames(UniValue::VARR);
112
113
0
    for (const auto& flag : serviceFlagsToStr(services)) {
  Branch (113:27): [True: 0, False: 0]
114
0
        servicesNames.push_back(flag);
115
0
    }
116
117
0
    return servicesNames;
118
0
}
119
120
static RPCHelpMan getpeerinfo()
121
22.1k
{
122
22.1k
    return RPCHelpMan{
123
22.1k
        "getpeerinfo",
124
22.1k
        "Returns data about each connected network peer as a json array of objects.",
125
22.1k
        {},
126
22.1k
        RPCResult{
127
22.1k
            RPCResult::Type::ARR, "", "",
128
22.1k
            {
129
22.1k
                {RPCResult::Type::OBJ, "", "",
130
22.1k
                {
131
22.1k
                    {
132
22.1k
                    {RPCResult::Type::NUM, "id", "Peer index"},
133
22.1k
                    {RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"},
134
22.1k
                    {RPCResult::Type::STR, "addrbind", /*optional=*/true, "(ip:port) Bind address of the connection to the peer"},
135
22.1k
                    {RPCResult::Type::STR, "addrlocal", /*optional=*/true, "(ip:port) Local address as reported by the peer"},
136
22.1k
                    {RPCResult::Type::STR, "network", "Network (" + Join(GetNetworkNames(/*append_unroutable=*/true), ", ") + ")"},
137
22.1k
                    {RPCResult::Type::NUM, "mapped_as", /*optional=*/true, "Mapped AS (Autonomous System) number at the end of the BGP route to the peer, used for diversifying\n"
138
22.1k
                                                        "peer selection (only displayed if the -asmap config option is set)"},
139
22.1k
                    {RPCResult::Type::STR_HEX, "services", "The services offered"},
140
22.1k
                    {RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form",
141
22.1k
                    {
142
22.1k
                        {RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"}
143
22.1k
                    }},
144
22.1k
                    {RPCResult::Type::BOOL, "relaytxes", "Whether we relay transactions to this peer"},
145
22.1k
                    {RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"},
146
22.1k
                    {RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"},
147
22.1k
                    {RPCResult::Type::NUM_TIME, "last_transaction", "The " + UNIX_EPOCH_TIME + " of the last valid transaction received from this peer"},
148
22.1k
                    {RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},
149
22.1k
                    {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
150
22.1k
                    {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
151
22.1k
                    {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
152
22.1k
                    {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
153
22.1k
                    {RPCResult::Type::NUM, "pingtime", /*optional=*/true, "The last ping time in milliseconds (ms), if any"},
154
22.1k
                    {RPCResult::Type::NUM, "minping", /*optional=*/true, "The minimum observed ping time in milliseconds (ms), if any"},
155
22.1k
                    {RPCResult::Type::NUM, "pingwait", /*optional=*/true, "The duration in milliseconds (ms) of an outstanding ping (if non-zero)"},
156
22.1k
                    {RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
157
22.1k
                    {RPCResult::Type::STR, "subver", "The string version"},
158
22.1k
                    {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
159
22.1k
                    {RPCResult::Type::BOOL, "bip152_hb_to", "Whether we selected peer as (compact blocks) high-bandwidth peer"},
160
22.1k
                    {RPCResult::Type::BOOL, "bip152_hb_from", "Whether peer selected us as (compact blocks) high-bandwidth peer"},
161
22.1k
                    {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
162
22.1k
                    {RPCResult::Type::NUM, "presynced_headers", "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},
163
22.1k
                    {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
164
22.1k
                    {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
165
22.1k
                    {RPCResult::Type::ARR, "inflight", "",
166
22.1k
                    {
167
22.1k
                        {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
168
22.1k
                    }},
169
22.1k
                    {RPCResult::Type::BOOL, "addr_relay_enabled", "Whether we participate in address relay with this peer"},
170
22.1k
                    {RPCResult::Type::NUM, "addr_processed", "The total number of addresses processed, excluding those dropped due to rate limiting"},
171
22.1k
                    {RPCResult::Type::NUM, "addr_rate_limited", "The total number of addresses dropped due to rate limiting"},
172
22.1k
                    {RPCResult::Type::ARR, "permissions", "Any special permissions that have been granted to this peer",
173
22.1k
                    {
174
22.1k
                        {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
175
22.1k
                    }},
176
22.1k
                    {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
177
22.1k
                    {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
178
22.1k
                    {
179
22.1k
                        {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n"
180
22.1k
                                                      "When a message type is not listed in this json object, the bytes sent are 0.\n"
181
22.1k
                                                      "Only known message types can appear as keys in the object."}
182
22.1k
                    }},
183
22.1k
                    {RPCResult::Type::OBJ_DYN, "bytesrecv_per_msg", "",
184
22.1k
                    {
185
22.1k
                        {RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n"
186
22.1k
                                                      "When a message type is not listed in this json object, the bytes received are 0.\n"
187
22.1k
                                                      "Only known message types can appear as keys in the object and all bytes received\n"
188
22.1k
                                                      "of unknown message types are listed under '"+NET_MESSAGE_TYPE_OTHER+"'."}
189
22.1k
                    }},
190
22.1k
                    {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + ".\n"
191
22.1k
                                                              "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
192
22.1k
                                                              "best capture connection behaviors."},
193
22.1k
                    {RPCResult::Type::STR, "transport_protocol_type", "Type of transport protocol: \n" + Join(TRANSPORT_TYPE_DOC, ",\n") + ".\n"},
194
22.1k
                    {RPCResult::Type::STR, "session_id", "The session ID for this connection, or \"\" if there is none (\"v2\" transport protocol only).\n"},
195
22.1k
                }},
196
22.1k
            }},
197
22.1k
        },
198
22.1k
        RPCExamples{
199
22.1k
            HelpExampleCli("getpeerinfo", "")
200
22.1k
            + HelpExampleRpc("getpeerinfo", "")
201
22.1k
        },
202
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
203
22.1k
{
204
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
205
0
    const CConnman& connman = EnsureConnman(node);
206
0
    const PeerManager& peerman = EnsurePeerman(node);
207
208
0
    std::vector<CNodeStats> vstats;
209
0
    connman.GetNodeStats(vstats);
210
211
0
    UniValue ret(UniValue::VARR);
212
213
0
    for (const CNodeStats& stats : vstats) {
  Branch (213:34): [True: 0, False: 0]
214
0
        UniValue obj(UniValue::VOBJ);
215
0
        CNodeStateStats statestats;
216
0
        bool fStateStats = peerman.GetNodeStateStats(stats.nodeid, statestats);
217
        // GetNodeStateStats() requires the existence of a CNodeState and a Peer object
218
        // to succeed for this peer. These are created at connection initialisation and
219
        // exist for the duration of the connection - except if there is a race where the
220
        // peer got disconnected in between the GetNodeStats() and the GetNodeStateStats()
221
        // calls. In this case, the peer doesn't need to be reported here.
222
0
        if (!fStateStats) {
  Branch (222:13): [True: 0, False: 0]
223
0
            continue;
224
0
        }
225
0
        obj.pushKV("id", stats.nodeid);
226
0
        obj.pushKV("addr", stats.m_addr_name);
227
0
        if (stats.addrBind.IsValid()) {
  Branch (227:13): [True: 0, False: 0]
228
0
            obj.pushKV("addrbind", stats.addrBind.ToStringAddrPort());
229
0
        }
230
0
        if (!(stats.addrLocal.empty())) {
  Branch (230:13): [True: 0, False: 0]
231
0
            obj.pushKV("addrlocal", stats.addrLocal);
232
0
        }
233
0
        obj.pushKV("network", GetNetworkName(stats.m_network));
234
0
        if (stats.m_mapped_as != 0) {
  Branch (234:13): [True: 0, False: 0]
235
0
            obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
236
0
        }
237
0
        ServiceFlags services{statestats.their_services};
238
0
        obj.pushKV("services", strprintf("%016x", services));
239
0
        obj.pushKV("servicesnames", GetServicesNames(services));
240
0
        obj.pushKV("relaytxes", statestats.m_relay_txs);
241
0
        obj.pushKV("lastsend", count_seconds(stats.m_last_send));
242
0
        obj.pushKV("lastrecv", count_seconds(stats.m_last_recv));
243
0
        obj.pushKV("last_transaction", count_seconds(stats.m_last_tx_time));
244
0
        obj.pushKV("last_block", count_seconds(stats.m_last_block_time));
245
0
        obj.pushKV("bytessent", stats.nSendBytes);
246
0
        obj.pushKV("bytesrecv", stats.nRecvBytes);
247
0
        obj.pushKV("conntime", count_seconds(stats.m_connected));
248
0
        obj.pushKV("timeoffset", Ticks<std::chrono::seconds>(statestats.time_offset));
249
0
        if (stats.m_last_ping_time > 0us) {
  Branch (249:13): [True: 0, False: 0]
250
0
            obj.pushKV("pingtime", Ticks<SecondsDouble>(stats.m_last_ping_time));
251
0
        }
252
0
        if (stats.m_min_ping_time < std::chrono::microseconds::max()) {
  Branch (252:13): [True: 0, False: 0]
253
0
            obj.pushKV("minping", Ticks<SecondsDouble>(stats.m_min_ping_time));
254
0
        }
255
0
        if (statestats.m_ping_wait > 0s) {
  Branch (255:13): [True: 0, False: 0]
256
0
            obj.pushKV("pingwait", Ticks<SecondsDouble>(statestats.m_ping_wait));
257
0
        }
258
0
        obj.pushKV("version", stats.nVersion);
259
        // Use the sanitized form of subver here, to avoid tricksy remote peers from
260
        // corrupting or modifying the JSON output by putting special characters in
261
        // their ver message.
262
0
        obj.pushKV("subver", stats.cleanSubVer);
263
0
        obj.pushKV("inbound", stats.fInbound);
264
0
        obj.pushKV("bip152_hb_to", stats.m_bip152_highbandwidth_to);
265
0
        obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from);
266
0
        obj.pushKV("startingheight", statestats.m_starting_height);
267
0
        obj.pushKV("presynced_headers", statestats.presync_height);
268
0
        obj.pushKV("synced_headers", statestats.nSyncHeight);
269
0
        obj.pushKV("synced_blocks", statestats.nCommonHeight);
270
0
        UniValue heights(UniValue::VARR);
271
0
        for (const int height : statestats.vHeightInFlight) {
  Branch (271:31): [True: 0, False: 0]
272
0
            heights.push_back(height);
273
0
        }
274
0
        obj.pushKV("inflight", std::move(heights));
275
0
        obj.pushKV("addr_relay_enabled", statestats.m_addr_relay_enabled);
276
0
        obj.pushKV("addr_processed", statestats.m_addr_processed);
277
0
        obj.pushKV("addr_rate_limited", statestats.m_addr_rate_limited);
278
0
        UniValue permissions(UniValue::VARR);
279
0
        for (const auto& permission : NetPermissions::ToStrings(stats.m_permission_flags)) {
  Branch (279:37): [True: 0, False: 0]
280
0
            permissions.push_back(permission);
281
0
        }
282
0
        obj.pushKV("permissions", std::move(permissions));
283
0
        obj.pushKV("minfeefilter", ValueFromAmount(statestats.m_fee_filter_received));
284
285
0
        UniValue sendPerMsgType(UniValue::VOBJ);
286
0
        for (const auto& i : stats.mapSendBytesPerMsgType) {
  Branch (286:28): [True: 0, False: 0]
287
0
            if (i.second > 0)
  Branch (287:17): [True: 0, False: 0]
288
0
                sendPerMsgType.pushKV(i.first, i.second);
289
0
        }
290
0
        obj.pushKV("bytessent_per_msg", std::move(sendPerMsgType));
291
292
0
        UniValue recvPerMsgType(UniValue::VOBJ);
293
0
        for (const auto& i : stats.mapRecvBytesPerMsgType) {
  Branch (293:28): [True: 0, False: 0]
294
0
            if (i.second > 0)
  Branch (294:17): [True: 0, False: 0]
295
0
                recvPerMsgType.pushKV(i.first, i.second);
296
0
        }
297
0
        obj.pushKV("bytesrecv_per_msg", std::move(recvPerMsgType));
298
0
        obj.pushKV("connection_type", ConnectionTypeAsString(stats.m_conn_type));
299
0
        obj.pushKV("transport_protocol_type", TransportTypeAsString(stats.m_transport_type));
300
0
        obj.pushKV("session_id", stats.m_session_id);
301
302
0
        ret.push_back(std::move(obj));
303
0
    }
304
305
0
    return ret;
306
0
},
307
22.1k
    };
308
22.1k
}
309
310
static RPCHelpMan addnode()
311
22.1k
{
312
22.1k
    return RPCHelpMan{
313
22.1k
        "addnode",
314
22.1k
        "Attempts to add or remove a node from the addnode list.\n"
315
22.1k
                "Or try a connection to a node once.\n"
316
22.1k
                "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
317
22.1k
                "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n" +
318
22.1k
                strprintf("Addnode connections are limited to %u at a time", MAX_ADDNODE_CONNECTIONS) +
319
22.1k
                " and are counted separately from the -maxconnections limit.\n",
320
22.1k
                {
321
22.1k
                    {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The address of the peer to connect to"},
322
22.1k
                    {"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"},
323
22.1k
                    {"v2transport", RPCArg::Type::BOOL, RPCArg::DefaultHint{"set by -v2transport"}, "Attempt to connect using BIP324 v2 transport protocol (ignored for 'remove' command)"},
324
22.1k
                },
325
22.1k
                RPCResult{RPCResult::Type::NONE, "", ""},
326
22.1k
                RPCExamples{
327
22.1k
                    HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\" true")
328
22.1k
            + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\" true")
329
22.1k
                },
330
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
331
22.1k
{
332
0
    const auto command{self.Arg<std::string>("command")};
333
0
    if (command != "onetry" && command != "add" && command != "remove") {
  Branch (333:9): [True: 0, False: 0]
  Branch (333:32): [True: 0, False: 0]
  Branch (333:52): [True: 0, False: 0]
334
0
        throw std::runtime_error(
335
0
            self.ToString());
336
0
    }
337
338
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
339
0
    CConnman& connman = EnsureConnman(node);
340
341
0
    const auto node_arg{self.Arg<std::string>("node")};
342
0
    bool node_v2transport = connman.GetLocalServices() & NODE_P2P_V2;
343
0
    bool use_v2transport = self.MaybeArg<bool>("v2transport").value_or(node_v2transport);
344
345
0
    if (use_v2transport && !node_v2transport) {
  Branch (345:9): [True: 0, False: 0]
  Branch (345:28): [True: 0, False: 0]
346
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Error: v2transport requested but not enabled (see -v2transport)");
347
0
    }
348
349
0
    if (command == "onetry")
  Branch (349:9): [True: 0, False: 0]
350
0
    {
351
0
        CAddress addr;
352
0
        connman.OpenNetworkConnection(addr, /*fCountFailure=*/false, /*grant_outbound=*/{}, node_arg.c_str(), ConnectionType::MANUAL, use_v2transport);
353
0
        return UniValue::VNULL;
354
0
    }
355
356
0
    if (command == "add")
  Branch (356:9): [True: 0, False: 0]
357
0
    {
358
0
        if (!connman.AddNode({node_arg, use_v2transport})) {
  Branch (358:13): [True: 0, False: 0]
359
0
            throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
360
0
        }
361
0
    }
362
0
    else if (command == "remove")
  Branch (362:14): [True: 0, False: 0]
363
0
    {
364
0
        if (!connman.RemoveAddedNode(node_arg)) {
  Branch (364:13): [True: 0, False: 0]
365
0
            throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node could not be removed. It has not been added previously.");
366
0
        }
367
0
    }
368
369
0
    return UniValue::VNULL;
370
0
},
371
22.1k
    };
372
22.1k
}
373
374
static RPCHelpMan addconnection()
375
66.5k
{
376
66.5k
    return RPCHelpMan{
377
66.5k
        "addconnection",
378
66.5k
        "Open an outbound connection to a specified node. This RPC is for testing only.\n",
379
66.5k
        {
380
66.5k
            {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address and port to attempt connecting to."},
381
66.5k
            {"connection_type", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of connection to open (\"outbound-full-relay\", \"block-relay-only\", \"addr-fetch\" or \"feeler\")."},
382
66.5k
            {"v2transport", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Attempt to connect using BIP324 v2 transport protocol"},
383
66.5k
        },
384
66.5k
        RPCResult{
385
66.5k
            RPCResult::Type::OBJ, "", "",
386
66.5k
            {
387
66.5k
                { RPCResult::Type::STR, "address", "Address of newly added connection." },
388
66.5k
                { RPCResult::Type::STR, "connection_type", "Type of connection opened." },
389
66.5k
            }},
390
66.5k
        RPCExamples{
391
66.5k
            HelpExampleCli("addconnection", "\"192.168.0.6:8333\" \"outbound-full-relay\" true")
392
66.5k
            + HelpExampleRpc("addconnection", "\"192.168.0.6:8333\" \"outbound-full-relay\" true")
393
66.5k
        },
394
66.5k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
395
66.5k
{
396
44.3k
    if (Params().GetChainType() != ChainType::REGTEST) {
  Branch (396:9): [True: 0, False: 44.3k]
397
0
        throw std::runtime_error("addconnection is for regression testing (-regtest mode) only.");
398
0
    }
399
400
44.3k
    const std::string address = request.params[0].get_str();
401
44.3k
    const std::string conn_type_in{TrimString(request.params[1].get_str())};
402
44.3k
    ConnectionType conn_type{};
403
44.3k
    if (conn_type_in == "outbound-full-relay") {
  Branch (403:9): [True: 44.3k, False: 0]
404
44.3k
        conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
405
44.3k
    } else if (conn_type_in == "block-relay-only") {
  Branch (405:16): [True: 0, False: 0]
406
0
        conn_type = ConnectionType::BLOCK_RELAY;
407
0
    } else if (conn_type_in == "addr-fetch") {
  Branch (407:16): [True: 0, False: 0]
408
0
        conn_type = ConnectionType::ADDR_FETCH;
409
0
    } else if (conn_type_in == "feeler") {
  Branch (409:16): [True: 0, False: 0]
410
0
        conn_type = ConnectionType::FEELER;
411
0
    } else {
412
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, self.ToString());
413
0
    }
414
44.3k
    bool use_v2transport{self.Arg<bool>("v2transport")};
415
416
44.3k
    NodeContext& node = EnsureAnyNodeContext(request.context);
417
44.3k
    CConnman& connman = EnsureConnman(node);
418
419
44.3k
    if (use_v2transport && !(connman.GetLocalServices() & NODE_P2P_V2)) {
  Branch (419:9): [True: 0, False: 44.3k]
  Branch (419:28): [True: 0, False: 0]
420
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Error: Adding v2transport connections requires -v2transport init flag to be set.");
421
0
    }
422
423
44.3k
    const bool success = connman.AddConnection(address, conn_type, use_v2transport);
424
44.3k
    if (!success) {
  Branch (424:9): [True: 0, False: 44.3k]
425
0
        throw JSONRPCError(RPC_CLIENT_NODE_CAPACITY_REACHED, "Error: Already at capacity for specified connection type.");
426
0
    }
427
428
44.3k
    UniValue info(UniValue::VOBJ);
429
44.3k
    info.pushKV("address", address);
430
44.3k
    info.pushKV("connection_type", conn_type_in);
431
432
44.3k
    return info;
433
44.3k
},
434
66.5k
    };
435
66.5k
}
436
437
static RPCHelpMan disconnectnode()
438
22.1k
{
439
22.1k
    return RPCHelpMan{
440
22.1k
        "disconnectnode",
441
22.1k
        "Immediately disconnects from the specified peer node.\n"
442
22.1k
                "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
443
22.1k
                "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
444
22.1k
                {
445
22.1k
                    {"address", RPCArg::Type::STR, RPCArg::DefaultHint{"fallback to nodeid"}, "The IP address/port of the node"},
446
22.1k
                    {"nodeid", RPCArg::Type::NUM, RPCArg::DefaultHint{"fallback to address"}, "The node ID (see getpeerinfo for node IDs)"},
447
22.1k
                },
448
22.1k
                RPCResult{RPCResult::Type::NONE, "", ""},
449
22.1k
                RPCExamples{
450
22.1k
                    HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
451
22.1k
            + HelpExampleCli("disconnectnode", "\"\" 1")
452
22.1k
            + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
453
22.1k
            + HelpExampleRpc("disconnectnode", "\"\", 1")
454
22.1k
                },
455
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
456
22.1k
{
457
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
458
0
    CConnman& connman = EnsureConnman(node);
459
460
0
    bool success;
461
0
    const UniValue &address_arg = request.params[0];
462
0
    const UniValue &id_arg = request.params[1];
463
464
0
    if (!address_arg.isNull() && id_arg.isNull()) {
  Branch (464:9): [True: 0, False: 0]
  Branch (464:34): [True: 0, False: 0]
465
        /* handle disconnect-by-address */
466
0
        success = connman.DisconnectNode(address_arg.get_str());
467
0
    } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
  Branch (467:16): [True: 0, False: 0]
  Branch (467:37): [True: 0, False: 0]
  Branch (467:62): [True: 0, False: 0]
  Branch (467:85): [True: 0, False: 0]
468
        /* handle disconnect-by-id */
469
0
        NodeId nodeid = (NodeId) id_arg.getInt<int64_t>();
470
0
        success = connman.DisconnectNode(nodeid);
471
0
    } else {
472
0
        throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
473
0
    }
474
475
0
    if (!success) {
  Branch (475:9): [True: 0, False: 0]
476
0
        throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
477
0
    }
478
479
0
    return UniValue::VNULL;
480
0
},
481
22.1k
    };
482
22.1k
}
483
484
static RPCHelpMan getaddednodeinfo()
485
22.1k
{
486
22.1k
    return RPCHelpMan{
487
22.1k
        "getaddednodeinfo",
488
22.1k
        "Returns information about the given added node, or all added nodes\n"
489
22.1k
                "(note that onetry addnodes are not listed here)\n",
490
22.1k
                {
491
22.1k
                    {"node", RPCArg::Type::STR, RPCArg::DefaultHint{"all nodes"}, "If provided, return information about this specific node, otherwise all nodes are returned."},
492
22.1k
                },
493
22.1k
                RPCResult{
494
22.1k
                    RPCResult::Type::ARR, "", "",
495
22.1k
                    {
496
22.1k
                        {RPCResult::Type::OBJ, "", "",
497
22.1k
                        {
498
22.1k
                            {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"},
499
22.1k
                            {RPCResult::Type::BOOL, "connected", "If connected"},
500
22.1k
                            {RPCResult::Type::ARR, "addresses", "Only when connected = true",
501
22.1k
                            {
502
22.1k
                                {RPCResult::Type::OBJ, "", "",
503
22.1k
                                {
504
22.1k
                                    {RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},
505
22.1k
                                    {RPCResult::Type::STR, "connected", "connection, inbound or outbound"},
506
22.1k
                                }},
507
22.1k
                            }},
508
22.1k
                        }},
509
22.1k
                    }
510
22.1k
                },
511
22.1k
                RPCExamples{
512
22.1k
                    HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
513
22.1k
            + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
514
22.1k
                },
515
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
516
22.1k
{
517
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
518
0
    const CConnman& connman = EnsureConnman(node);
519
520
0
    std::vector<AddedNodeInfo> vInfo = connman.GetAddedNodeInfo(/*include_connected=*/true);
521
522
0
    if (!request.params[0].isNull()) {
  Branch (522:9): [True: 0, False: 0]
523
0
        bool found = false;
524
0
        for (const AddedNodeInfo& info : vInfo) {
  Branch (524:40): [True: 0, False: 0]
525
0
            if (info.m_params.m_added_node == request.params[0].get_str()) {
  Branch (525:17): [True: 0, False: 0]
526
0
                vInfo.assign(1, info);
527
0
                found = true;
528
0
                break;
529
0
            }
530
0
        }
531
0
        if (!found) {
  Branch (531:13): [True: 0, False: 0]
532
0
            throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
533
0
        }
534
0
    }
535
536
0
    UniValue ret(UniValue::VARR);
537
538
0
    for (const AddedNodeInfo& info : vInfo) {
  Branch (538:36): [True: 0, False: 0]
539
0
        UniValue obj(UniValue::VOBJ);
540
0
        obj.pushKV("addednode", info.m_params.m_added_node);
541
0
        obj.pushKV("connected", info.fConnected);
542
0
        UniValue addresses(UniValue::VARR);
543
0
        if (info.fConnected) {
  Branch (543:13): [True: 0, False: 0]
544
0
            UniValue address(UniValue::VOBJ);
545
0
            address.pushKV("address", info.resolvedAddress.ToStringAddrPort());
546
0
            address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
  Branch (546:41): [True: 0, False: 0]
547
0
            addresses.push_back(std::move(address));
548
0
        }
549
0
        obj.pushKV("addresses", std::move(addresses));
550
0
        ret.push_back(std::move(obj));
551
0
    }
552
553
0
    return ret;
554
0
},
555
22.1k
    };
556
22.1k
}
557
558
static RPCHelpMan getnettotals()
559
22.1k
{
560
22.1k
    return RPCHelpMan{"getnettotals",
561
22.1k
        "Returns information about network traffic, including bytes in, bytes out,\n"
562
22.1k
        "and current system time.",
563
22.1k
        {},
564
22.1k
                RPCResult{
565
22.1k
                   RPCResult::Type::OBJ, "", "",
566
22.1k
                   {
567
22.1k
                       {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
568
22.1k
                       {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
569
22.1k
                       {RPCResult::Type::NUM_TIME, "timemillis", "Current system " + UNIX_EPOCH_TIME + " in milliseconds"},
570
22.1k
                       {RPCResult::Type::OBJ, "uploadtarget", "",
571
22.1k
                       {
572
22.1k
                           {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
573
22.1k
                           {RPCResult::Type::NUM, "target", "Target in bytes"},
574
22.1k
                           {RPCResult::Type::BOOL, "target_reached", "True if target is reached"},
575
22.1k
                           {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},
576
22.1k
                           {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},
577
22.1k
                           {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},
578
22.1k
                        }},
579
22.1k
                    }
580
22.1k
                },
581
22.1k
                RPCExamples{
582
22.1k
                    HelpExampleCli("getnettotals", "")
583
22.1k
            + HelpExampleRpc("getnettotals", "")
584
22.1k
                },
585
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
586
22.1k
{
587
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
588
0
    const CConnman& connman = EnsureConnman(node);
589
590
0
    UniValue obj(UniValue::VOBJ);
591
0
    obj.pushKV("totalbytesrecv", connman.GetTotalBytesRecv());
592
0
    obj.pushKV("totalbytessent", connman.GetTotalBytesSent());
593
0
    obj.pushKV("timemillis", TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()));
594
595
0
    UniValue outboundLimit(UniValue::VOBJ);
596
0
    outboundLimit.pushKV("timeframe", count_seconds(connman.GetMaxOutboundTimeframe()));
597
0
    outboundLimit.pushKV("target", connman.GetMaxOutboundTarget());
598
0
    outboundLimit.pushKV("target_reached", connman.OutboundTargetReached(false));
599
0
    outboundLimit.pushKV("serve_historical_blocks", !connman.OutboundTargetReached(true));
600
0
    outboundLimit.pushKV("bytes_left_in_cycle", connman.GetOutboundTargetBytesLeft());
601
0
    outboundLimit.pushKV("time_left_in_cycle", count_seconds(connman.GetMaxOutboundTimeLeftInCycle()));
602
0
    obj.pushKV("uploadtarget", std::move(outboundLimit));
603
0
    return obj;
604
0
},
605
22.1k
    };
606
22.1k
}
607
608
static UniValue GetNetworksInfo()
609
0
{
610
0
    UniValue networks(UniValue::VARR);
611
0
    for (int n = 0; n < NET_MAX; ++n) {
  Branch (611:21): [True: 0, False: 0]
612
0
        enum Network network = static_cast<enum Network>(n);
613
0
        if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
  Branch (613:13): [True: 0, False: 0]
  Branch (613:42): [True: 0, False: 0]
614
0
        Proxy proxy;
615
0
        UniValue obj(UniValue::VOBJ);
616
0
        GetProxy(network, proxy);
617
0
        obj.pushKV("name", GetNetworkName(network));
618
0
        obj.pushKV("limited", !g_reachable_nets.Contains(network));
619
0
        obj.pushKV("reachable", g_reachable_nets.Contains(network));
620
0
        obj.pushKV("proxy", proxy.IsValid() ? proxy.ToString() : std::string());
  Branch (620:29): [True: 0, False: 0]
621
0
        obj.pushKV("proxy_randomize_credentials", proxy.m_tor_stream_isolation);
622
0
        networks.push_back(std::move(obj));
623
0
    }
624
0
    return networks;
625
0
}
626
627
static RPCHelpMan getnetworkinfo()
628
22.1k
{
629
22.1k
    return RPCHelpMan{"getnetworkinfo",
630
22.1k
                "Returns an object containing various state info regarding P2P networking.\n",
631
22.1k
                {},
632
22.1k
                RPCResult{
633
22.1k
                    RPCResult::Type::OBJ, "", "",
634
22.1k
                    {
635
22.1k
                        {RPCResult::Type::NUM, "version", "the server version"},
636
22.1k
                        {RPCResult::Type::STR, "subversion", "the server subversion string"},
637
22.1k
                        {RPCResult::Type::NUM, "protocolversion", "the protocol version"},
638
22.1k
                        {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"},
639
22.1k
                        {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form",
640
22.1k
                        {
641
22.1k
                            {RPCResult::Type::STR, "SERVICE_NAME", "the service name"},
642
22.1k
                        }},
643
22.1k
                        {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"},
644
22.1k
                        {RPCResult::Type::NUM, "timeoffset", "the time offset"},
645
22.1k
                        {RPCResult::Type::NUM, "connections", "the total number of connections"},
646
22.1k
                        {RPCResult::Type::NUM, "connections_in", "the number of inbound connections"},
647
22.1k
                        {RPCResult::Type::NUM, "connections_out", "the number of outbound connections"},
648
22.1k
                        {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"},
649
22.1k
                        {RPCResult::Type::ARR, "networks", "information per network",
650
22.1k
                        {
651
22.1k
                            {RPCResult::Type::OBJ, "", "",
652
22.1k
                            {
653
22.1k
                                {RPCResult::Type::STR, "name", "network (" + Join(GetNetworkNames(), ", ") + ")"},
654
22.1k
                                {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"},
655
22.1k
                                {RPCResult::Type::BOOL, "reachable", "is the network reachable?"},
656
22.1k
                                {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"},
657
22.1k
                                {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"},
658
22.1k
                            }},
659
22.1k
                        }},
660
22.1k
                        {RPCResult::Type::NUM, "relayfee", "minimum relay fee rate for transactions in " + CURRENCY_UNIT + "/kvB"},
661
22.1k
                        {RPCResult::Type::NUM, "incrementalfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},
662
22.1k
                        {RPCResult::Type::ARR, "localaddresses", "list of local addresses",
663
22.1k
                        {
664
22.1k
                            {RPCResult::Type::OBJ, "", "",
665
22.1k
                            {
666
22.1k
                                {RPCResult::Type::STR, "address", "network address"},
667
22.1k
                                {RPCResult::Type::NUM, "port", "network port"},
668
22.1k
                                {RPCResult::Type::NUM, "score", "relative score"},
669
22.1k
                            }},
670
22.1k
                        }},
671
22.1k
                        (IsDeprecatedRPCEnabled("warnings") ?
  Branch (671:26): [True: 0, False: 22.1k]
672
0
                            RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} :
673
22.1k
                            RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)",
674
22.1k
                            {
675
22.1k
                                {RPCResult::Type::STR, "", "warning"},
676
22.1k
                            }
677
22.1k
                            }
678
22.1k
                        ),
679
22.1k
                    }
680
22.1k
                },
681
22.1k
                RPCExamples{
682
22.1k
                    HelpExampleCli("getnetworkinfo", "")
683
22.1k
            + HelpExampleRpc("getnetworkinfo", "")
684
22.1k
                },
685
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
686
22.1k
{
687
0
    LOCK(cs_main);
688
0
    UniValue obj(UniValue::VOBJ);
689
0
    obj.pushKV("version",       CLIENT_VERSION);
690
0
    obj.pushKV("subversion",    strSubVersion);
691
0
    obj.pushKV("protocolversion",PROTOCOL_VERSION);
692
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
693
0
    if (node.connman) {
  Branch (693:9): [True: 0, False: 0]
694
0
        ServiceFlags services = node.connman->GetLocalServices();
695
0
        obj.pushKV("localservices", strprintf("%016x", services));
696
0
        obj.pushKV("localservicesnames", GetServicesNames(services));
697
0
    }
698
0
    if (node.peerman) {
  Branch (698:9): [True: 0, False: 0]
699
0
        auto peerman_info{node.peerman->GetInfo()};
700
0
        obj.pushKV("localrelay", !peerman_info.ignores_incoming_txs);
701
0
        obj.pushKV("timeoffset", Ticks<std::chrono::seconds>(peerman_info.median_outbound_time_offset));
702
0
    }
703
0
    if (node.connman) {
  Branch (703:9): [True: 0, False: 0]
704
0
        obj.pushKV("networkactive", node.connman->GetNetworkActive());
705
0
        obj.pushKV("connections", node.connman->GetNodeCount(ConnectionDirection::Both));
706
0
        obj.pushKV("connections_in", node.connman->GetNodeCount(ConnectionDirection::In));
707
0
        obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out));
708
0
    }
709
0
    obj.pushKV("networks",      GetNetworksInfo());
710
0
    if (node.mempool) {
  Branch (710:9): [True: 0, False: 0]
711
        // Those fields can be deprecated, to be replaced by the getmempoolinfo fields
712
0
        obj.pushKV("relayfee", ValueFromAmount(node.mempool->m_opts.min_relay_feerate.GetFeePerK()));
713
0
        obj.pushKV("incrementalfee", ValueFromAmount(node.mempool->m_opts.incremental_relay_feerate.GetFeePerK()));
714
0
    }
715
0
    UniValue localAddresses(UniValue::VARR);
716
0
    {
717
0
        LOCK(g_maplocalhost_mutex);
718
0
        for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
  Branch (718:70): [True: 0, False: 0]
719
0
        {
720
0
            UniValue rec(UniValue::VOBJ);
721
0
            rec.pushKV("address", item.first.ToStringAddr());
722
0
            rec.pushKV("port", item.second.nPort);
723
0
            rec.pushKV("score", item.second.nScore);
724
0
            localAddresses.push_back(std::move(rec));
725
0
        }
726
0
    }
727
0
    obj.pushKV("localaddresses", std::move(localAddresses));
728
0
    obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings")));
729
0
    return obj;
730
0
},
731
22.1k
    };
732
22.1k
}
733
734
static RPCHelpMan setban()
735
22.1k
{
736
22.1k
    return RPCHelpMan{
737
22.1k
        "setban",
738
22.1k
        "Attempts to add or remove an IP/Subnet from the banned list.\n",
739
22.1k
                {
740
22.1k
                    {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
741
22.1k
                    {"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"},
742
22.1k
                    {"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)"},
743
22.1k
                    {"absolute", RPCArg::Type::BOOL, RPCArg::Default{false}, "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
744
22.1k
                },
745
22.1k
                RPCResult{RPCResult::Type::NONE, "", ""},
746
22.1k
                RPCExamples{
747
22.1k
                    HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
748
22.1k
                            + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
749
22.1k
                            + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
750
22.1k
                },
751
22.1k
        [&](const RPCHelpMan& help, const JSONRPCRequest& request) -> UniValue
752
22.1k
{
753
0
    std::string strCommand;
754
0
    if (!request.params[1].isNull())
  Branch (754:9): [True: 0, False: 0]
755
0
        strCommand = request.params[1].get_str();
756
0
    if (strCommand != "add" && strCommand != "remove") {
  Branch (756:9): [True: 0, False: 0]
  Branch (756:32): [True: 0, False: 0]
757
0
        throw std::runtime_error(help.ToString());
758
0
    }
759
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
760
0
    BanMan& banman = EnsureBanman(node);
761
762
0
    CSubNet subNet;
763
0
    CNetAddr netAddr;
764
0
    bool isSubnet = false;
765
766
0
    if (request.params[0].get_str().find('/') != std::string::npos)
  Branch (766:9): [True: 0, False: 0]
767
0
        isSubnet = true;
768
769
0
    if (!isSubnet) {
  Branch (769:9): [True: 0, False: 0]
770
0
        const std::optional<CNetAddr> addr{LookupHost(request.params[0].get_str(), false)};
771
0
        if (addr.has_value()) {
  Branch (771:13): [True: 0, False: 0]
772
0
            netAddr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
773
0
        }
774
0
    }
775
0
    else
776
0
        subNet = LookupSubNet(request.params[0].get_str());
777
778
0
    if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
  Branch (778:9): [True: 0, False: 0]
  Branch (778:12): [True: 0, False: 0]
779
0
        throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
780
781
0
    if (strCommand == "add")
  Branch (781:9): [True: 0, False: 0]
782
0
    {
783
0
        if (isSubnet ? banman.IsBanned(subNet) : banman.IsBanned(netAddr)) {
  Branch (783:13): [True: 0, False: 0]
  Branch (783:13): [True: 0, False: 0]
784
0
            throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
785
0
        }
786
787
0
        int64_t banTime = 0; //use standard bantime if not specified
788
0
        if (!request.params[2].isNull())
  Branch (788:13): [True: 0, False: 0]
789
0
            banTime = request.params[2].getInt<int64_t>();
790
791
0
        const bool absolute{request.params[3].isNull() ? false : request.params[3].get_bool()};
  Branch (791:29): [True: 0, False: 0]
792
793
0
        if (absolute && banTime < GetTime()) {
  Branch (793:13): [True: 0, False: 0]
  Branch (793:25): [True: 0, False: 0]
794
0
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Error: Absolute timestamp is in the past");
795
0
        }
796
797
0
        if (isSubnet) {
  Branch (797:13): [True: 0, False: 0]
798
0
            banman.Ban(subNet, banTime, absolute);
799
0
            if (node.connman) {
  Branch (799:17): [True: 0, False: 0]
800
0
                node.connman->DisconnectNode(subNet);
801
0
            }
802
0
        } else {
803
0
            banman.Ban(netAddr, banTime, absolute);
804
0
            if (node.connman) {
  Branch (804:17): [True: 0, False: 0]
805
0
                node.connman->DisconnectNode(netAddr);
806
0
            }
807
0
        }
808
0
    }
809
0
    else if(strCommand == "remove")
  Branch (809:13): [True: 0, False: 0]
810
0
    {
811
0
        if (!( isSubnet ? banman.Unban(subNet) : banman.Unban(netAddr) )) {
  Branch (811:13): [True: 0, False: 0]
  Branch (811:16): [True: 0, False: 0]
812
0
            throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");
813
0
        }
814
0
    }
815
0
    return UniValue::VNULL;
816
0
},
817
22.1k
    };
818
22.1k
}
819
820
static RPCHelpMan listbanned()
821
22.1k
{
822
22.1k
    return RPCHelpMan{
823
22.1k
        "listbanned",
824
22.1k
        "List all manually banned IPs/Subnets.\n",
825
22.1k
                {},
826
22.1k
        RPCResult{RPCResult::Type::ARR, "", "",
827
22.1k
            {
828
22.1k
                {RPCResult::Type::OBJ, "", "",
829
22.1k
                    {
830
22.1k
                        {RPCResult::Type::STR, "address", "The IP/Subnet of the banned node"},
831
22.1k
                        {RPCResult::Type::NUM_TIME, "ban_created", "The " + UNIX_EPOCH_TIME + " the ban was created"},
832
22.1k
                        {RPCResult::Type::NUM_TIME, "banned_until", "The " + UNIX_EPOCH_TIME + " the ban expires"},
833
22.1k
                        {RPCResult::Type::NUM_TIME, "ban_duration", "The ban duration, in seconds"},
834
22.1k
                        {RPCResult::Type::NUM_TIME, "time_remaining", "The time remaining until the ban expires, in seconds"},
835
22.1k
                    }},
836
22.1k
            }},
837
22.1k
                RPCExamples{
838
22.1k
                    HelpExampleCli("listbanned", "")
839
22.1k
                            + HelpExampleRpc("listbanned", "")
840
22.1k
                },
841
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
842
22.1k
{
843
0
    BanMan& banman = EnsureAnyBanman(request.context);
844
845
0
    banmap_t banMap;
846
0
    banman.GetBanned(banMap);
847
0
    const int64_t current_time{GetTime()};
848
849
0
    UniValue bannedAddresses(UniValue::VARR);
850
0
    for (const auto& entry : banMap)
  Branch (850:28): [True: 0, False: 0]
851
0
    {
852
0
        const CBanEntry& banEntry = entry.second;
853
0
        UniValue rec(UniValue::VOBJ);
854
0
        rec.pushKV("address", entry.first.ToString());
855
0
        rec.pushKV("ban_created", banEntry.nCreateTime);
856
0
        rec.pushKV("banned_until", banEntry.nBanUntil);
857
0
        rec.pushKV("ban_duration", (banEntry.nBanUntil - banEntry.nCreateTime));
858
0
        rec.pushKV("time_remaining", (banEntry.nBanUntil - current_time));
859
860
0
        bannedAddresses.push_back(std::move(rec));
861
0
    }
862
863
0
    return bannedAddresses;
864
0
},
865
22.1k
    };
866
22.1k
}
867
868
static RPCHelpMan clearbanned()
869
22.1k
{
870
22.1k
    return RPCHelpMan{
871
22.1k
        "clearbanned",
872
22.1k
        "Clear all banned IPs.\n",
873
22.1k
                {},
874
22.1k
                RPCResult{RPCResult::Type::NONE, "", ""},
875
22.1k
                RPCExamples{
876
22.1k
                    HelpExampleCli("clearbanned", "")
877
22.1k
                            + HelpExampleRpc("clearbanned", "")
878
22.1k
                },
879
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
880
22.1k
{
881
0
    BanMan& banman = EnsureAnyBanman(request.context);
882
883
0
    banman.ClearBanned();
884
885
0
    return UniValue::VNULL;
886
0
},
887
22.1k
    };
888
22.1k
}
889
890
static RPCHelpMan setnetworkactive()
891
22.1k
{
892
22.1k
    return RPCHelpMan{
893
22.1k
        "setnetworkactive",
894
22.1k
        "Disable/enable all p2p network activity.\n",
895
22.1k
                {
896
22.1k
                    {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
897
22.1k
                },
898
22.1k
                RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
899
22.1k
                RPCExamples{""},
900
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
901
22.1k
{
902
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
903
0
    CConnman& connman = EnsureConnman(node);
904
905
0
    connman.SetNetworkActive(request.params[0].get_bool());
906
907
0
    return connman.GetNetworkActive();
908
0
},
909
22.1k
    };
910
22.1k
}
911
912
static RPCHelpMan getnodeaddresses()
913
22.1k
{
914
22.1k
    return RPCHelpMan{"getnodeaddresses",
915
22.1k
                "Return known addresses, after filtering for quality and recency.\n"
916
22.1k
                "These can potentially be used to find new peers in the network.\n"
917
22.1k
                "The total number of addresses known to the node may be higher.",
918
22.1k
                {
919
22.1k
                    {"count", RPCArg::Type::NUM, RPCArg::Default{1}, "The maximum number of addresses to return. Specify 0 to return all known addresses."},
920
22.1k
                    {"network", RPCArg::Type::STR, RPCArg::DefaultHint{"all networks"}, "Return only addresses of the specified network. Can be one of: " + Join(GetNetworkNames(), ", ") + "."},
921
22.1k
                },
922
22.1k
                RPCResult{
923
22.1k
                    RPCResult::Type::ARR, "", "",
924
22.1k
                    {
925
22.1k
                        {RPCResult::Type::OBJ, "", "",
926
22.1k
                        {
927
22.1k
                            {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " when the node was last seen"},
928
22.1k
                            {RPCResult::Type::NUM, "services", "The services offered by the node"},
929
22.1k
                            {RPCResult::Type::STR, "address", "The address of the node"},
930
22.1k
                            {RPCResult::Type::NUM, "port", "The port number of the node"},
931
22.1k
                            {RPCResult::Type::STR, "network", "The network (" + Join(GetNetworkNames(), ", ") + ") the node connected through"},
932
22.1k
                        }},
933
22.1k
                    }
934
22.1k
                },
935
22.1k
                RPCExamples{
936
22.1k
                    HelpExampleCli("getnodeaddresses", "8")
937
22.1k
                    + HelpExampleCli("getnodeaddresses", "4 \"i2p\"")
938
22.1k
                    + HelpExampleCli("-named getnodeaddresses", "network=onion count=12")
939
22.1k
                    + HelpExampleRpc("getnodeaddresses", "8")
940
22.1k
                    + HelpExampleRpc("getnodeaddresses", "4, \"i2p\"")
941
22.1k
                },
942
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
943
22.1k
{
944
0
    NodeContext& node = EnsureAnyNodeContext(request.context);
945
0
    const CConnman& connman = EnsureConnman(node);
946
947
0
    const int count{request.params[0].isNull() ? 1 : request.params[0].getInt<int>()};
  Branch (947:21): [True: 0, False: 0]
948
0
    if (count < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
  Branch (948:9): [True: 0, False: 0]
949
950
0
    const std::optional<Network> network{request.params[1].isNull() ? std::nullopt : std::optional<Network>{ParseNetwork(request.params[1].get_str())}};
  Branch (950:42): [True: 0, False: 0]
951
0
    if (network == NET_UNROUTABLE) {
  Branch (951:9): [True: 0, False: 0]
952
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Network not recognized: %s", request.params[1].get_str()));
953
0
    }
954
955
    // returns a shuffled list of CAddress
956
0
    const std::vector<CAddress> vAddr{connman.GetAddresses(count, /*max_pct=*/0, network)};
957
0
    UniValue ret(UniValue::VARR);
958
959
0
    for (const CAddress& addr : vAddr) {
  Branch (959:31): [True: 0, False: 0]
960
0
        UniValue obj(UniValue::VOBJ);
961
0
        obj.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(addr.nTime)});
962
0
        obj.pushKV("services", (uint64_t)addr.nServices);
963
0
        obj.pushKV("address", addr.ToStringAddr());
964
0
        obj.pushKV("port", addr.GetPort());
965
0
        obj.pushKV("network", GetNetworkName(addr.GetNetClass()));
966
0
        ret.push_back(std::move(obj));
967
0
    }
968
0
    return ret;
969
0
},
970
22.1k
    };
971
22.1k
}
972
973
static RPCHelpMan addpeeraddress()
974
22.1k
{
975
22.1k
    return RPCHelpMan{"addpeeraddress",
976
22.1k
        "Add the address of a potential peer to an address manager table. This RPC is for testing only.",
977
22.1k
        {
978
22.1k
            {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address of the peer"},
979
22.1k
            {"port", RPCArg::Type::NUM, RPCArg::Optional::NO, "The port of the peer"},
980
22.1k
            {"tried", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, attempt to add the peer to the tried addresses table"},
981
22.1k
        },
982
22.1k
        RPCResult{
983
22.1k
            RPCResult::Type::OBJ, "", "",
984
22.1k
            {
985
22.1k
                {RPCResult::Type::BOOL, "success", "whether the peer address was successfully added to the address manager table"},
986
22.1k
                {RPCResult::Type::STR, "error", /*optional=*/true, "error description, if the address could not be added"},
987
22.1k
            },
988
22.1k
        },
989
22.1k
        RPCExamples{
990
22.1k
            HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 8333 true")
991
22.1k
    + HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 8333, true")
992
22.1k
        },
993
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
994
22.1k
{
995
0
    AddrMan& addrman = EnsureAnyAddrman(request.context);
996
997
0
    const std::string& addr_string{request.params[0].get_str()};
998
0
    const auto port{request.params[1].getInt<uint16_t>()};
999
0
    const bool tried{request.params[2].isNull() ? false : request.params[2].get_bool()};
  Branch (999:22): [True: 0, False: 0]
1000
1001
0
    UniValue obj(UniValue::VOBJ);
1002
0
    std::optional<CNetAddr> net_addr{LookupHost(addr_string, false)};
1003
0
    bool success{false};
1004
1005
0
    if (net_addr.has_value()) {
  Branch (1005:9): [True: 0, False: 0]
1006
0
        CService service{net_addr.value(), port};
1007
0
        CAddress address{MaybeFlipIPv6toCJDNS(service), ServiceFlags{NODE_NETWORK | NODE_WITNESS}};
1008
0
        address.nTime = Now<NodeSeconds>();
1009
        // The source address is set equal to the address. This is equivalent to the peer
1010
        // announcing itself.
1011
0
        if (addrman.Add({address}, address)) {
  Branch (1011:13): [True: 0, False: 0]
1012
0
            success = true;
1013
0
            if (tried) {
  Branch (1013:17): [True: 0, False: 0]
1014
                // Attempt to move the address to the tried addresses table.
1015
0
                if (!addrman.Good(address)) {
  Branch (1015:21): [True: 0, False: 0]
1016
0
                    success = false;
1017
0
                    obj.pushKV("error", "failed-adding-to-tried");
1018
0
                }
1019
0
            }
1020
0
        } else {
1021
0
            obj.pushKV("error", "failed-adding-to-new");
1022
0
        }
1023
0
    }
1024
1025
0
    obj.pushKV("success", success);
1026
0
    return obj;
1027
0
},
1028
22.1k
    };
1029
22.1k
}
1030
1031
static RPCHelpMan sendmsgtopeer()
1032
22.1k
{
1033
22.1k
    return RPCHelpMan{
1034
22.1k
        "sendmsgtopeer",
1035
22.1k
        "Send a p2p message to a peer specified by id.\n"
1036
22.1k
        "The message type and body must be provided, the message header will be generated.\n"
1037
22.1k
        "This RPC is for testing only.",
1038
22.1k
        {
1039
22.1k
            {"peer_id", RPCArg::Type::NUM, RPCArg::Optional::NO, "The peer to send the message to."},
1040
22.1k
            {"msg_type", RPCArg::Type::STR, RPCArg::Optional::NO, strprintf("The message type (maximum length %i)", CMessageHeader::MESSAGE_TYPE_SIZE)},
1041
22.1k
            {"msg", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The serialized message body to send, in hex, without a message header"},
1042
22.1k
        },
1043
22.1k
        RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},
1044
22.1k
        RPCExamples{
1045
22.1k
            HelpExampleCli("sendmsgtopeer", "0 \"addr\" \"ffffff\"") + HelpExampleRpc("sendmsgtopeer", "0 \"addr\" \"ffffff\"")},
1046
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
1047
0
            const NodeId peer_id{request.params[0].getInt<int64_t>()};
1048
0
            const std::string& msg_type{request.params[1].get_str()};
1049
0
            if (msg_type.size() > CMessageHeader::MESSAGE_TYPE_SIZE) {
  Branch (1049:17): [True: 0, False: 0]
1050
0
                throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Error: msg_type too long, max length is %i", CMessageHeader::MESSAGE_TYPE_SIZE));
1051
0
            }
1052
0
            auto msg{TryParseHex<unsigned char>(request.params[2].get_str())};
1053
0
            if (!msg.has_value()) {
  Branch (1053:17): [True: 0, False: 0]
1054
0
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Error parsing input for msg");
1055
0
            }
1056
1057
0
            NodeContext& node = EnsureAnyNodeContext(request.context);
1058
0
            CConnman& connman = EnsureConnman(node);
1059
1060
0
            CSerializedNetMsg msg_ser;
1061
0
            msg_ser.data = msg.value();
1062
0
            msg_ser.m_type = msg_type;
1063
1064
0
            bool success = connman.ForNode(peer_id, [&](CNode* node) {
1065
0
                connman.PushMessage(node, std::move(msg_ser));
1066
0
                return true;
1067
0
            });
1068
1069
0
            if (!success) {
  Branch (1069:17): [True: 0, False: 0]
1070
0
                throw JSONRPCError(RPC_MISC_ERROR, "Error: Could not send message to peer");
1071
0
            }
1072
1073
0
            UniValue ret{UniValue::VOBJ};
1074
0
            return ret;
1075
0
        },
1076
22.1k
    };
1077
22.1k
}
1078
1079
static RPCHelpMan getaddrmaninfo()
1080
22.1k
{
1081
22.1k
    return RPCHelpMan{
1082
22.1k
        "getaddrmaninfo",
1083
22.1k
        "Provides information about the node's address manager by returning the number of "
1084
22.1k
        "addresses in the `new` and `tried` tables and their sum for all networks.\n",
1085
22.1k
        {},
1086
22.1k
        RPCResult{
1087
22.1k
            RPCResult::Type::OBJ_DYN, "", "json object with network type as keys", {
1088
22.1k
                {RPCResult::Type::OBJ, "network", "the network (" + Join(GetNetworkNames(), ", ") + ", all_networks)", {
1089
22.1k
                {RPCResult::Type::NUM, "new", "number of addresses in the new table, which represent potential peers the node has discovered but hasn't yet successfully connected to."},
1090
22.1k
                {RPCResult::Type::NUM, "tried", "number of addresses in the tried table, which represent peers the node has successfully connected to in the past."},
1091
22.1k
                {RPCResult::Type::NUM, "total", "total number of addresses in both new/tried tables"},
1092
22.1k
            }},
1093
22.1k
        }},
1094
22.1k
        RPCExamples{HelpExampleCli("getaddrmaninfo", "") + HelpExampleRpc("getaddrmaninfo", "")},
1095
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
1096
0
            AddrMan& addrman = EnsureAnyAddrman(request.context);
1097
1098
0
            UniValue ret(UniValue::VOBJ);
1099
0
            for (int n = 0; n < NET_MAX; ++n) {
  Branch (1099:29): [True: 0, False: 0]
1100
0
                enum Network network = static_cast<enum Network>(n);
1101
0
                if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue;
  Branch (1101:21): [True: 0, False: 0]
  Branch (1101:50): [True: 0, False: 0]
1102
0
                UniValue obj(UniValue::VOBJ);
1103
0
                obj.pushKV("new", addrman.Size(network, true));
1104
0
                obj.pushKV("tried", addrman.Size(network, false));
1105
0
                obj.pushKV("total", addrman.Size(network));
1106
0
                ret.pushKV(GetNetworkName(network), std::move(obj));
1107
0
            }
1108
0
            UniValue obj(UniValue::VOBJ);
1109
0
            obj.pushKV("new", addrman.Size(std::nullopt, true));
1110
0
            obj.pushKV("tried", addrman.Size(std::nullopt, false));
1111
0
            obj.pushKV("total", addrman.Size());
1112
0
            ret.pushKV("all_networks", std::move(obj));
1113
0
            return ret;
1114
0
        },
1115
22.1k
    };
1116
22.1k
}
1117
1118
UniValue AddrmanEntryToJSON(const AddrInfo& info, const CConnman& connman)
1119
0
{
1120
0
    UniValue ret(UniValue::VOBJ);
1121
0
    ret.pushKV("address", info.ToStringAddr());
1122
0
    const uint32_t mapped_as{connman.GetMappedAS(info)};
1123
0
    if (mapped_as) {
  Branch (1123:9): [True: 0, False: 0]
1124
0
        ret.pushKV("mapped_as", mapped_as);
1125
0
    }
1126
0
    ret.pushKV("port", info.GetPort());
1127
0
    ret.pushKV("services", (uint64_t)info.nServices);
1128
0
    ret.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(info.nTime)});
1129
0
    ret.pushKV("network", GetNetworkName(info.GetNetClass()));
1130
0
    ret.pushKV("source", info.source.ToStringAddr());
1131
0
    ret.pushKV("source_network", GetNetworkName(info.source.GetNetClass()));
1132
0
    const uint32_t source_mapped_as{connman.GetMappedAS(info.source)};
1133
0
    if (source_mapped_as) {
  Branch (1133:9): [True: 0, False: 0]
1134
0
        ret.pushKV("source_mapped_as", source_mapped_as);
1135
0
    }
1136
0
    return ret;
1137
0
}
1138
1139
UniValue AddrmanTableToJSON(const std::vector<std::pair<AddrInfo, AddressPosition>>& tableInfos, const CConnman& connman)
1140
0
{
1141
0
    UniValue table(UniValue::VOBJ);
1142
0
    for (const auto& e : tableInfos) {
  Branch (1142:24): [True: 0, False: 0]
1143
0
        AddrInfo info = e.first;
1144
0
        AddressPosition location = e.second;
1145
0
        std::ostringstream key;
1146
0
        key << location.bucket << "/" << location.position;
1147
        // Address manager tables have unique entries so there is no advantage
1148
        // in using UniValue::pushKV, which checks if the key already exists
1149
        // in O(N). UniValue::pushKVEnd is used instead which currently is O(1).
1150
0
        table.pushKVEnd(key.str(), AddrmanEntryToJSON(info, connman));
1151
0
    }
1152
0
    return table;
1153
0
}
1154
1155
static RPCHelpMan getrawaddrman()
1156
22.1k
{
1157
22.1k
    return RPCHelpMan{"getrawaddrman",
1158
22.1k
        "EXPERIMENTAL warning: this call may be changed in future releases.\n"
1159
22.1k
        "\nReturns information on all address manager entries for the new and tried tables.\n",
1160
22.1k
        {},
1161
22.1k
        RPCResult{
1162
22.1k
            RPCResult::Type::OBJ_DYN, "", "", {
1163
22.1k
                {RPCResult::Type::OBJ_DYN, "table", "buckets with addresses in the address manager table ( new, tried )", {
1164
22.1k
                    {RPCResult::Type::OBJ, "bucket/position", "the location in the address manager table (<bucket>/<position>)", {
1165
22.1k
                        {RPCResult::Type::STR, "address", "The address of the node"},
1166
22.1k
                        {RPCResult::Type::NUM, "mapped_as", /*optional=*/true, "Mapped AS (Autonomous System) number at the end of the BGP route to the peer, used for diversifying peer selection (only displayed if the -asmap config option is set)"},
1167
22.1k
                        {RPCResult::Type::NUM, "port", "The port number of the node"},
1168
22.1k
                        {RPCResult::Type::STR, "network", "The network (" + Join(GetNetworkNames(), ", ") + ") of the address"},
1169
22.1k
                        {RPCResult::Type::NUM, "services", "The services offered by the node"},
1170
22.1k
                        {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " when the node was last seen"},
1171
22.1k
                        {RPCResult::Type::STR, "source", "The address that relayed the address to us"},
1172
22.1k
                        {RPCResult::Type::STR, "source_network", "The network (" + Join(GetNetworkNames(), ", ") + ") of the source address"},
1173
22.1k
                        {RPCResult::Type::NUM, "source_mapped_as", /*optional=*/true, "Mapped AS (Autonomous System) number at the end of the BGP route to the source, used for diversifying peer selection (only displayed if the -asmap config option is set)"}
1174
22.1k
                    }}
1175
22.1k
                }}
1176
22.1k
            }
1177
22.1k
        },
1178
22.1k
        RPCExamples{
1179
22.1k
            HelpExampleCli("getrawaddrman", "")
1180
22.1k
            + HelpExampleRpc("getrawaddrman", "")
1181
22.1k
        },
1182
22.1k
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
1183
0
            AddrMan& addrman = EnsureAnyAddrman(request.context);
1184
0
            NodeContext& node_context = EnsureAnyNodeContext(request.context);
1185
0
            CConnman& connman = EnsureConnman(node_context);
1186
1187
0
            UniValue ret(UniValue::VOBJ);
1188
0
            ret.pushKV("new", AddrmanTableToJSON(addrman.GetEntries(false), connman));
1189
0
            ret.pushKV("tried", AddrmanTableToJSON(addrman.GetEntries(true), connman));
1190
0
            return ret;
1191
0
        },
1192
22.1k
    };
1193
22.1k
}
1194
1195
void RegisterNetRPCCommands(CRPCTable& t)
1196
11.0k
{
1197
11.0k
    static const CRPCCommand commands[]{
1198
11.0k
        {"network", &getconnectioncount},
1199
11.0k
        {"network", &ping},
1200
11.0k
        {"network", &getpeerinfo},
1201
11.0k
        {"network", &addnode},
1202
11.0k
        {"network", &disconnectnode},
1203
11.0k
        {"network", &getaddednodeinfo},
1204
11.0k
        {"network", &getnettotals},
1205
11.0k
        {"network", &getnetworkinfo},
1206
11.0k
        {"network", &setban},
1207
11.0k
        {"network", &listbanned},
1208
11.0k
        {"network", &clearbanned},
1209
11.0k
        {"network", &setnetworkactive},
1210
11.0k
        {"network", &getnodeaddresses},
1211
11.0k
        {"network", &getaddrmaninfo},
1212
11.0k
        {"hidden", &addconnection},
1213
11.0k
        {"hidden", &addpeeraddress},
1214
11.0k
        {"hidden", &sendmsgtopeer},
1215
11.0k
        {"hidden", &getrawaddrman},
1216
11.0k
    };
1217
199k
    for (const auto& c : commands) {
  Branch (1217:24): [True: 199k, False: 11.0k]
1218
199k
        t.appendCommand(c.name, &c);
1219
199k
    }
1220
11.0k
}