Bitcoin ABC  0.22.13
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 <config.h>
10 #include <core_io.h>
11 #include <net.h>
12 #include <net_permissions.h>
13 #include <net_processing.h>
14 #include <net_types.h> // For banmap_t
15 #include <netbase.h>
16 #include <network.h>
17 #include <node/context.h>
18 #include <policy/settings.h>
19 #include <rpc/blockchain.h>
20 #include <rpc/protocol.h>
21 #include <rpc/util.h>
22 #include <sync.h>
23 #include <timedata.h>
24 #include <util/strencodings.h>
25 #include <util/string.h>
26 #include <util/system.h>
27 #include <validation.h>
28 #include <version.h>
29 #include <warnings.h>
30 
31 #include <univalue.h>
32 
33 static UniValue getconnectioncount(const Config &config,
34  const JSONRPCRequest &request) {
35  RPCHelpMan{
36  "getconnectioncount",
37  "Returns the number of connections to other nodes.\n",
38  {},
39  RPCResult{RPCResult::Type::NUM, "", "The connection count"},
40  RPCExamples{HelpExampleCli("getconnectioncount", "") +
41  HelpExampleRpc("getconnectioncount", "")},
42  }
43  .Check(request);
44 
45  NodeContext &node = EnsureNodeContext(request.context);
46  if (!node.connman) {
47  throw JSONRPCError(
49  "Error: Peer-to-peer functionality missing or disabled");
50  }
51 
52  return int(node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
53 }
54 
55 static UniValue ping(const Config &config, const JSONRPCRequest &request) {
56  RPCHelpMan{
57  "ping",
58  "Requests that a ping be sent to all other nodes, to measure ping "
59  "time.\n"
60  "Results provided in getpeerinfo, pingtime and pingwait fields are "
61  "decimal seconds.\n"
62  "Ping command is handled in queue with all other commands, so it "
63  "measures processing backlog, not just network ping.\n",
64  {},
66  RPCExamples{HelpExampleCli("ping", "") + HelpExampleRpc("ping", "")},
67  }
68  .Check(request);
69 
70  NodeContext &node = EnsureNodeContext(request.context);
71  if (!node.connman) {
72  throw JSONRPCError(
74  "Error: Peer-to-peer functionality missing or disabled");
75  }
76 
77  // Request that each node send a ping during next message processing pass
78  node.connman->ForEachNode([](CNode *pnode) { pnode->fPingQueued = true; });
79  return NullUniValue;
80 }
81 
82 static UniValue getpeerinfo(const Config &config,
83  const JSONRPCRequest &request) {
84  RPCHelpMan{
85  "getpeerinfo",
86  "Returns data about each connected network node as a json array of "
87  "objects.\n",
88  {},
89  RPCResult{
91  "",
92  "",
93  {{
95  "",
96  "",
97  {{
98  {RPCResult::Type::NUM, "id", "Peer index"},
99  {RPCResult::Type::STR, "addr",
100  "(host:port) The IP address and port of the peer"},
101  {RPCResult::Type::STR, "addrbind",
102  "(ip:port) Bind address of the connection to the peer"},
103  {RPCResult::Type::STR, "addrlocal",
104  "(ip:port) Local address as reported by the peer"},
105  {RPCResult::Type::NUM, "mapped_as",
106  "The AS in the BGP route to the peer used for "
107  "diversifying\n"
108  "peer selection (only available if the asmap config flag "
109  "is set)\n"},
110  {RPCResult::Type::STR_HEX, "services",
111  "The services offered"},
113  "servicesnames",
114  "the services offered, in human-readable form",
115  {{RPCResult::Type::STR, "SERVICE_NAME",
116  "the service name if it is recognised"}}},
117  {RPCResult::Type::BOOL, "relaytxes",
118  "Whether peer has asked us to relay transactions to it"},
119  {RPCResult::Type::NUM_TIME, "lastsend",
120  "The " + UNIX_EPOCH_TIME + " of the last send"},
121  {RPCResult::Type::NUM_TIME, "lastrecv",
122  "The " + UNIX_EPOCH_TIME + " of the last receive"},
123  {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
124  {RPCResult::Type::NUM, "bytesrecv",
125  "The total bytes received"},
126  {RPCResult::Type::NUM_TIME, "conntime",
127  "The " + UNIX_EPOCH_TIME + " of the connection"},
128  {RPCResult::Type::NUM, "timeoffset",
129  "The time offset in seconds"},
130  {RPCResult::Type::NUM, "pingtime",
131  "ping time (if available)"},
132  {RPCResult::Type::NUM, "minping",
133  "minimum observed ping time (if any at all)"},
134  {RPCResult::Type::NUM, "pingwait",
135  "ping wait (if non-zero)"},
136  {RPCResult::Type::NUM, "version",
137  "The peer version, such as 70001"},
138  {RPCResult::Type::STR, "subver", "The string version"},
139  {RPCResult::Type::BOOL, "inbound",
140  "Inbound (true) or Outbound (false)"},
141  {RPCResult::Type::BOOL, "addnode",
142  "Whether connection was due to addnode/-connect or if it "
143  "was an automatic/inbound connection"},
144  {RPCResult::Type::NUM, "startingheight",
145  "The starting height (block) of the peer"},
146  {RPCResult::Type::NUM, "banscore",
147  "The ban score (DEPRECATED, returned only if config "
148  "option -deprecatedrpc=banscore is passed)"},
149  {RPCResult::Type::NUM, "synced_headers",
150  "The last header we have in common with this peer"},
151  {RPCResult::Type::NUM, "synced_blocks",
152  "The last block we have in common with this peer"},
154  "inflight",
155  "",
156  {
157  {RPCResult::Type::NUM, "n",
158  "The heights of blocks we're currently asking from "
159  "this peer"},
160  }},
161  {RPCResult::Type::BOOL, "whitelisted",
162  "Whether the peer is whitelisted"},
163  {RPCResult::Type::NUM, "minfeefilter",
164  "The minimum fee rate for transactions this peer accepts"},
166  "bytessent_per_msg",
167  "",
168  {{RPCResult::Type::NUM, "msg",
169  "The total bytes sent aggregated by message type\n"
170  "When a message type is not listed in this json object, "
171  "the bytes sent are 0.\n"
172  "Only known message types can appear as keys in the "
173  "object."}}},
175  "bytesrecv_per_msg",
176  "",
177  {{RPCResult::Type::NUM, "msg",
178  "The total bytes received aggregated by message type\n"
179  "When a message type is not listed in this json object, "
180  "the bytes received are 0.\n"
181  "Only known message types can appear as keys in the "
182  "object and all bytes received of unknown message types "
183  "are listed under '" +
184  NET_MESSAGE_COMMAND_OTHER + "'."}}},
185  }},
186  }},
187  },
188  RPCExamples{HelpExampleCli("getpeerinfo", "") +
189  HelpExampleRpc("getpeerinfo", "")},
190  }
191  .Check(request);
192 
193  NodeContext &node = EnsureNodeContext(request.context);
194  if (!node.connman) {
195  throw JSONRPCError(
197  "Error: Peer-to-peer functionality missing or disabled");
198  }
199 
200  std::vector<CNodeStats> vstats;
201  node.connman->GetNodeStats(vstats);
202 
204 
205  for (const CNodeStats &stats : vstats) {
207  CNodeStateStats statestats;
208  bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
209  obj.pushKV("id", stats.nodeid);
210  obj.pushKV("addr", stats.addrName);
211  if (!(stats.addrLocal.empty())) {
212  obj.pushKV("addrlocal", stats.addrLocal);
213  }
214  if (stats.addrBind.IsValid()) {
215  obj.pushKV("addrbind", stats.addrBind.ToString());
216  }
217  if (stats.m_mapped_as != 0) {
218  obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
219  }
220  obj.pushKV("services", strprintf("%016x", stats.nServices));
221  obj.pushKV("servicesnames", GetServicesNames(stats.nServices));
222  obj.pushKV("relaytxes", stats.fRelayTxes);
223  obj.pushKV("lastsend", stats.nLastSend);
224  obj.pushKV("lastrecv", stats.nLastRecv);
225  obj.pushKV("bytessent", stats.nSendBytes);
226  obj.pushKV("bytesrecv", stats.nRecvBytes);
227  obj.pushKV("conntime", stats.nTimeConnected);
228  obj.pushKV("timeoffset", stats.nTimeOffset);
229  if (stats.m_ping_usec > 0) {
230  obj.pushKV("pingtime", double(stats.m_ping_usec) / 1e6);
231  }
232  if (stats.m_min_ping_usec < std::numeric_limits<int64_t>::max()) {
233  obj.pushKV("minping", double(stats.m_min_ping_usec) / 1e6);
234  }
235  if (stats.m_ping_wait_usec > 0) {
236  obj.pushKV("pingwait", double(stats.m_ping_wait_usec) / 1e6);
237  }
238  obj.pushKV("version", stats.nVersion);
239  // Use the sanitized form of subver here, to avoid tricksy remote peers
240  // from corrupting or modifying the JSON output by putting special
241  // characters in their ver message.
242  obj.pushKV("subver", stats.cleanSubVer);
243  obj.pushKV("inbound", stats.fInbound);
244  obj.pushKV("addnode", stats.m_manual_connection);
245  obj.pushKV("startingheight", stats.nStartingHeight);
246  if (fStateStats) {
247  if (IsDeprecatedRPCEnabled(gArgs, "banscore")) {
248  // banscore is deprecated in v0.22.11 for removal in v0.23
249  obj.pushKV("banscore", statestats.m_misbehavior_score);
250  }
251  obj.pushKV("synced_headers", statestats.nSyncHeight);
252  obj.pushKV("synced_blocks", statestats.nCommonHeight);
253  UniValue heights(UniValue::VARR);
254  for (const int height : statestats.vHeightInFlight) {
255  heights.push_back(height);
256  }
257  obj.pushKV("inflight", heights);
258  }
259  obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
260  UniValue permissions(UniValue::VARR);
261  for (const auto &permission :
262  NetPermissions::ToStrings(stats.m_permissionFlags)) {
263  permissions.push_back(permission);
264  }
265  obj.pushKV("permissions", permissions);
266  obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter));
267 
268  UniValue sendPerMsgCmd(UniValue::VOBJ);
269  for (const auto &i : stats.mapSendBytesPerMsgCmd) {
270  if (i.second > 0) {
271  sendPerMsgCmd.pushKV(i.first, i.second);
272  }
273  }
274  obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
275 
276  UniValue recvPerMsgCmd(UniValue::VOBJ);
277  for (const auto &i : stats.mapRecvBytesPerMsgCmd) {
278  if (i.second > 0) {
279  recvPerMsgCmd.pushKV(i.first, i.second);
280  }
281  }
282  obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
283 
284  ret.push_back(obj);
285  }
286 
287  return ret;
288 }
289 
290 static UniValue addnode(const Config &config, const JSONRPCRequest &request) {
291  std::string strCommand;
292  if (!request.params[1].isNull()) {
293  strCommand = request.params[1].get_str();
294  }
295 
296  if (request.fHelp || request.params.size() != 2 ||
297  (strCommand != "onetry" && strCommand != "add" &&
298  strCommand != "remove")) {
299  throw std::runtime_error(RPCHelpMan{
300  "addnode",
301  "Attempts to add or remove a node from the addnode list.\n"
302  "Or try a connection to a node once.\n"
303  "Nodes added using addnode (or -connect) are protected from "
304  "DoS disconnection and are not required to be\n"
305  "full nodes as other outbound peers are (though such peers "
306  "will not be synced from).\n",
307  {
309  "The node (see getpeerinfo for nodes)"},
311  "'add' to add a node to the list, 'remove' to remove a "
312  "node from the list, 'onetry' to try a connection to the "
313  "node once"},
314  },
316  RPCExamples{
317  HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"") +
318  HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")},
319  }
320  .ToString());
321  }
322 
323  NodeContext &node = EnsureNodeContext(request.context);
324  if (!node.connman) {
325  throw JSONRPCError(
327  "Error: Peer-to-peer functionality missing or disabled");
328  }
329 
330  std::string strNode = request.params[0].get_str();
331 
332  if (strCommand == "onetry") {
333  CAddress addr;
334  node.connman->OpenNetworkConnection(
335  addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL);
336  return NullUniValue;
337  }
338 
339  if ((strCommand == "add") && (!node.connman->AddNode(strNode))) {
341  "Error: Node already added");
342  } else if ((strCommand == "remove") &&
343  (!node.connman->RemoveAddedNode(strNode))) {
345  "Error: Node has not been added.");
346  }
347 
348  return NullUniValue;
349 }
350 
351 static UniValue disconnectnode(const Config &config,
352  const JSONRPCRequest &request) {
353  RPCHelpMan{
354  "disconnectnode",
355  "Immediately disconnects from the specified peer node.\n"
356  "\nStrictly one out of 'address' and 'nodeid' can be provided to "
357  "identify the node.\n"
358  "\nTo disconnect by nodeid, either set 'address' to the empty string, "
359  "or call using the named 'nodeid' argument only.\n",
360  {
361  {"address", RPCArg::Type::STR,
362  /* default */ "fallback to nodeid",
363  "The IP address/port of the node"},
364  {"nodeid", RPCArg::Type::NUM,
365  /* default */ "fallback to address",
366  "The node ID (see getpeerinfo for node IDs)"},
367  },
369  RPCExamples{HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"") +
370  HelpExampleCli("disconnectnode", "\"\" 1") +
371  HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") +
372  HelpExampleRpc("disconnectnode", "\"\", 1")},
373  }
374  .Check(request);
375 
376  NodeContext &node = EnsureNodeContext(request.context);
377  if (!node.connman) {
378  throw JSONRPCError(
380  "Error: Peer-to-peer functionality missing or disabled");
381  }
382 
383  bool success;
384  const UniValue &address_arg = request.params[0];
385  const UniValue &id_arg = request.params[1];
386 
387  if (!address_arg.isNull() && id_arg.isNull()) {
388  /* handle disconnect-by-address */
389  success = node.connman->DisconnectNode(address_arg.get_str());
390  } else if (!id_arg.isNull() &&
391  (address_arg.isNull() ||
392  (address_arg.isStr() && address_arg.get_str().empty()))) {
393  /* handle disconnect-by-id */
394  NodeId nodeid = (NodeId)id_arg.get_int64();
395  success = node.connman->DisconnectNode(nodeid);
396  } else {
397  throw JSONRPCError(
399  "Only one of address and nodeid should be provided.");
400  }
401 
402  if (!success) {
404  "Node not found in connected nodes");
405  }
406 
407  return NullUniValue;
408 }
409 
410 static UniValue getaddednodeinfo(const Config &config,
411  const JSONRPCRequest &request) {
412  RPCHelpMan{
413  "getaddednodeinfo",
414  "Returns information about the given added node, or all added nodes\n"
415  "(note that onetry addnodes are not listed here)\n",
416  {
417  {"node", RPCArg::Type::STR, /* default */ "all nodes",
418  "If provided, return information about this specific node, "
419  "otherwise all nodes are returned."},
420  },
421  RPCResult{
423  "",
424  "",
425  {
427  "",
428  "",
429  {
430  {RPCResult::Type::STR, "addednode",
431  "The node IP address or name (as provided to addnode)"},
432  {RPCResult::Type::BOOL, "connected", "If connected"},
434  "addresses",
435  "Only when connected = true",
436  {
438  "",
439  "",
440  {
441  {RPCResult::Type::STR, "address",
442  "The bitcoin server IP and port we're "
443  "connected to"},
444  {RPCResult::Type::STR, "connected",
445  "connection, inbound or outbound"},
446  }},
447  }},
448  }},
449  }},
450  RPCExamples{HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") +
451  HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")},
452  }
453  .Check(request);
454 
455  NodeContext &node = EnsureNodeContext(request.context);
456  if (!node.connman) {
457  throw JSONRPCError(
459  "Error: Peer-to-peer functionality missing or disabled");
460  }
461 
462  std::vector<AddedNodeInfo> vInfo = node.connman->GetAddedNodeInfo();
463 
464  if (!request.params[0].isNull()) {
465  bool found = false;
466  for (const AddedNodeInfo &info : vInfo) {
467  if (info.strAddedNode == request.params[0].get_str()) {
468  vInfo.assign(1, info);
469  found = true;
470  break;
471  }
472  }
473  if (!found) {
475  "Error: Node has not been added.");
476  }
477  }
478 
480 
481  for (const AddedNodeInfo &info : vInfo) {
483  obj.pushKV("addednode", info.strAddedNode);
484  obj.pushKV("connected", info.fConnected);
485  UniValue addresses(UniValue::VARR);
486  if (info.fConnected) {
487  UniValue address(UniValue::VOBJ);
488  address.pushKV("address", info.resolvedAddress.ToString());
489  address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
490  addresses.push_back(address);
491  }
492  obj.pushKV("addresses", addresses);
493  ret.push_back(obj);
494  }
495 
496  return ret;
497 }
498 
499 static UniValue getnettotals(const Config &config,
500  const JSONRPCRequest &request) {
501  RPCHelpMan{
502  "getnettotals",
503  "Returns information about network traffic, including bytes in, "
504  "bytes out,\n"
505  "and current time.\n",
506  {},
507  RPCResult{
509  "",
510  "",
511  {
512  {RPCResult::Type::NUM, "totalbytesrecv",
513  "Total bytes received"},
514  {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
515  {RPCResult::Type::NUM_TIME, "timemillis",
516  "Current UNIX time in milliseconds"},
518  "uploadtarget",
519  "",
520  {
521  {RPCResult::Type::NUM, "timeframe",
522  "Length of the measuring timeframe in seconds"},
523  {RPCResult::Type::NUM, "target", "Target in bytes"},
524  {RPCResult::Type::BOOL, "target_reached",
525  "True if target is reached"},
526  {RPCResult::Type::BOOL, "serve_historical_blocks",
527  "True if serving historical blocks"},
528  {RPCResult::Type::NUM, "bytes_left_in_cycle",
529  "Bytes left in current time cycle"},
530  {RPCResult::Type::NUM, "time_left_in_cycle",
531  "Seconds left in current time cycle"},
532  }},
533  }},
534  RPCExamples{HelpExampleCli("getnettotals", "") +
535  HelpExampleRpc("getnettotals", "")},
536  }
537  .Check(request);
538 
539  NodeContext &node = EnsureNodeContext(request.context);
540  if (!node.connman) {
541  throw JSONRPCError(
543  "Error: Peer-to-peer functionality missing or disabled");
544  }
545 
547  obj.pushKV("totalbytesrecv", node.connman->GetTotalBytesRecv());
548  obj.pushKV("totalbytessent", node.connman->GetTotalBytesSent());
549  obj.pushKV("timemillis", GetTimeMillis());
550 
551  UniValue outboundLimit(UniValue::VOBJ);
552  outboundLimit.pushKV("timeframe", node.connman->GetMaxOutboundTimeframe());
553  outboundLimit.pushKV("target", node.connman->GetMaxOutboundTarget());
554  outboundLimit.pushKV("target_reached",
555  node.connman->OutboundTargetReached(false));
556  outboundLimit.pushKV("serve_historical_blocks",
557  !node.connman->OutboundTargetReached(true));
558  outboundLimit.pushKV("bytes_left_in_cycle",
559  node.connman->GetOutboundTargetBytesLeft());
560  outboundLimit.pushKV("time_left_in_cycle",
561  node.connman->GetMaxOutboundTimeLeftInCycle());
562  obj.pushKV("uploadtarget", outboundLimit);
563  return obj;
564 }
565 
567  UniValue networks(UniValue::VARR);
568  for (int n = 0; n < NET_MAX; ++n) {
569  enum Network network = static_cast<enum Network>(n);
570  if (network == NET_UNROUTABLE || network == NET_INTERNAL) {
571  continue;
572  }
573  proxyType proxy;
575  GetProxy(network, proxy);
576  obj.pushKV("name", GetNetworkName(network));
577  obj.pushKV("limited", !IsReachable(network));
578  obj.pushKV("reachable", IsReachable(network));
579  obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort()
580  : std::string());
581  obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
582  networks.push_back(obj);
583  }
584  return networks;
585 }
586 
587 static UniValue getnetworkinfo(const Config &config,
588  const JSONRPCRequest &request) {
589  RPCHelpMan{
590  "getnetworkinfo",
591  "Returns an object containing various state info regarding P2P "
592  "networking.\n",
593  {},
594  RPCResult{
596  "",
597  "",
598  {
599  {RPCResult::Type::NUM, "version", "the server version"},
600  {RPCResult::Type::STR, "subversion",
601  "the server subversion string"},
602  {RPCResult::Type::NUM, "protocolversion",
603  "the protocol version"},
604  {RPCResult::Type::STR_HEX, "localservices",
605  "the services we offer to the network"},
607  "localservicesnames",
608  "the services we offer to the network, in human-readable form",
609  {
610  {RPCResult::Type::STR, "SERVICE_NAME", "the service name"},
611  }},
612  {RPCResult::Type::BOOL, "localrelay",
613  "true if transaction relay is requested from peers"},
614  {RPCResult::Type::NUM, "timeoffset", "the time offset"},
615  {RPCResult::Type::NUM, "connections",
616  "the number of connections"},
617  {RPCResult::Type::BOOL, "networkactive",
618  "whether p2p networking is enabled"},
620  "networks",
621  "information per network",
622  {
624  "",
625  "",
626  {
627  {RPCResult::Type::STR, "name",
628  "network (ipv4, ipv6 or onion)"},
629  {RPCResult::Type::BOOL, "limited",
630  "is the network limited using -onlynet?"},
631  {RPCResult::Type::BOOL, "reachable",
632  "is the network reachable?"},
633  {RPCResult::Type::STR, "proxy",
634  "(\"host:port\") the proxy that is used for this "
635  "network, or empty if none"},
636  {RPCResult::Type::BOOL, "proxy_randomize_credentials",
637  "Whether randomized credentials are used"},
638  }},
639  }},
640  {RPCResult::Type::NUM, "relayfee",
641  "minimum relay fee for transactions in " + CURRENCY_UNIT +
642  "/kB"},
643  {RPCResult::Type::NUM, "excessutxocharge",
644  "minimum charge for excess utxos in " + CURRENCY_UNIT},
646  "localaddresses",
647  "list of local addresses",
648  {
650  "",
651  "",
652  {
653  {RPCResult::Type::STR, "address", "network address"},
654  {RPCResult::Type::NUM, "port", "network port"},
655  {RPCResult::Type::NUM, "score", "relative score"},
656  }},
657  }},
658  {RPCResult::Type::STR, "warnings",
659  "any network and blockchain warnings"},
660  }},
661  RPCExamples{HelpExampleCli("getnetworkinfo", "") +
662  HelpExampleRpc("getnetworkinfo", "")},
663  }
664  .Check(request);
665 
666  LOCK(cs_main);
668  obj.pushKV("version", CLIENT_VERSION);
669  obj.pushKV("subversion", userAgent(config));
670  obj.pushKV("protocolversion", PROTOCOL_VERSION);
671  NodeContext &node = EnsureNodeContext(request.context);
672  if (node.connman) {
673  ServiceFlags services = node.connman->GetLocalServices();
674  obj.pushKV("localservices", strprintf("%016x", services));
675  obj.pushKV("localservicesnames", GetServicesNames(services));
676  }
677  obj.pushKV("localrelay", g_relay_txes);
678  obj.pushKV("timeoffset", GetTimeOffset());
679  if (node.connman) {
680  obj.pushKV("networkactive", node.connman->GetNetworkActive());
681  obj.pushKV("connections",
682  int(node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
683  }
684  obj.pushKV("networks", GetNetworksInfo());
685  obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
686  obj.pushKV("excessutxocharge",
688  UniValue localAddresses(UniValue::VARR);
689  {
691  for (const std::pair<const CNetAddr, LocalServiceInfo> &item :
692  mapLocalHost) {
694  rec.pushKV("address", item.first.ToString());
695  rec.pushKV("port", item.second.nPort);
696  rec.pushKV("score", item.second.nScore);
697  localAddresses.push_back(rec);
698  }
699  }
700  obj.pushKV("localaddresses", localAddresses);
701  obj.pushKV("warnings", GetWarnings(false));
702  return obj;
703 }
704 
705 static UniValue setban(const Config &config, const JSONRPCRequest &request) {
706  const RPCHelpMan help{
707  "setban",
708  "Attempts to add or remove an IP/Subnet from the banned list.\n",
709  {
711  "The IP/Subnet (see getpeerinfo for nodes IP) with an optional "
712  "netmask (default is /32 = single IP)"},
714  "'add' to add an IP/Subnet to the list, 'remove' to remove an "
715  "IP/Subnet from the list"},
716  {"bantime", RPCArg::Type::NUM, /* default */ "0",
717  "time in seconds how long (or until when if [absolute] is set) "
718  "the IP is banned (0 or empty means using the default time of 24h "
719  "which can also be overwritten by the -bantime startup argument)"},
720  {"absolute", RPCArg::Type::BOOL, /* default */ "false",
721  "If set, the bantime must be an absolute timestamp expressed in " +
723  },
725  RPCExamples{
726  HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") +
727  HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") +
728  HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")},
729  };
730 
731  std::string strCommand;
732  if (!request.params[1].isNull()) {
733  strCommand = request.params[1].get_str();
734  }
735 
736  if (request.fHelp || !help.IsValidNumArgs(request.params.size()) ||
737  (strCommand != "add" && strCommand != "remove")) {
738  throw std::runtime_error(help.ToString());
739  }
740 
741  NodeContext &node = EnsureNodeContext(request.context);
742  if (!node.banman) {
744  "Error: Ban database not loaded");
745  }
746 
747  CSubNet subNet;
748  CNetAddr netAddr;
749  bool isSubnet = false;
750 
751  if (request.params[0].get_str().find('/') != std::string::npos) {
752  isSubnet = true;
753  }
754 
755  if (!isSubnet) {
756  CNetAddr resolved;
757  LookupHost(request.params[0].get_str(), resolved, false);
758  netAddr = resolved;
759  } else {
760  LookupSubNet(request.params[0].get_str(), subNet);
761  }
762 
763  if (!(isSubnet ? subNet.IsValid() : netAddr.IsValid())) {
765  "Error: Invalid IP/Subnet");
766  }
767 
768  if (strCommand == "add") {
769  if (isSubnet ? node.banman->IsBanned(subNet)
770  : node.banman->IsBanned(netAddr)) {
772  "Error: IP/Subnet already banned");
773  }
774 
775  // Use standard bantime if not specified.
776  int64_t banTime = 0;
777  if (!request.params[2].isNull()) {
778  banTime = request.params[2].get_int64();
779  }
780 
781  bool absolute = false;
782  if (request.params[3].isTrue()) {
783  absolute = true;
784  }
785 
786  if (isSubnet) {
787  node.banman->Ban(subNet, banTime, absolute);
788  if (node.connman) {
789  node.connman->DisconnectNode(subNet);
790  }
791  } else {
792  node.banman->Ban(netAddr, banTime, absolute);
793  if (node.connman) {
794  node.connman->DisconnectNode(netAddr);
795  }
796  }
797  } else if (strCommand == "remove") {
798  if (!(isSubnet ? node.banman->Unban(subNet)
799  : node.banman->Unban(netAddr))) {
801  "Error: Unban failed. Requested address/subnet "
802  "was not previously manually banned.");
803  }
804  }
805  return NullUniValue;
806 }
807 
808 static UniValue listbanned(const Config &config,
809  const JSONRPCRequest &request) {
810  RPCHelpMan{
811  "listbanned",
812  "List all manually banned IPs/Subnets.\n",
813  {},
815  "",
816  "",
817  {
819  "",
820  "",
821  {
822  {RPCResult::Type::STR, "address", ""},
823  {RPCResult::Type::NUM_TIME, "banned_until", ""},
824  {RPCResult::Type::NUM_TIME, "ban_created", ""},
825  {RPCResult::Type::STR, "ban_reason", ""},
826  }},
827  }},
828  RPCExamples{HelpExampleCli("listbanned", "") +
829  HelpExampleRpc("listbanned", "")},
830  }
831  .Check(request);
832 
833  NodeContext &node = EnsureNodeContext(request.context);
834  if (!node.banman) {
836  "Error: Ban database not loaded");
837  }
838 
839  banmap_t banMap;
840  node.banman->GetBanned(banMap);
841 
842  UniValue bannedAddresses(UniValue::VARR);
843  for (const auto &entry : banMap) {
844  const CBanEntry &banEntry = entry.second;
846  rec.pushKV("address", entry.first.ToString());
847  rec.pushKV("banned_until", banEntry.nBanUntil);
848  rec.pushKV("ban_created", banEntry.nCreateTime);
849 
850  bannedAddresses.push_back(rec);
851  }
852 
853  return bannedAddresses;
854 }
855 
856 static UniValue clearbanned(const Config &config,
857  const JSONRPCRequest &request) {
858  RPCHelpMan{
859  "clearbanned",
860  "Clear all banned IPs.\n",
861  {},
863  RPCExamples{HelpExampleCli("clearbanned", "") +
864  HelpExampleRpc("clearbanned", "")},
865  }
866  .Check(request);
867 
868  NodeContext &node = EnsureNodeContext(request.context);
869  if (!node.banman) {
870  throw JSONRPCError(
872  "Error: Peer-to-peer functionality missing or disabled");
873  }
874 
875  node.banman->ClearBanned();
876 
877  return NullUniValue;
878 }
879 
880 static UniValue setnetworkactive(const Config &config,
881  const JSONRPCRequest &request) {
882  RPCHelpMan{
883  "setnetworkactive",
884  "Disable/enable all p2p network activity.\n",
885  {
887  "true to enable networking, false to disable"},
888  },
889  RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
890  RPCExamples{""},
891  }
892  .Check(request);
893 
894  NodeContext &node = EnsureNodeContext(request.context);
895  if (!node.banman) {
896  throw JSONRPCError(
898  "Error: Peer-to-peer functionality missing or disabled");
899  }
900 
901  node.connman->SetNetworkActive(request.params[0].get_bool());
902 
903  return node.connman->GetNetworkActive();
904 }
905 
906 static UniValue getnodeaddresses(const Config &config,
907  const JSONRPCRequest &request) {
908  RPCHelpMan{
909  "getnodeaddresses",
910  "Return known addresses which can potentially be used to find new "
911  "nodes in the network\n",
912  {
913  {"count", RPCArg::Type::NUM, /* default */ "1",
914  "How many addresses to return. Limited to the smaller of " +
915  ToString(ADDRMAN_GETADDR_MAX) + " or " +
917  "% of all known addresses."},
918  },
919  RPCResult{
921  "",
922  "",
923  {
925  "",
926  "",
927  {
928  {RPCResult::Type::NUM_TIME, "time",
929  "The " + UNIX_EPOCH_TIME +
930  " of when the node was last seen"},
931  {RPCResult::Type::NUM, "services", "The services offered"},
932  {RPCResult::Type::STR, "address",
933  "The address of the node"},
934  {RPCResult::Type::NUM, "port", "The port of the node"},
935  }},
936  }},
937  RPCExamples{HelpExampleCli("getnodeaddresses", "8") +
938  HelpExampleRpc("getnodeaddresses", "8")},
939  }
940  .Check(request);
941 
942  NodeContext &node = EnsureNodeContext(request.context);
943  if (!node.banman) {
944  throw JSONRPCError(
946  "Error: Peer-to-peer functionality missing or disabled");
947  }
948 
949  int count = 1;
950  if (!request.params[0].isNull()) {
951  count = request.params[0].get_int();
952  if (count <= 0) {
954  "Address count out of range");
955  }
956  }
957  // returns a shuffled list of CAddress
958  std::vector<CAddress> vAddr = node.connman->GetAddresses();
960 
961  int address_return_count = std::min<int>(count, vAddr.size());
962  for (int i = 0; i < address_return_count; ++i) {
964  const CAddress &addr = vAddr[i];
965  obj.pushKV("time", int(addr.nTime));
966  obj.pushKV("services", uint64_t(addr.nServices));
967  obj.pushKV("address", addr.ToStringIP());
968  obj.pushKV("port", addr.GetPort());
969  ret.push_back(obj);
970  }
971  return ret;
972 }
973 
975  // clang-format off
976  static const CRPCCommand commands[] = {
977  // category name actor (function) argNames
978  // ------------------- ------------------------ ---------------------- ----------
979  { "network", "getconnectioncount", getconnectioncount, {} },
980  { "network", "ping", ping, {} },
981  { "network", "getpeerinfo", getpeerinfo, {} },
982  { "network", "addnode", addnode, {"node","command"} },
983  { "network", "disconnectnode", disconnectnode, {"address", "nodeid"} },
984  { "network", "getaddednodeinfo", getaddednodeinfo, {"node"} },
985  { "network", "getnettotals", getnettotals, {} },
986  { "network", "getnetworkinfo", getnetworkinfo, {} },
987  { "network", "setban", setban, {"subnet", "command", "bantime", "absolute"} },
988  { "network", "listbanned", listbanned, {} },
989  { "network", "clearbanned", clearbanned, {} },
990  { "network", "setnetworkactive", setnetworkactive, {"state"} },
991  { "network", "getnodeaddresses", getnodeaddresses, {"count"} },
992  };
993  // clang-format on
994 
995  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) {
996  t.appendCommand(commands[vcidx].name, &commands[vcidx]);
997  }
998 }
static UniValue help(Config &config, const JSONRPCRequest &jsonRequest)
Definition: server.cpp:175
static UniValue getnodeaddresses(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:906
unsigned short GetPort() const
Definition: netaddress.cpp:692
const util::Ref & context
Definition: request.h:42
const std::string CURRENCY_UNIT
Definition: network.cpp:8
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
Definition: server.cpp:387
Node has not been added before.
Definition: protocol.h:75
ServiceFlags
nServices flags.
Definition: protocol.h:320
Bitcoin RPC command dispatcher.
Definition: server.h:198
Connections to addresses added via addnode or the connect command line argument.
bool get_bool() const
virtual Amount GetExcessUTXOCharge() const =0
Required arg.
int64_t GetTimeMillis()
Returns the system time (not mockable)
Definition: time.cpp:59
std::unique_ptr< BanMan > banman
Definition: context.h:42
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats)
Get statistics from node state.
static UniValue disconnectnode(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:351
UniValue GetServicesNames(ServiceFlags services)
Returns, given services flags, a list of humanly readable (known) network services.
Definition: util.cpp:896
void RegisterNetRPCCommands(CRPCTable &t)
Register P2P networking RPC commands.
Definition: net.cpp:974
#define ARRAYLEN(array)
Utilities for converting data from/to strings.
Definition: strencodings.h:19
static UniValue setnetworkactive(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:880
static UniValue GetNetworksInfo()
Definition: net.cpp:566
const std::string & get_str() const
bool isStr() const
Definition: univalue.h:93
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:316
static UniValue getnettotals(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:499
int64_t nCreateTime
Definition: addrdb.h:25
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
static UniValue setban(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:705
static UniValue listbanned(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:808
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:890
RecursiveMutex cs_mapLocalHost
Definition: net.cpp:112
bool IsValid() const
Definition: netaddress.cpp:244
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:67
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:143
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:52
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
Definition: config.h:19
Special string with only hex chars.
NodeContext struct containing references to chain state and connection state.
Definition: context.h:35
std::unique_ptr< CConnman > connman
Definition: context.h:36
bool randomize_credentials
Definition: netbase.h:38
CFeeRate minRelayTxFee
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) ...
Definition: validation.cpp:115
UniValue params
Definition: request.h:37
static UniValue clearbanned(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:856
std::string ToStringIP() const
Definition: netaddress.cpp:332
#define LOCK(cs)
Definition: sync.h:230
const char * name
Definition: rest.cpp:43
static UniValue getpeerinfo(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:82
bool g_relay_txes
Definition: net.cpp:111
A CService with information about it as peer.
Definition: protocol.h:427
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:95
Network
Definition: netaddress.h:19
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
int64_t NodeId
Definition: net.h:99
int get_int() const
Invalid IP/Subnet.
Definition: protocol.h:79
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:138
bool isNull() const
Definition: univalue.h:89
Special numeric to denote unix epoch time.
bool isTrue() const
Definition: univalue.h:90
const std::string NET_MESSAGE_COMMAND_OTHER
Definition: net.cpp:98
int64_t nBanUntil
Definition: addrdb.h:26
NodeContext & EnsureNodeContext(const util::Ref &context)
Definition: blockchain.cpp:55
Database error.
Definition: protocol.h:48
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:30
bool fHelp
Definition: request.h:38
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:164
bool IsValid() const
Definition: netaddress.cpp:930
#define ADDRMAN_GETADDR_MAX
the maximum number of nodes to return in a getaddr call
Definition: addrman.h:176
std::atomic< bool > fPingQueued
Definition: net.h:1015
unsigned int nTime
Definition: protocol.h:466
bool IsReachable(enum Network net)
Definition: net.cpp:275
ServiceFlags nServices
Definition: protocol.h:463
CService proxy
Definition: netbase.h:37
bool IsValid() const
Definition: netbase.h:35
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:44
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11
std::string ToStringIPPort() const
Definition: netaddress.cpp:772
Node to disconnect not found in connected nodes.
Definition: protocol.h:77
Node is already added.
Definition: protocol.h:73
ArgsManager gArgs
Definition: system.cpp:76
const UniValue NullUniValue
Definition: univalue.cpp:13
static int count
Definition: tests.c:35
std::string GetWarnings(bool verbose)
Format a string that describes several potential problems detected by the core.
Definition: warnings.cpp:38
POD that contains various stats about a node.
Definition: net.h:645
static UniValue getconnectioncount(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:33
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:13
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:782
No valid connection manager instance found.
Definition: protocol.h:81
size_t size() const
Definition: univalue.h:80
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:59
static UniValue addnode(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:290
Information about a peer.
Definition: net.h:806
std::vector< int > vHeightInFlight
std::string userAgent(const Config &config)
Definition: net.cpp:3164
Special dictionary with keys that are not literals.
Definition: addrdb.h:21
static UniValue getnetworkinfo(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:587
static UniValue getaddednodeinfo(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:410
static UniValue ping(const Config &config, const JSONRPCRequest &request)
Definition: net.cpp:55
#define ADDRMAN_GETADDR_MAX_PCT
the maximum percentage of nodes to return in a getaddr call
Definition: addrman.h:173
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:21
static std::vector< std::string > ToStrings(NetPermissionFlags flags)
UniValue ValueFromAmount(const Amount &amount)
Definition: core_write.cpp:20