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