Bitcoin Core  0.21.1
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules
net.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <rpc/server.h>
6 
7 #include <banman.h>
8 #include <clientversion.h>
9 #include <core_io.h>
10 #include <net.h>
11 #include <net_permissions.h>
12 #include <net_processing.h>
13 #include <net_types.h> // For banmap_t
14 #include <netbase.h>
15 #include <node/context.h>
16 #include <policy/settings.h>
17 #include <rpc/blockchain.h>
18 #include <rpc/protocol.h>
19 #include <rpc/util.h>
20 #include <sync.h>
21 #include <timedata.h>
22 #include <util/strencodings.h>
23 #include <util/string.h>
24 #include <util/system.h>
25 #include <util/translation.h>
26 #include <validation.h>
27 #include <version.h>
28 #include <warnings.h>
29 
30 #include <univalue.h>
31 
32 const std::vector<std::string> CONNECTION_TYPE_DOC{
33  "outbound-full-relay (default automatic connections)",
34  "block-relay-only (does not relay transactions or addresses)",
35  "inbound (initiated by the peer)",
36  "manual (added via addnode RPC or -addnode/-connect configuration options)",
37  "addr-fetch (short-lived automatic connection for soliciting addresses)",
38  "feeler (short-lived automatic connection for testing addresses)"
39 };
40 
42 {
43  return RPCHelpMan{"getconnectioncount",
44  "\nReturns the number of connections to other nodes.\n",
45  {},
46  RPCResult{
47  RPCResult::Type::NUM, "", "The connection count"
48  },
50  HelpExampleCli("getconnectioncount", "")
51  + HelpExampleRpc("getconnectioncount", "")
52  },
53  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
54 {
55  NodeContext& node = EnsureNodeContext(request.context);
56  if(!node.connman)
57  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
58 
59  return (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
60 },
61  };
62 }
63 
64 static RPCHelpMan ping()
65 {
66  return RPCHelpMan{"ping",
67  "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
68  "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
69  "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
70  {},
73  HelpExampleCli("ping", "")
74  + HelpExampleRpc("ping", "")
75  },
76  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
77 {
78  NodeContext& node = EnsureNodeContext(request.context);
79  if(!node.connman)
80  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
81 
82  // Request that each node send a ping during next message processing pass
83  node.connman->ForEachNode([](CNode* pnode) {
84  pnode->fPingQueued = true;
85  });
86  return NullUniValue;
87 },
88  };
89 }
90 
92 {
93  return RPCHelpMan{"getpeerinfo",
94  "\nReturns data about each connected network node as a json array of objects.\n",
95  {},
96  RPCResult{
97  RPCResult::Type::ARR, "", "",
98  {
99  {RPCResult::Type::OBJ, "", "",
100  {
101  {
102  {RPCResult::Type::NUM, "id", "Peer index"},
103  {RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"},
104  {RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"},
105  {RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"},
106  {RPCResult::Type::STR, "network", "Network (ipv4, ipv6, or onion) the peer connected through"},
107  {RPCResult::Type::NUM, "mapped_as", "The AS in the BGP route to the peer used for diversifying\n"
108  "peer selection (only available if the asmap config flag is set)"},
109  {RPCResult::Type::STR_HEX, "services", "The services offered"},
110  {RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form",
111  {
112  {RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"}
113  }},
114  {RPCResult::Type::BOOL, "relaytxes", "Whether peer has asked us to relay transactions to it"},
115  {RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"},
116  {RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"},
117  {RPCResult::Type::NUM_TIME, "last_transaction", "The " + UNIX_EPOCH_TIME + " of the last valid transaction received from this peer"},
118  {RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},
119  {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
120  {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
121  {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
122  {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
123  {RPCResult::Type::NUM, "pingtime", "ping time (if available)"},
124  {RPCResult::Type::NUM, "minping", "minimum observed ping time (if any at all)"},
125  {RPCResult::Type::NUM, "pingwait", "ping wait (if non-zero)"},
126  {RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
127  {RPCResult::Type::STR, "subver", "The string version"},
128  {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
129  {RPCResult::Type::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n"
130  "(DEPRECATED, returned only if the config option -deprecatedrpc=getpeerinfo_addnode is passed)"},
131  {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + ".\n"
132  "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
133  "best capture connection behaviors."},
134  {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
135  {RPCResult::Type::NUM, "banscore", "The ban score (DEPRECATED, returned only if config option -deprecatedrpc=banscore is passed)"},
136  {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
137  {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
138  {RPCResult::Type::ARR, "inflight", "",
139  {
140  {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
141  }},
142  {RPCResult::Type::BOOL, "whitelisted", /* optional */ true, "Whether the peer is whitelisted with default permissions\n"
143  "(DEPRECATED, returned only if config option -deprecatedrpc=whitelisted is passed)"},
144  {RPCResult::Type::ARR, "permissions", "Any special permissions that have been granted to this peer",
145  {
146  {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
147  }},
148  {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
149  {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
150  {
151  {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n"
152  "When a message type is not listed in this json object, the bytes sent are 0.\n"
153  "Only known message types can appear as keys in the object."}
154  }},
155  {RPCResult::Type::OBJ, "bytesrecv_per_msg", "",
156  {
157  {RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n"
158  "When a message type is not listed in this json object, the bytes received are 0.\n"
159  "Only known message types can appear as keys in the object and all bytes received\n"
160  "of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."}
161  }},
162  }},
163  }},
164  },
165  RPCExamples{
166  HelpExampleCli("getpeerinfo", "")
167  + HelpExampleRpc("getpeerinfo", "")
168  },
169  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
170 {
171  NodeContext& node = EnsureNodeContext(request.context);
172  if(!node.connman)
173  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
174 
175  std::vector<CNodeStats> vstats;
176  node.connman->GetNodeStats(vstats);
177 
179 
180  for (const CNodeStats& stats : vstats) {
182  CNodeStateStats statestats;
183  bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
184  obj.pushKV("id", stats.nodeid);
185  obj.pushKV("addr", stats.addrName);
186  if (stats.addrBind.IsValid()) {
187  obj.pushKV("addrbind", stats.addrBind.ToString());
188  }
189  if (!(stats.addrLocal.empty())) {
190  obj.pushKV("addrlocal", stats.addrLocal);
191  }
192  obj.pushKV("network", stats.m_network);
193  if (stats.m_mapped_as != 0) {
194  obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
195  }
196  obj.pushKV("services", strprintf("%016x", stats.nServices));
197  obj.pushKV("servicesnames", GetServicesNames(stats.nServices));
198  obj.pushKV("relaytxes", stats.fRelayTxes);
199  obj.pushKV("lastsend", stats.nLastSend);
200  obj.pushKV("lastrecv", stats.nLastRecv);
201  obj.pushKV("last_transaction", stats.nLastTXTime);
202  obj.pushKV("last_block", stats.nLastBlockTime);
203  obj.pushKV("bytessent", stats.nSendBytes);
204  obj.pushKV("bytesrecv", stats.nRecvBytes);
205  obj.pushKV("conntime", stats.nTimeConnected);
206  obj.pushKV("timeoffset", stats.nTimeOffset);
207  if (stats.m_ping_usec > 0) {
208  obj.pushKV("pingtime", ((double)stats.m_ping_usec) / 1e6);
209  }
210  if (stats.m_min_ping_usec < std::numeric_limits<int64_t>::max()) {
211  obj.pushKV("minping", ((double)stats.m_min_ping_usec) / 1e6);
212  }
213  if (stats.m_ping_wait_usec > 0) {
214  obj.pushKV("pingwait", ((double)stats.m_ping_wait_usec) / 1e6);
215  }
216  obj.pushKV("version", stats.nVersion);
217  // Use the sanitized form of subver here, to avoid tricksy remote peers from
218  // corrupting or modifying the JSON output by putting special characters in
219  // their ver message.
220  obj.pushKV("subver", stats.cleanSubVer);
221  obj.pushKV("inbound", stats.fInbound);
222  if (IsDeprecatedRPCEnabled("getpeerinfo_addnode")) {
223  // addnode is deprecated in v0.21 for removal in v0.22
224  obj.pushKV("addnode", stats.m_manual_connection);
225  }
226  obj.pushKV("startingheight", stats.nStartingHeight);
227  if (fStateStats) {
228  if (IsDeprecatedRPCEnabled("banscore")) {
229  // banscore is deprecated in v0.21 for removal in v0.22
230  obj.pushKV("banscore", statestats.m_misbehavior_score);
231  }
232  obj.pushKV("synced_headers", statestats.nSyncHeight);
233  obj.pushKV("synced_blocks", statestats.nCommonHeight);
234  UniValue heights(UniValue::VARR);
235  for (const int height : statestats.vHeightInFlight) {
236  heights.push_back(height);
237  }
238  obj.pushKV("inflight", heights);
239  }
240  if (IsDeprecatedRPCEnabled("whitelisted")) {
241  // whitelisted is deprecated in v0.21 for removal in v0.22
242  obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
243  }
244  UniValue permissions(UniValue::VARR);
245  for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
246  permissions.push_back(permission);
247  }
248  obj.pushKV("permissions", permissions);
249  obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter));
250 
251  UniValue sendPerMsgCmd(UniValue::VOBJ);
252  for (const auto& i : stats.mapSendBytesPerMsgCmd) {
253  if (i.second > 0)
254  sendPerMsgCmd.pushKV(i.first, i.second);
255  }
256  obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
257 
258  UniValue recvPerMsgCmd(UniValue::VOBJ);
259  for (const auto& i : stats.mapRecvBytesPerMsgCmd) {
260  if (i.second > 0)
261  recvPerMsgCmd.pushKV(i.first, i.second);
262  }
263  obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
264  obj.pushKV("connection_type", stats.m_conn_type_string);
265 
266  ret.push_back(obj);
267  }
268 
269  return ret;
270 },
271  };
272 }
273 
275 {
276  return RPCHelpMan{"addnode",
277  "\nAttempts to add or remove a node from the addnode list.\n"
278  "Or try a connection to a node once.\n"
279  "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
280  "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n",
281  {
282  {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"},
283  {"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"},
284  },
286  RPCExamples{
287  HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
288  + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
289  },
290  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
291 {
292  std::string strCommand;
293  if (!request.params[1].isNull())
294  strCommand = request.params[1].get_str();
295  if (request.fHelp || request.params.size() != 2 ||
296  (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
297  throw std::runtime_error(
298  self.ToString());
299 
300  NodeContext& node = EnsureNodeContext(request.context);
301  if(!node.connman)
302  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
303 
304  std::string strNode = request.params[0].get_str();
305 
306  if (strCommand == "onetry")
307  {
308  CAddress addr;
309  node.connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL);
310  return NullUniValue;
311  }
312 
313  if (strCommand == "add")
314  {
315  if(!node.connman->AddNode(strNode))
316  throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
317  }
318  else if(strCommand == "remove")
319  {
320  if(!node.connman->RemoveAddedNode(strNode))
321  throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node could not be removed. It has not been added previously.");
322  }
323 
324  return NullUniValue;
325 },
326  };
327 }
328 
330 {
331  return RPCHelpMan{"disconnectnode",
332  "\nImmediately disconnects from the specified peer node.\n"
333  "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
334  "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
335  {
336  {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"},
337  {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"},
338  },
340  RPCExamples{
341  HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
342  + HelpExampleCli("disconnectnode", "\"\" 1")
343  + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
344  + HelpExampleRpc("disconnectnode", "\"\", 1")
345  },
346  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
347 {
348  NodeContext& node = EnsureNodeContext(request.context);
349  if(!node.connman)
350  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
351 
352  bool success;
353  const UniValue &address_arg = request.params[0];
354  const UniValue &id_arg = request.params[1];
355 
356  if (!address_arg.isNull() && id_arg.isNull()) {
357  /* handle disconnect-by-address */
358  success = node.connman->DisconnectNode(address_arg.get_str());
359  } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
360  /* handle disconnect-by-id */
361  NodeId nodeid = (NodeId) id_arg.get_int64();
362  success = node.connman->DisconnectNode(nodeid);
363  } else {
364  throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
365  }
366 
367  if (!success) {
368  throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
369  }
370 
371  return NullUniValue;
372 },
373  };
374 }
375 
377 {
378  return RPCHelpMan{"getaddednodeinfo",
379  "\nReturns information about the given added node, or all added nodes\n"
380  "(note that onetry addnodes are not listed here)\n",
381  {
382  {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."},
383  },
384  RPCResult{
385  RPCResult::Type::ARR, "", "",
386  {
387  {RPCResult::Type::OBJ, "", "",
388  {
389  {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"},
390  {RPCResult::Type::BOOL, "connected", "If connected"},
391  {RPCResult::Type::ARR, "addresses", "Only when connected = true",
392  {
393  {RPCResult::Type::OBJ, "", "",
394  {
395  {RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},
396  {RPCResult::Type::STR, "connected", "connection, inbound or outbound"},
397  }},
398  }},
399  }},
400  }
401  },
402  RPCExamples{
403  HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
404  + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
405  },
406  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
407 {
408  NodeContext& node = EnsureNodeContext(request.context);
409  if(!node.connman)
410  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
411 
412  std::vector<AddedNodeInfo> vInfo = node.connman->GetAddedNodeInfo();
413 
414  if (!request.params[0].isNull()) {
415  bool found = false;
416  for (const AddedNodeInfo& info : vInfo) {
417  if (info.strAddedNode == request.params[0].get_str()) {
418  vInfo.assign(1, info);
419  found = true;
420  break;
421  }
422  }
423  if (!found) {
424  throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
425  }
426  }
427 
429 
430  for (const AddedNodeInfo& info : vInfo) {
432  obj.pushKV("addednode", info.strAddedNode);
433  obj.pushKV("connected", info.fConnected);
434  UniValue addresses(UniValue::VARR);
435  if (info.fConnected) {
436  UniValue address(UniValue::VOBJ);
437  address.pushKV("address", info.resolvedAddress.ToString());
438  address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
439  addresses.push_back(address);
440  }
441  obj.pushKV("addresses", addresses);
442  ret.push_back(obj);
443  }
444 
445  return ret;
446 },
447  };
448 }
449 
451 {
452  return RPCHelpMan{"getnettotals",
453  "\nReturns information about network traffic, including bytes in, bytes out,\n"
454  "and current time.\n",
455  {},
456  RPCResult{
457  RPCResult::Type::OBJ, "", "",
458  {
459  {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
460  {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
461  {RPCResult::Type::NUM_TIME, "timemillis", "Current " + UNIX_EPOCH_TIME + " in milliseconds"},
462  {RPCResult::Type::OBJ, "uploadtarget", "",
463  {
464  {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
465  {RPCResult::Type::NUM, "target", "Target in bytes"},
466  {RPCResult::Type::BOOL, "target_reached", "True if target is reached"},
467  {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},
468  {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},
469  {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},
470  }},
471  }
472  },
473  RPCExamples{
474  HelpExampleCli("getnettotals", "")
475  + HelpExampleRpc("getnettotals", "")
476  },
477  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
478 {
479  NodeContext& node = EnsureNodeContext(request.context);
480  if(!node.connman)
481  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
482 
484  obj.pushKV("totalbytesrecv", node.connman->GetTotalBytesRecv());
485  obj.pushKV("totalbytessent", node.connman->GetTotalBytesSent());
486  obj.pushKV("timemillis", GetTimeMillis());
487 
488  UniValue outboundLimit(UniValue::VOBJ);
489  outboundLimit.pushKV("timeframe", node.connman->GetMaxOutboundTimeframe());
490  outboundLimit.pushKV("target", node.connman->GetMaxOutboundTarget());
491  outboundLimit.pushKV("target_reached", node.connman->OutboundTargetReached(false));
492  outboundLimit.pushKV("serve_historical_blocks", !node.connman->OutboundTargetReached(true));
493  outboundLimit.pushKV("bytes_left_in_cycle", node.connman->GetOutboundTargetBytesLeft());
494  outboundLimit.pushKV("time_left_in_cycle", node.connman->GetMaxOutboundTimeLeftInCycle());
495  obj.pushKV("uploadtarget", outboundLimit);
496  return obj;
497 },
498  };
499 }
500 
502 {
503  UniValue networks(UniValue::VARR);
504  for (int n = 0; n < NET_MAX; ++n) {
505  enum Network network = static_cast<enum Network>(n);
506  if (network == NET_UNROUTABLE || network == NET_I2P || network == NET_CJDNS || network == NET_INTERNAL) continue;
507  proxyType proxy;
509  GetProxy(network, proxy);
510  obj.pushKV("name", GetNetworkName(network));
511  obj.pushKV("limited", !IsReachable(network));
512  obj.pushKV("reachable", IsReachable(network));
513  obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
514  obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
515  networks.push_back(obj);
516  }
517  return networks;
518 }
519 
521 {
522  return RPCHelpMan{"getnetworkinfo",
523  "Returns an object containing various state info regarding P2P networking.\n",
524  {},
525  RPCResult{
526  RPCResult::Type::OBJ, "", "",
527  {
528  {RPCResult::Type::NUM, "version", "the server version"},
529  {RPCResult::Type::STR, "subversion", "the server subversion string"},
530  {RPCResult::Type::NUM, "protocolversion", "the protocol version"},
531  {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"},
532  {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form",
533  {
534  {RPCResult::Type::STR, "SERVICE_NAME", "the service name"},
535  }},
536  {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"},
537  {RPCResult::Type::NUM, "timeoffset", "the time offset"},
538  {RPCResult::Type::NUM, "connections", "the total number of connections"},
539  {RPCResult::Type::NUM, "connections_in", "the number of inbound connections"},
540  {RPCResult::Type::NUM, "connections_out", "the number of outbound connections"},
541  {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"},
542  {RPCResult::Type::ARR, "networks", "information per network",
543  {
544  {RPCResult::Type::OBJ, "", "",
545  {
546  {RPCResult::Type::STR, "name", "network (ipv4, ipv6 or onion)"},
547  {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"},
548  {RPCResult::Type::BOOL, "reachable", "is the network reachable?"},
549  {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"},
550  {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"},
551  }},
552  }},
553  {RPCResult::Type::NUM, "relayfee", "minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB"},
554  {RPCResult::Type::NUM, "incrementalfee", "minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB"},
555  {RPCResult::Type::ARR, "localaddresses", "list of local addresses",
556  {
557  {RPCResult::Type::OBJ, "", "",
558  {
559  {RPCResult::Type::STR, "address", "network address"},
560  {RPCResult::Type::NUM, "port", "network port"},
561  {RPCResult::Type::NUM, "score", "relative score"},
562  }},
563  }},
564  {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"},
565  }
566  },
567  RPCExamples{
568  HelpExampleCli("getnetworkinfo", "")
569  + HelpExampleRpc("getnetworkinfo", "")
570  },
571  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
572 {
573  LOCK(cs_main);
575  obj.pushKV("version", CLIENT_VERSION);
576  obj.pushKV("subversion", strSubVersion);
577  obj.pushKV("protocolversion",PROTOCOL_VERSION);
578  NodeContext& node = EnsureNodeContext(request.context);
579  if (node.connman) {
580  ServiceFlags services = node.connman->GetLocalServices();
581  obj.pushKV("localservices", strprintf("%016x", services));
582  obj.pushKV("localservicesnames", GetServicesNames(services));
583  }
584  obj.pushKV("localrelay", g_relay_txes);
585  obj.pushKV("timeoffset", GetTimeOffset());
586  if (node.connman) {
587  obj.pushKV("networkactive", node.connman->GetNetworkActive());
588  obj.pushKV("connections", (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
589  obj.pushKV("connections_in", (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_IN));
590  obj.pushKV("connections_out", (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_OUT));
591  }
592  obj.pushKV("networks", GetNetworksInfo());
593  obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
594  obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
595  UniValue localAddresses(UniValue::VARR);
596  {
598  for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
599  {
601  rec.pushKV("address", item.first.ToString());
602  rec.pushKV("port", item.second.nPort);
603  rec.pushKV("score", item.second.nScore);
604  localAddresses.push_back(rec);
605  }
606  }
607  obj.pushKV("localaddresses", localAddresses);
608  obj.pushKV("warnings", GetWarnings(false).original);
609  return obj;
610 },
611  };
612 }
613 
615 {
616  return RPCHelpMan{"setban",
617  "\nAttempts to add or remove an IP/Subnet from the banned list.\n",
618  {
619  {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
620  {"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"},
621  {"bantime", RPCArg::Type::NUM, /* 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)"},
622  {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
623  },
625  RPCExamples{
626  HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
627  + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
628  + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
629  },
630  [&](const RPCHelpMan& help, const JSONRPCRequest& request) -> UniValue
631 {
632  std::string strCommand;
633  if (!request.params[1].isNull())
634  strCommand = request.params[1].get_str();
635  if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
636  throw std::runtime_error(help.ToString());
637  }
638  NodeContext& node = EnsureNodeContext(request.context);
639  if (!node.banman) {
640  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
641  }
642 
643  CSubNet subNet;
644  CNetAddr netAddr;
645  bool isSubnet = false;
646 
647  if (request.params[0].get_str().find('/') != std::string::npos)
648  isSubnet = true;
649 
650  if (!isSubnet) {
651  CNetAddr resolved;
652  LookupHost(request.params[0].get_str(), resolved, false);
653  netAddr = resolved;
654  }
655  else
656  LookupSubNet(request.params[0].get_str(), subNet);
657 
658  if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
659  throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
660 
661  if (strCommand == "add")
662  {
663  if (isSubnet ? node.banman->IsBanned(subNet) : node.banman->IsBanned(netAddr)) {
664  throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
665  }
666 
667  int64_t banTime = 0; //use standard bantime if not specified
668  if (!request.params[2].isNull())
669  banTime = request.params[2].get_int64();
670 
671  bool absolute = false;
672  if (request.params[3].isTrue())
673  absolute = true;
674 
675  if (isSubnet) {
676  node.banman->Ban(subNet, banTime, absolute);
677  if (node.connman) {
678  node.connman->DisconnectNode(subNet);
679  }
680  } else {
681  node.banman->Ban(netAddr, banTime, absolute);
682  if (node.connman) {
683  node.connman->DisconnectNode(netAddr);
684  }
685  }
686  }
687  else if(strCommand == "remove")
688  {
689  if (!( isSubnet ? node.banman->Unban(subNet) : node.banman->Unban(netAddr) )) {
690  throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");
691  }
692  }
693  return NullUniValue;
694 },
695  };
696 }
697 
699 {
700  return RPCHelpMan{"listbanned",
701  "\nList all manually banned IPs/Subnets.\n",
702  {},
704  {
705  {RPCResult::Type::OBJ, "", "",
706  {
707  {RPCResult::Type::STR, "address", ""},
708  {RPCResult::Type::NUM_TIME, "banned_until", ""},
709  {RPCResult::Type::NUM_TIME, "ban_created", ""},
710  }},
711  }},
712  RPCExamples{
713  HelpExampleCli("listbanned", "")
714  + HelpExampleRpc("listbanned", "")
715  },
716  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
717 {
718  NodeContext& node = EnsureNodeContext(request.context);
719  if(!node.banman) {
720  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
721  }
722 
723  banmap_t banMap;
724  node.banman->GetBanned(banMap);
725 
726  UniValue bannedAddresses(UniValue::VARR);
727  for (const auto& entry : banMap)
728  {
729  const CBanEntry& banEntry = entry.second;
731  rec.pushKV("address", entry.first.ToString());
732  rec.pushKV("banned_until", banEntry.nBanUntil);
733  rec.pushKV("ban_created", banEntry.nCreateTime);
734 
735  bannedAddresses.push_back(rec);
736  }
737 
738  return bannedAddresses;
739 },
740  };
741 }
742 
744 {
745  return RPCHelpMan{"clearbanned",
746  "\nClear all banned IPs.\n",
747  {},
749  RPCExamples{
750  HelpExampleCli("clearbanned", "")
751  + HelpExampleRpc("clearbanned", "")
752  },
753  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
754 {
755  NodeContext& node = EnsureNodeContext(request.context);
756  if (!node.banman) {
757  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
758  }
759 
760  node.banman->ClearBanned();
761 
762  return NullUniValue;
763 },
764  };
765 }
766 
768 {
769  return RPCHelpMan{"setnetworkactive",
770  "\nDisable/enable all p2p network activity.\n",
771  {
772  {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
773  },
774  RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
775  RPCExamples{""},
776  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
777 {
778  NodeContext& node = EnsureNodeContext(request.context);
779  if (!node.connman) {
780  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
781  }
782 
783  node.connman->SetNetworkActive(request.params[0].get_bool());
784 
785  return node.connman->GetNetworkActive();
786 },
787  };
788 }
789 
791 {
792  return RPCHelpMan{"getnodeaddresses",
793  "\nReturn known addresses which can potentially be used to find new nodes in the network\n",
794  {
795  {"count", RPCArg::Type::NUM, /* default */ "1", "The maximum number of addresses to return. Specify 0 to return all known addresses."},
796  },
797  RPCResult{
798  RPCResult::Type::ARR, "", "",
799  {
800  {RPCResult::Type::OBJ, "", "",
801  {
802  {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " of when the node was last seen"},
803  {RPCResult::Type::NUM, "services", "The services offered"},
804  {RPCResult::Type::STR, "address", "The address of the node"},
805  {RPCResult::Type::NUM, "port", "The port of the node"},
806  }},
807  }
808  },
809  RPCExamples{
810  HelpExampleCli("getnodeaddresses", "8")
811  + HelpExampleRpc("getnodeaddresses", "8")
812  },
813  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
814 {
815  NodeContext& node = EnsureNodeContext(request.context);
816  if (!node.connman) {
817  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
818  }
819 
820  int count = 1;
821  if (!request.params[0].isNull()) {
822  count = request.params[0].get_int();
823  if (count < 0) {
824  throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
825  }
826  }
827  // returns a shuffled list of CAddress
828  std::vector<CAddress> vAddr = node.connman->GetAddresses(count, /* max_pct */ 0);
830 
831  for (const CAddress& addr : vAddr) {
833  obj.pushKV("time", (int)addr.nTime);
834  obj.pushKV("services", (uint64_t)addr.nServices);
835  obj.pushKV("address", addr.ToStringIP());
836  obj.pushKV("port", addr.GetPort());
837  ret.push_back(obj);
838  }
839  return ret;
840 },
841  };
842 }
843 
845 {
846  return RPCHelpMan{"addpeeraddress",
847  "\nAdd the address of a potential peer to the address manager. This RPC is for testing only.\n",
848  {
849  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address of the peer"},
850  {"port", RPCArg::Type::NUM, RPCArg::Optional::NO, "The port of the peer"},
851  },
852  RPCResult{
853  RPCResult::Type::OBJ, "", "",
854  {
855  {RPCResult::Type::BOOL, "success", "whether the peer address was successfully added to the address manager"},
856  },
857  },
858  RPCExamples{
859  HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 8333")
860  + HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 8333")
861  },
862  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
863 {
864  NodeContext& node = EnsureNodeContext(request.context);
865  if (!node.connman) {
866  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
867  }
868 
870 
871  std::string addr_string = request.params[0].get_str();
872  uint16_t port = request.params[1].get_int();
873 
874  CNetAddr net_addr;
875  if (!LookupHost(addr_string, net_addr, false)) {
876  obj.pushKV("success", false);
877  return obj;
878  }
879  CAddress address = CAddress({net_addr, port}, ServiceFlags(NODE_NETWORK|NODE_WITNESS));
880  address.nTime = GetAdjustedTime();
881  // The source address is set equal to the address. This is equivalent to the peer
882  // announcing itself.
883  if (!node.connman->AddNewAddresses({address}, address)) {
884  obj.pushKV("success", false);
885  return obj;
886  }
887 
888  obj.pushKV("success", true);
889  return obj;
890 },
891  };
892 }
893 
895 {
896 // clang-format off
897 static const CRPCCommand commands[] =
898 { // category name actor (function) argNames
899  // --------------------- ------------------------ ----------------------- ----------
900  { "network", "getconnectioncount", &getconnectioncount, {} },
901  { "network", "ping", &ping, {} },
902  { "network", "getpeerinfo", &getpeerinfo, {} },
903  { "network", "addnode", &addnode, {"node","command"} },
904  { "network", "disconnectnode", &disconnectnode, {"address", "nodeid"} },
905  { "network", "getaddednodeinfo", &getaddednodeinfo, {"node"} },
906  { "network", "getnettotals", &getnettotals, {} },
907  { "network", "getnetworkinfo", &getnetworkinfo, {} },
908  { "network", "setban", &setban, {"subnet", "command", "bantime", "absolute"} },
909  { "network", "listbanned", &listbanned, {} },
910  { "network", "clearbanned", &clearbanned, {} },
911  { "network", "setnetworkactive", &setnetworkactive, {"state"} },
912  { "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
913  { "hidden", "addpeeraddress", &addpeeraddress, {"address", "port"} },
914 };
915 // clang-format on
916  for (const auto& c : commands) {
917  t.appendCommand(c.name, &c);
918  }
919 }
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:60
static RPCHelpMan ping()
Definition: net.cpp:64
const std::string & get_str() const
bool IsReachable(enum Network net)
Node has not been added before.
Definition: protocol.h:61
const std::vector< std::string > NET_PERMISSIONS_DOC
ServiceFlags
nServices flags
Definition: protocol.h:269
static RPCHelpMan clearbanned()
Definition: net.cpp:743
RPC command dispatcher.
Definition: server.h:137
A set of addresses that represent the hash of a string or FQDN.
Definition: netaddress.h:65
We open manual connections to addresses that users explicitly inputted via the addnode RPC...
Dummy value to indicate the number of NET_* constants.
Definition: netaddress.h:68
Required arg.
const std::string NET_MESSAGE_COMMAND_OTHER
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:60
std::unique_ptr< BanMan > banman
Definition: context.h:41
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:36
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:264
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:20
void RegisterNetRPCCommands(CRPCTable &t)
Register P2P networking RPC commands.
Definition: net.cpp:894
std::string ToStringIPPort() const
Definition: netaddress.cpp:972
bool g_relay_txes
UniValue ValueFromAmount(const CAmount &amount)
Definition: core_write.cpp:18
static UniValue GetNetworksInfo()
Definition: net.cpp:501
static RPCHelpMan addpeeraddress()
Definition: net.cpp:844
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are: ...
Definition: timedata.cpp:28
static RPCHelpMan getnettotals()
Definition: net.cpp:450
I2P.
Definition: netaddress.h:58
int64_t nCreateTime
Definition: addrdb.h:25
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:831
bool IsValid() const
Definition: netbase.h:34
static RPCHelpMan getpeerinfo()
Definition: net.cpp:91
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:71
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats)
Get statistics from node state.
int64_t get_int64() const
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:51
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
static RPCHelpMan getnodeaddresses()
Definition: net.cpp:790
Special string with only hex chars.
NodeContext struct containing references to chain state and connection state.
Definition: context.h:36
std::unique_ptr< CConnman > connman
Definition: context.h:37
bool randomize_credentials
Definition: netbase.h:37
CFeeRate minRelayTxFee
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) ...
Definition: validation.cpp:149
bool IsValid() const
Definition: netaddress.cpp:432
#define LOCK(cs)
Definition: sync.h:230
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:138
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: validation.cpp:129
static RPCHelpMan disconnectnode()
Definition: net.cpp:329
A CService with information about it as peer.
Definition: protocol.h:360
const std::string CURRENCY_UNIT
Definition: feerate.h:14
static RPCHelpMan setban()
Definition: net.cpp:614
static RPCHelpMan addnode()
Definition: net.cpp:274
RecursiveMutex cs_mapLocalHost
Network
A network type.
Definition: netaddress.h:43
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
int64_t NodeId
Definition: net.h:92
Invalid IP/Subnet.
Definition: protocol.h:63
bool IsDeprecatedRPCEnabled(const std::string &method)
Definition: server.cpp:346
Special numeric to denote unix epoch time.
static RPCHelpMan setnetworkactive()
Definition: net.cpp:767
CFeeRate incrementalRelayFee
Definition: settings.cpp:12
int64_t nBanUntil
Definition: addrdb.h:26
NodeContext & EnsureNodeContext(const util::Ref &context)
Definition: blockchain.cpp:58
Database error.
Definition: protocol.h:44
const std::vector< std::string > CONNECTION_TYPE_DOC
Definition: net.cpp:32
Network address.
Definition: netaddress.h:119
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Resolve a host string to its corresponding network addresses.
Definition: netbase.cpp:159
bool IsValidNumArgs(size_t num_args) const
If the supplied number of args is neither too small nor too high.
Definition: util.cpp:479
std::atomic< bool > fPingQueued
Definition: net.h:1057
CService proxy
Definition: netbase.h:36
bilingual_str GetWarnings(bool verbose)
Format a string that describes several potential problems detected by the core.
Definition: warnings.cpp:44
bool IsValid() const
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12
int64_t GetAdjustedTime()
Definition: timedata.cpp:34
static RPCHelpMan getnetworkinfo()
Definition: net.cpp:520
Node to disconnect not found in connected nodes.
Definition: protocol.h:62
Node is already added.
Definition: protocol.h:60
const UniValue NullUniValue
Definition: univalue.cpp:13
static int count
Definition: tests.c:35
UniValue GetServicesNames(ServiceFlags services)
Returns, given services flags, a list of humanly readable (known) network services.
Definition: util.cpp:867
static RPCHelpMan getaddednodeinfo()
Definition: net.cpp:376
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:133
static RPCHelpMan getconnectioncount()
Definition: net.cpp:41
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:13
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:727
std::string ToString() const
Definition: util.cpp:500
No valid connection manager instance found.
Definition: protocol.h:64
static RPCHelpMan listbanned()
Definition: net.cpp:698
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:55
Information about a peer.
Definition: net.h:840
std::vector< int > vHeightInFlight
Special dictionary with keys that are not literals.
Definition: addrdb.h:20
bool isNull() const
Definition: univalue.h:77
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
CJDNS.
Definition: netaddress.h:61
static RPCHelpMan help()
Definition: server.cpp:133
uint32_t nTime
Definition: protocol.h:398
bool isStr() const
Definition: univalue.h:81
static std::vector< std::string > ToStrings(NetPermissionFlags flags)
Addresses from these networks are not publicly routable on the global Internet.
Definition: netaddress.h:46