Bitcoin Core  0.19.99
P2P Digital Currency
net.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2019 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/system.h>
24 #include <validation.h>
25 #include <version.h>
26 #include <warnings.h>
27 
28 #include <univalue.h>
29 
31 {
32  RPCHelpMan{"getconnectioncount",
33  "\nReturns the number of connections to other nodes.\n",
34  {},
35  RPCResult{
36  "n (numeric) The connection count\n"
37  },
39  HelpExampleCli("getconnectioncount", "")
40  + HelpExampleRpc("getconnectioncount", "")
41  },
42  }.Check(request);
43 
44  if(!g_rpc_node->connman)
45  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
46 
47  return (int)g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
48 }
49 
50 static UniValue ping(const JSONRPCRequest& request)
51 {
52  RPCHelpMan{"ping",
53  "\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
54  "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
55  "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
56  {},
57  RPCResults{},
59  HelpExampleCli("ping", "")
60  + HelpExampleRpc("ping", "")
61  },
62  }.Check(request);
63 
64  if(!g_rpc_node->connman)
65  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
66 
67  // Request that each node send a ping during next message processing pass
68  g_rpc_node->connman->ForEachNode([](CNode* pnode) {
69  pnode->fPingQueued = true;
70  });
71  return NullUniValue;
72 }
73 
74 static UniValue getpeerinfo(const JSONRPCRequest& request)
75 {
76  RPCHelpMan{"getpeerinfo",
77  "\nReturns data about each connected network node as a json array of objects.\n",
78  {},
79  RPCResult{
80  "[\n"
81  " {\n"
82  " \"id\" : n, (numeric) Peer index\n"
83  " \"addr\" : \"host:port\", (string) The IP address and port of the peer\n"
84  " \"addrbind\" : \"ip:port\", (string) Bind address of the connection to the peer\n"
85  " \"addrlocal\" : \"ip:port\", (string) Local address as reported by the peer\n"
86  " \"mapped_as\" : \"mapped_as\", (string) The AS in the BGP route to the peer used for diversifying peer selection\n"
87  " \"services\" : \"xxxxxxxxxxxxxxxx\", (string) The services offered\n"
88  " \"servicesnames\" : [ (json array) the services offered, in human-readable form\n"
89  " \"SERVICE_NAME\", (string) the service name if it is recognised\n"
90  " ...\n"
91  " ],\n"
92  " \"relaytxes\" : true|false, (boolean) Whether peer has asked us to relay transactions to it\n"
93  " \"lastsend\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last send\n"
94  " \"lastrecv\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last receive\n"
95  " \"bytessent\" : n, (numeric) The total bytes sent\n"
96  " \"bytesrecv\" : n, (numeric) The total bytes received\n"
97  " \"conntime\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the connection\n"
98  " \"timeoffset\" : ttt, (numeric) The time offset in seconds\n"
99  " \"pingtime\" : n, (numeric) ping time (if available)\n"
100  " \"minping\" : n, (numeric) minimum observed ping time (if any at all)\n"
101  " \"pingwait\" : n, (numeric) ping wait (if non-zero)\n"
102  " \"version\" : v, (numeric) The peer version, such as 70001\n"
103  " \"subver\" : \"/Satoshi:0.8.5/\", (string) The string version\n"
104  " \"inbound\" : true|false, (boolean) Inbound (true) or Outbound (false)\n"
105  " \"addnode\" : true|false, (boolean) Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n"
106  " \"startingheight\" : n, (numeric) The starting height (block) of the peer\n"
107  " \"banscore\" : n, (numeric) The ban score\n"
108  " \"synced_headers\" : n, (numeric) The last header we have in common with this peer\n"
109  " \"synced_blocks\" : n, (numeric) The last block we have in common with this peer\n"
110  " \"inflight\" : [\n"
111  " n, (numeric) The heights of blocks we're currently asking from this peer\n"
112  " ...\n"
113  " ],\n"
114  " \"whitelisted\" : true|false, (boolean) Whether the peer is whitelisted\n"
115  " \"minfeefilter\" : n, (numeric) The minimum fee rate for transactions this peer accepts\n"
116  " \"bytessent_per_msg\" : {\n"
117  " \"msg\" : n, (numeric) The total bytes sent aggregated by message type\n"
118  " When a message type is not listed in this json object, the bytes sent are 0.\n"
119  " Only known message types can appear as keys in the object.\n"
120  " ...\n"
121  " },\n"
122  " \"bytesrecv_per_msg\" : {\n"
123  " \"msg\" : n, (numeric) The total bytes received aggregated by message type\n"
124  " When a message type is not listed in this json object, the bytes received are 0.\n"
125  " Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'.\n"
126  " ...\n"
127  " }\n"
128  " }\n"
129  " ,...\n"
130  "]\n"
131  },
132  RPCExamples{
133  HelpExampleCli("getpeerinfo", "")
134  + HelpExampleRpc("getpeerinfo", "")
135  },
136  }.Check(request);
137 
138  if(!g_rpc_node->connman)
139  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
140 
141  std::vector<CNodeStats> vstats;
142  g_rpc_node->connman->GetNodeStats(vstats);
143 
145 
146  for (const CNodeStats& stats : vstats) {
148  CNodeStateStats statestats;
149  bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
150  obj.pushKV("id", stats.nodeid);
151  obj.pushKV("addr", stats.addrName);
152  if (!(stats.addrLocal.empty()))
153  obj.pushKV("addrlocal", stats.addrLocal);
154  if (stats.addrBind.IsValid())
155  obj.pushKV("addrbind", stats.addrBind.ToString());
156  if (stats.m_mapped_as != 0) {
157  obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
158  }
159  obj.pushKV("services", strprintf("%016x", stats.nServices));
160  obj.pushKV("servicesnames", GetServicesNames(stats.nServices));
161  obj.pushKV("relaytxes", stats.fRelayTxes);
162  obj.pushKV("lastsend", stats.nLastSend);
163  obj.pushKV("lastrecv", stats.nLastRecv);
164  obj.pushKV("bytessent", stats.nSendBytes);
165  obj.pushKV("bytesrecv", stats.nRecvBytes);
166  obj.pushKV("conntime", stats.nTimeConnected);
167  obj.pushKV("timeoffset", stats.nTimeOffset);
168  if (stats.dPingTime > 0.0)
169  obj.pushKV("pingtime", stats.dPingTime);
170  if (stats.dMinPing < static_cast<double>(std::numeric_limits<int64_t>::max())/1e6)
171  obj.pushKV("minping", stats.dMinPing);
172  if (stats.dPingWait > 0.0)
173  obj.pushKV("pingwait", stats.dPingWait);
174  obj.pushKV("version", stats.nVersion);
175  // Use the sanitized form of subver here, to avoid tricksy remote peers from
176  // corrupting or modifying the JSON output by putting special characters in
177  // their ver message.
178  obj.pushKV("subver", stats.cleanSubVer);
179  obj.pushKV("inbound", stats.fInbound);
180  obj.pushKV("addnode", stats.m_manual_connection);
181  obj.pushKV("startingheight", stats.nStartingHeight);
182  if (fStateStats) {
183  obj.pushKV("banscore", statestats.nMisbehavior);
184  obj.pushKV("synced_headers", statestats.nSyncHeight);
185  obj.pushKV("synced_blocks", statestats.nCommonHeight);
186  UniValue heights(UniValue::VARR);
187  for (const int height : statestats.vHeightInFlight) {
188  heights.push_back(height);
189  }
190  obj.pushKV("inflight", heights);
191  }
192  obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
193  UniValue permissions(UniValue::VARR);
194  for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
195  permissions.push_back(permission);
196  }
197  obj.pushKV("permissions", permissions);
198  obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter));
199 
200  UniValue sendPerMsgCmd(UniValue::VOBJ);
201  for (const auto& i : stats.mapSendBytesPerMsgCmd) {
202  if (i.second > 0)
203  sendPerMsgCmd.pushKV(i.first, i.second);
204  }
205  obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
206 
207  UniValue recvPerMsgCmd(UniValue::VOBJ);
208  for (const auto& i : stats.mapRecvBytesPerMsgCmd) {
209  if (i.second > 0)
210  recvPerMsgCmd.pushKV(i.first, i.second);
211  }
212  obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
213 
214  ret.push_back(obj);
215  }
216 
217  return ret;
218 }
219 
220 static UniValue addnode(const JSONRPCRequest& request)
221 {
222  std::string strCommand;
223  if (!request.params[1].isNull())
224  strCommand = request.params[1].get_str();
225  if (request.fHelp || request.params.size() != 2 ||
226  (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
227  throw std::runtime_error(
228  RPCHelpMan{"addnode",
229  "\nAttempts to add or remove a node from the addnode list.\n"
230  "Or try a connection to a node once.\n"
231  "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
232  "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n",
233  {
234  {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"},
235  {"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"},
236  },
237  RPCResults{},
238  RPCExamples{
239  HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
240  + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
241  },
242  }.ToString());
243 
244  if(!g_rpc_node->connman)
245  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
246 
247  std::string strNode = request.params[0].get_str();
248 
249  if (strCommand == "onetry")
250  {
251  CAddress addr;
252  g_rpc_node->connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), false, false, true);
253  return NullUniValue;
254  }
255 
256  if (strCommand == "add")
257  {
258  if(!g_rpc_node->connman->AddNode(strNode))
259  throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
260  }
261  else if(strCommand == "remove")
262  {
263  if(!g_rpc_node->connman->RemoveAddedNode(strNode))
264  throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
265  }
266 
267  return NullUniValue;
268 }
269 
270 static UniValue disconnectnode(const JSONRPCRequest& request)
271 {
272  RPCHelpMan{"disconnectnode",
273  "\nImmediately disconnects from the specified peer node.\n"
274  "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
275  "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
276  {
277  {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"},
278  {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"},
279  },
280  RPCResults{},
281  RPCExamples{
282  HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
283  + HelpExampleCli("disconnectnode", "\"\" 1")
284  + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
285  + HelpExampleRpc("disconnectnode", "\"\", 1")
286  },
287  }.Check(request);
288 
289  if(!g_rpc_node->connman)
290  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
291 
292  bool success;
293  const UniValue &address_arg = request.params[0];
294  const UniValue &id_arg = request.params[1];
295 
296  if (!address_arg.isNull() && id_arg.isNull()) {
297  /* handle disconnect-by-address */
298  success = g_rpc_node->connman->DisconnectNode(address_arg.get_str());
299  } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
300  /* handle disconnect-by-id */
301  NodeId nodeid = (NodeId) id_arg.get_int64();
302  success = g_rpc_node->connman->DisconnectNode(nodeid);
303  } else {
304  throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
305  }
306 
307  if (!success) {
308  throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
309  }
310 
311  return NullUniValue;
312 }
313 
315 {
316  RPCHelpMan{"getaddednodeinfo",
317  "\nReturns information about the given added node, or all added nodes\n"
318  "(note that onetry addnodes are not listed here)\n",
319  {
320  {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."},
321  },
322  RPCResult{
323  "[\n"
324  " {\n"
325  " \"addednode\" : \"192.168.0.201\", (string) The node IP address or name (as provided to addnode)\n"
326  " \"connected\" : true|false, (boolean) If connected\n"
327  " \"addresses\" : [ (list of objects) Only when connected = true\n"
328  " {\n"
329  " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server IP and port we're connected to\n"
330  " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n"
331  " }\n"
332  " ]\n"
333  " }\n"
334  " ,...\n"
335  "]\n"
336  },
337  RPCExamples{
338  HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
339  + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
340  },
341  }.Check(request);
342 
343  if(!g_rpc_node->connman)
344  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
345 
346  std::vector<AddedNodeInfo> vInfo = g_rpc_node->connman->GetAddedNodeInfo();
347 
348  if (!request.params[0].isNull()) {
349  bool found = false;
350  for (const AddedNodeInfo& info : vInfo) {
351  if (info.strAddedNode == request.params[0].get_str()) {
352  vInfo.assign(1, info);
353  found = true;
354  break;
355  }
356  }
357  if (!found) {
358  throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
359  }
360  }
361 
363 
364  for (const AddedNodeInfo& info : vInfo) {
366  obj.pushKV("addednode", info.strAddedNode);
367  obj.pushKV("connected", info.fConnected);
368  UniValue addresses(UniValue::VARR);
369  if (info.fConnected) {
370  UniValue address(UniValue::VOBJ);
371  address.pushKV("address", info.resolvedAddress.ToString());
372  address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
373  addresses.push_back(address);
374  }
375  obj.pushKV("addresses", addresses);
376  ret.push_back(obj);
377  }
378 
379  return ret;
380 }
381 
382 static UniValue getnettotals(const JSONRPCRequest& request)
383 {
384  RPCHelpMan{"getnettotals",
385  "\nReturns information about network traffic, including bytes in, bytes out,\n"
386  "and current time.\n",
387  {},
388  RPCResult{
389  "{\n"
390  " \"totalbytesrecv\" : n, (numeric) Total bytes received\n"
391  " \"totalbytessent\" : n, (numeric) Total bytes sent\n"
392  " \"timemillis\" : t, (numeric) Current UNIX time in milliseconds\n"
393  " \"uploadtarget\" : \n"
394  " {\n"
395  " \"timeframe\" : n, (numeric) Length of the measuring timeframe in seconds\n"
396  " \"target\" : n, (numeric) Target in bytes\n"
397  " \"target_reached\" : true|false, (boolean) True if target is reached\n"
398  " \"serve_historical_blocks\" : true|false, (boolean) True if serving historical blocks\n"
399  " \"bytes_left_in_cycle\" : t, (numeric) Bytes left in current time cycle\n"
400  " \"time_left_in_cycle\" : t (numeric) Seconds left in current time cycle\n"
401  " }\n"
402  "}\n"
403  },
404  RPCExamples{
405  HelpExampleCli("getnettotals", "")
406  + HelpExampleRpc("getnettotals", "")
407  },
408  }.Check(request);
409  if(!g_rpc_node->connman)
410  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
411 
413  obj.pushKV("totalbytesrecv", g_rpc_node->connman->GetTotalBytesRecv());
414  obj.pushKV("totalbytessent", g_rpc_node->connman->GetTotalBytesSent());
415  obj.pushKV("timemillis", GetTimeMillis());
416 
417  UniValue outboundLimit(UniValue::VOBJ);
418  outboundLimit.pushKV("timeframe", g_rpc_node->connman->GetMaxOutboundTimeframe());
419  outboundLimit.pushKV("target", g_rpc_node->connman->GetMaxOutboundTarget());
420  outboundLimit.pushKV("target_reached", g_rpc_node->connman->OutboundTargetReached(false));
421  outboundLimit.pushKV("serve_historical_blocks", !g_rpc_node->connman->OutboundTargetReached(true));
422  outboundLimit.pushKV("bytes_left_in_cycle", g_rpc_node->connman->GetOutboundTargetBytesLeft());
423  outboundLimit.pushKV("time_left_in_cycle", g_rpc_node->connman->GetMaxOutboundTimeLeftInCycle());
424  obj.pushKV("uploadtarget", outboundLimit);
425  return obj;
426 }
427 
429 {
430  UniValue networks(UniValue::VARR);
431  for(int n=0; n<NET_MAX; ++n)
432  {
433  enum Network network = static_cast<enum Network>(n);
434  if(network == NET_UNROUTABLE || network == NET_INTERNAL)
435  continue;
436  proxyType proxy;
438  GetProxy(network, proxy);
439  obj.pushKV("name", GetNetworkName(network));
440  obj.pushKV("limited", !IsReachable(network));
441  obj.pushKV("reachable", IsReachable(network));
442  obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
443  obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
444  networks.push_back(obj);
445  }
446  return networks;
447 }
448 
449 static UniValue getnetworkinfo(const JSONRPCRequest& request)
450 {
451  RPCHelpMan{"getnetworkinfo",
452  "Returns an object containing various state info regarding P2P networking.\n",
453  {},
454  RPCResult{
455  "{ (json object)\n"
456  " \"version\" : xxxxx, (numeric) the server version\n"
457  " \"subversion\" : \"str\", (string) the server subversion string\n"
458  " \"protocolversion\" : xxxxx, (numeric) the protocol version\n"
459  " \"localservices\" : \"hex\", (string) the services we offer to the network\n"
460  " \"localservicesnames\" : [ (json array) the services we offer to the network, in human-readable form\n"
461  " \"SERVICE_NAME\", (string) the service name\n"
462  " ...\n"
463  " ],\n"
464  " \"localrelay\" : true|false, (boolean) true if transaction relay is requested from peers\n"
465  " \"timeoffset\" : xxxxx, (numeric) the time offset\n"
466  " \"connections\" : xxxxx, (numeric) the number of connections\n"
467  " \"networkactive\" : true|false, (boolean) whether p2p networking is enabled\n"
468  " \"networks\" : [ (json array) information per network\n"
469  " { (json object)\n"
470  " \"name\" : \"str\", (string) network (ipv4, ipv6 or onion)\n"
471  " \"limited\" : true|false, (boolean) is the network limited using -onlynet?\n"
472  " \"reachable\" : true|false, (boolean) is the network reachable?\n"
473  " \"proxy\" : \"str\" (string) (\"host:port\") the proxy that is used for this network, or empty if none\n"
474  " \"proxy_randomize_credentials\" : true|false, (boolean) Whether randomized credentials are used\n"
475  " },\n"
476  " ...\n"
477  " ],\n"
478  " \"relayfee\" : x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
479  " \"incrementalfee\" : x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n"
480  " \"localaddresses\" : [ (json array) list of local addresses\n"
481  " { (json object)\n"
482  " \"address\" : \"xxxx\", (string) network address\n"
483  " \"port\" : xxx, (numeric) network port\n"
484  " \"score\" : xxx (numeric) relative score\n"
485  " },\n"
486  " ...\n"
487  " ],\n"
488  " \"warnings\" : \"str\", (string) any network and blockchain warnings\n"
489  "}\n"
490  },
491  RPCExamples{
492  HelpExampleCli("getnetworkinfo", "")
493  + HelpExampleRpc("getnetworkinfo", "")
494  },
495  }.Check(request);
496 
497  LOCK(cs_main);
499  obj.pushKV("version", CLIENT_VERSION);
500  obj.pushKV("subversion", strSubVersion);
501  obj.pushKV("protocolversion",PROTOCOL_VERSION);
502  if (g_rpc_node->connman) {
503  ServiceFlags services = g_rpc_node->connman->GetLocalServices();
504  obj.pushKV("localservices", strprintf("%016x", services));
505  obj.pushKV("localservicesnames", GetServicesNames(services));
506  }
507  obj.pushKV("localrelay", g_relay_txes);
508  obj.pushKV("timeoffset", GetTimeOffset());
509  if (g_rpc_node->connman) {
510  obj.pushKV("networkactive", g_rpc_node->connman->GetNetworkActive());
511  obj.pushKV("connections", (int)g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
512  }
513  obj.pushKV("networks", GetNetworksInfo());
514  obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
515  obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
516  UniValue localAddresses(UniValue::VARR);
517  {
519  for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
520  {
522  rec.pushKV("address", item.first.ToString());
523  rec.pushKV("port", item.second.nPort);
524  rec.pushKV("score", item.second.nScore);
525  localAddresses.push_back(rec);
526  }
527  }
528  obj.pushKV("localaddresses", localAddresses);
529  obj.pushKV("warnings", GetWarnings(false));
530  return obj;
531 }
532 
533 static UniValue setban(const JSONRPCRequest& request)
534 {
535  const RPCHelpMan help{"setban",
536  "\nAttempts to add or remove an IP/Subnet from the banned list.\n",
537  {
538  {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
539  {"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"},
540  {"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)"},
541  {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
542  },
543  RPCResults{},
544  RPCExamples{
545  HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
546  + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
547  + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
548  },
549  };
550  std::string strCommand;
551  if (!request.params[1].isNull())
552  strCommand = request.params[1].get_str();
553  if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
554  throw std::runtime_error(help.ToString());
555  }
556  if (!g_rpc_node->banman) {
557  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
558  }
559 
560  CSubNet subNet;
561  CNetAddr netAddr;
562  bool isSubnet = false;
563 
564  if (request.params[0].get_str().find('/') != std::string::npos)
565  isSubnet = true;
566 
567  if (!isSubnet) {
568  CNetAddr resolved;
569  LookupHost(request.params[0].get_str(), resolved, false);
570  netAddr = resolved;
571  }
572  else
573  LookupSubNet(request.params[0].get_str(), subNet);
574 
575  if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
576  throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
577 
578  if (strCommand == "add")
579  {
580  if (isSubnet ? g_rpc_node->banman->IsBanned(subNet) : g_rpc_node->banman->IsBanned(netAddr)) {
581  throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
582  }
583 
584  int64_t banTime = 0; //use standard bantime if not specified
585  if (!request.params[2].isNull())
586  banTime = request.params[2].get_int64();
587 
588  bool absolute = false;
589  if (request.params[3].isTrue())
590  absolute = true;
591 
592  if (isSubnet) {
593  g_rpc_node->banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute);
594  if (g_rpc_node->connman) {
595  g_rpc_node->connman->DisconnectNode(subNet);
596  }
597  } else {
598  g_rpc_node->banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
599  if (g_rpc_node->connman) {
600  g_rpc_node->connman->DisconnectNode(netAddr);
601  }
602  }
603  }
604  else if(strCommand == "remove")
605  {
606  if (!( isSubnet ? g_rpc_node->banman->Unban(subNet) : g_rpc_node->banman->Unban(netAddr) )) {
607  throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned.");
608  }
609  }
610  return NullUniValue;
611 }
612 
613 static UniValue listbanned(const JSONRPCRequest& request)
614 {
615  RPCHelpMan{"listbanned",
616  "\nList all banned IPs/Subnets.\n",
617  {},
618  RPCResults{},
619  RPCExamples{
620  HelpExampleCli("listbanned", "")
621  + HelpExampleRpc("listbanned", "")
622  },
623  }.Check(request);
624 
625  if(!g_rpc_node->banman) {
626  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
627  }
628 
629  banmap_t banMap;
630  g_rpc_node->banman->GetBanned(banMap);
631 
632  UniValue bannedAddresses(UniValue::VARR);
633  for (const auto& entry : banMap)
634  {
635  const CBanEntry& banEntry = entry.second;
637  rec.pushKV("address", entry.first.ToString());
638  rec.pushKV("banned_until", banEntry.nBanUntil);
639  rec.pushKV("ban_created", banEntry.nCreateTime);
640  rec.pushKV("ban_reason", banEntry.banReasonToString());
641 
642  bannedAddresses.push_back(rec);
643  }
644 
645  return bannedAddresses;
646 }
647 
648 static UniValue clearbanned(const JSONRPCRequest& request)
649 {
650  RPCHelpMan{"clearbanned",
651  "\nClear all banned IPs.\n",
652  {},
653  RPCResults{},
654  RPCExamples{
655  HelpExampleCli("clearbanned", "")
656  + HelpExampleRpc("clearbanned", "")
657  },
658  }.Check(request);
659  if (!g_rpc_node->banman) {
660  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
661  }
662 
663  g_rpc_node->banman->ClearBanned();
664 
665  return NullUniValue;
666 }
667 
669 {
670  RPCHelpMan{"setnetworkactive",
671  "\nDisable/enable all p2p network activity.\n",
672  {
673  {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
674  },
675  RPCResults{},
676  RPCExamples{""},
677  }.Check(request);
678 
679  if (!g_rpc_node->connman) {
680  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
681  }
682 
683  g_rpc_node->connman->SetNetworkActive(request.params[0].get_bool());
684 
685  return g_rpc_node->connman->GetNetworkActive();
686 }
687 
689 {
690  RPCHelpMan{"getnodeaddresses",
691  "\nReturn known addresses which can potentially be used to find new nodes in the network\n",
692  {
693  {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + std::to_string(ADDRMAN_GETADDR_MAX) + " or " + std::to_string(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."},
694  },
695  RPCResult{
696  "[\n"
697  " {\n"
698  " \"time\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of when the node was last seen\n"
699  " \"services\" : n, (numeric) The services offered\n"
700  " \"address\" : \"host\", (string) The address of the node\n"
701  " \"port\" : n (numeric) The port of the node\n"
702  " }\n"
703  " ,....\n"
704  "]\n"
705  },
706  RPCExamples{
707  HelpExampleCli("getnodeaddresses", "8")
708  + HelpExampleRpc("getnodeaddresses", "8")
709  },
710  }.Check(request);
711  if (!g_rpc_node->connman) {
712  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
713  }
714 
715  int count = 1;
716  if (!request.params[0].isNull()) {
717  count = request.params[0].get_int();
718  if (count <= 0) {
719  throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
720  }
721  }
722  // returns a shuffled list of CAddress
723  std::vector<CAddress> vAddr = g_rpc_node->connman->GetAddresses();
725 
726  int address_return_count = std::min<int>(count, vAddr.size());
727  for (int i = 0; i < address_return_count; ++i) {
729  const CAddress& addr = vAddr[i];
730  obj.pushKV("time", (int)addr.nTime);
731  obj.pushKV("services", (uint64_t)addr.nServices);
732  obj.pushKV("address", addr.ToStringIP());
733  obj.pushKV("port", addr.GetPort());
734  ret.push_back(obj);
735  }
736  return ret;
737 }
738 
739 // clang-format off
740 static const CRPCCommand commands[] =
741 { // category name actor (function) argNames
742  // --------------------- ------------------------ ----------------------- ----------
743  { "network", "getconnectioncount", &getconnectioncount, {} },
744  { "network", "ping", &ping, {} },
745  { "network", "getpeerinfo", &getpeerinfo, {} },
746  { "network", "addnode", &addnode, {"node","command"} },
747  { "network", "disconnectnode", &disconnectnode, {"address", "nodeid"} },
748  { "network", "getaddednodeinfo", &getaddednodeinfo, {"node"} },
749  { "network", "getnettotals", &getnettotals, {} },
750  { "network", "getnetworkinfo", &getnetworkinfo, {} },
751  { "network", "setban", &setban, {"subnet", "command", "bantime", "absolute"} },
752  { "network", "listbanned", &listbanned, {} },
753  { "network", "clearbanned", &clearbanned, {} },
754  { "network", "setnetworkactive", &setnetworkactive, {"state"} },
755  { "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
756 };
757 // clang-format on
758 
760 {
761  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
762  t.appendCommand(commands[vcidx].name, &commands[vcidx]);
763 }
static UniValue setnetworkactive(const JSONRPCRequest &request)
Definition: net.cpp:668
unsigned short GetPort() const
Definition: netaddress.cpp:661
Node has not been added before.
Definition: protocol.h:61
static UniValue clearbanned(const JSONRPCRequest &request)
Definition: net.cpp:648
ServiceFlags
nServices flags
Definition: protocol.h:239
Bitcoin RPC command dispatcher.
Definition: server.h:119
bool get_bool() const
Required arg.
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:54
std::unique_ptr< BanMan > banman
Definition: context.h:35
static UniValue getnettotals(const JSONRPCRequest &request)
Definition: net.cpp:382
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats)
Get statistics from node state.
static UniValue getaddednodeinfo(const JSONRPCRequest &request)
Definition: net.cpp:314
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:16
void RegisterNetRPCCommands(CRPCTable &t)
Register P2P networking RPC commands.
Definition: net.cpp:759
static UniValue disconnectnode(const JSONRPCRequest &request)
Definition: net.cpp:270
#define ARRAYLEN(array)
Utilities for converting data from/to strings.
Definition: strencodings.h:19
static UniValue getconnectioncount(const JSONRPCRequest &request)
Definition: net.cpp:30
UniValue ValueFromAmount(const CAmount &amount)
Definition: core_write.cpp:18
static UniValue GetNetworksInfo()
Definition: net.cpp:428
NodeContext * g_rpc_node
Pointer to node state that needs to be declared as a global to be accessible RPC methods.
static UniValue ping(const JSONRPCRequest &request)
Definition: net.cpp:50
const std::string & get_str() const
const std::string CURRENCY_UNIT
Definition: feerate.cpp:10
bool isStr() const
Definition: univalue.h:81
int64_t get_int64() const
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are: ...
Definition: timedata.cpp:29
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:259
static UniValue listbanned(const JSONRPCRequest &request)
Definition: net.cpp:613
std::string banReasonToString() const
Definition: addrdb.h:62
int64_t nCreateTime
Definition: addrdb.h:32
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:823
RecursiveMutex cs_mapLocalHost
Definition: net.cpp:88
bool IsValid() const
Definition: netaddress.cpp:248
static UniValue setban(const JSONRPCRequest &request)
Definition: net.cpp:533
static const CRPCCommand commands[]
Definition: net.cpp:740
std::string name
Definition: server.h:110
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:51
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
std::unique_ptr< CConnman > connman
Definition: context.h:32
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:127
UniValue params
Definition: request.h:32
std::string ToStringIP() const
Definition: netaddress.cpp:328
#define LOCK(cs)
Definition: sync.h:179
static UniValue getnetworkinfo(const JSONRPCRequest &request)
Definition: net.cpp:449
bool g_relay_txes
Definition: net.cpp:87
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:117
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: validation.cpp:106
A CService with information about it as peer.
Definition: protocol.h:318
Network
Definition: netaddress.h:19
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
int64_t NodeId
Definition: net.h:93
static UniValue getnodeaddresses(const JSONRPCRequest &request)
Definition: net.cpp:688
int get_int() const
UniValue help(const JSONRPCRequest &jsonRequest)
Definition: server.cpp:130
Invalid IP/Subnet.
Definition: protocol.h:63
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
Definition: net.cpp:91
bool isNull() const
Definition: univalue.h:77
bool isTrue() const
Definition: univalue.h:78
CFeeRate incrementalRelayFee
Definition: settings.cpp:12
const std::string NET_MESSAGE_COMMAND_OTHER
Definition: net.cpp:78
int64_t nBanUntil
Definition: addrdb.h:33
Database error.
Definition: protocol.h:44
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:31
bool fHelp
Definition: request.h:33
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:151
bool IsValid() const
Definition: netaddress.cpp:878
#define ADDRMAN_GETADDR_MAX
the maximum number of nodes to return in a getaddr call
Definition: addrman.h:161
std::atomic< bool > fPingQueued
Definition: net.h:844
unsigned int nTime
Definition: protocol.h:350
bool IsReachable(enum Network net)
Definition: net.cpp:255
ServiceFlags nServices
Definition: protocol.h:347
CService proxy
Definition: netbase.h:36
bool IsValid() const
Definition: netbase.h:34
static UniValue getpeerinfo(const JSONRPCRequest &request)
Definition: net.cpp:74
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12
std::string ToStringIPPort() const
Definition: netaddress.cpp:736
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:45
std::string GetWarnings(bool verbose)
Format a string that describes several potential problems detected by the core.
Definition: warnings.cpp:41
static UniValue addnode(const JSONRPCRequest &request)
Definition: net.cpp:220
UniValue GetServicesNames(ServiceFlags services)
Returns, given services flags, a list of humanly readable (known) network services.
Definition: util.cpp:738
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:112
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:13
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:719
No valid connection manager instance found.
Definition: protocol.h:64
size_t size() const
Definition: univalue.h:68
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:53
Information about a peer.
Definition: net.h:707
std::vector< int > vHeightInFlight
Definition: addrdb.h:27
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:41
#define ADDRMAN_GETADDR_MAX_PCT
the maximum percentage of nodes to return in a getaddr call
Definition: addrman.h:158
static std::vector< std::string > ToStrings(NetPermissionFlags flags)