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