Bitcoin Core  0.21.0rc3
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::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
145  {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
146  {
147  {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n"
148  "When a message type is not listed in this json object, the bytes sent are 0.\n"
149  "Only known message types can appear as keys in the object."}
150  }},
151  {RPCResult::Type::OBJ, "bytesrecv_per_msg", "",
152  {
153  {RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n"
154  "When a message type is not listed in this json object, the bytes received are 0.\n"
155  "Only known message types can appear as keys in the object and all bytes received\n"
156  "of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."}
157  }},
158  }},
159  }},
160  },
161  RPCExamples{
162  HelpExampleCli("getpeerinfo", "")
163  + HelpExampleRpc("getpeerinfo", "")
164  },
165  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
166 {
167  NodeContext& node = EnsureNodeContext(request.context);
168  if(!node.connman)
169  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
170 
171  std::vector<CNodeStats> vstats;
172  node.connman->GetNodeStats(vstats);
173 
175 
176  for (const CNodeStats& stats : vstats) {
178  CNodeStateStats statestats;
179  bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
180  obj.pushKV("id", stats.nodeid);
181  obj.pushKV("addr", stats.addrName);
182  if (stats.addrBind.IsValid()) {
183  obj.pushKV("addrbind", stats.addrBind.ToString());
184  }
185  if (!(stats.addrLocal.empty())) {
186  obj.pushKV("addrlocal", stats.addrLocal);
187  }
188  obj.pushKV("network", stats.m_network);
189  if (stats.m_mapped_as != 0) {
190  obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
191  }
192  obj.pushKV("services", strprintf("%016x", stats.nServices));
193  obj.pushKV("servicesnames", GetServicesNames(stats.nServices));
194  obj.pushKV("relaytxes", stats.fRelayTxes);
195  obj.pushKV("lastsend", stats.nLastSend);
196  obj.pushKV("lastrecv", stats.nLastRecv);
197  obj.pushKV("last_transaction", stats.nLastTXTime);
198  obj.pushKV("last_block", stats.nLastBlockTime);
199  obj.pushKV("bytessent", stats.nSendBytes);
200  obj.pushKV("bytesrecv", stats.nRecvBytes);
201  obj.pushKV("conntime", stats.nTimeConnected);
202  obj.pushKV("timeoffset", stats.nTimeOffset);
203  if (stats.m_ping_usec > 0) {
204  obj.pushKV("pingtime", ((double)stats.m_ping_usec) / 1e6);
205  }
206  if (stats.m_min_ping_usec < std::numeric_limits<int64_t>::max()) {
207  obj.pushKV("minping", ((double)stats.m_min_ping_usec) / 1e6);
208  }
209  if (stats.m_ping_wait_usec > 0) {
210  obj.pushKV("pingwait", ((double)stats.m_ping_wait_usec) / 1e6);
211  }
212  obj.pushKV("version", stats.nVersion);
213  // Use the sanitized form of subver here, to avoid tricksy remote peers from
214  // corrupting or modifying the JSON output by putting special characters in
215  // their ver message.
216  obj.pushKV("subver", stats.cleanSubVer);
217  obj.pushKV("inbound", stats.fInbound);
218  if (IsDeprecatedRPCEnabled("getpeerinfo_addnode")) {
219  // addnode is deprecated in v0.21 for removal in v0.22
220  obj.pushKV("addnode", stats.m_manual_connection);
221  }
222  obj.pushKV("startingheight", stats.nStartingHeight);
223  if (fStateStats) {
224  if (IsDeprecatedRPCEnabled("banscore")) {
225  // banscore is deprecated in v0.21 for removal in v0.22
226  obj.pushKV("banscore", statestats.m_misbehavior_score);
227  }
228  obj.pushKV("synced_headers", statestats.nSyncHeight);
229  obj.pushKV("synced_blocks", statestats.nCommonHeight);
230  UniValue heights(UniValue::VARR);
231  for (const int height : statestats.vHeightInFlight) {
232  heights.push_back(height);
233  }
234  obj.pushKV("inflight", heights);
235  }
236  if (IsDeprecatedRPCEnabled("whitelisted")) {
237  // whitelisted is deprecated in v0.21 for removal in v0.22
238  obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
239  }
240  UniValue permissions(UniValue::VARR);
241  for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
242  permissions.push_back(permission);
243  }
244  obj.pushKV("permissions", permissions);
245  obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter));
246 
247  UniValue sendPerMsgCmd(UniValue::VOBJ);
248  for (const auto& i : stats.mapSendBytesPerMsgCmd) {
249  if (i.second > 0)
250  sendPerMsgCmd.pushKV(i.first, i.second);
251  }
252  obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
253 
254  UniValue recvPerMsgCmd(UniValue::VOBJ);
255  for (const auto& i : stats.mapRecvBytesPerMsgCmd) {
256  if (i.second > 0)
257  recvPerMsgCmd.pushKV(i.first, i.second);
258  }
259  obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
260  obj.pushKV("connection_type", stats.m_conn_type_string);
261 
262  ret.push_back(obj);
263  }
264 
265  return ret;
266 },
267  };
268 }
269 
271 {
272  return RPCHelpMan{"addnode",
273  "\nAttempts to add or remove a node from the addnode list.\n"
274  "Or try a connection to a node once.\n"
275  "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
276  "full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).\n",
277  {
278  {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"},
279  {"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"},
280  },
282  RPCExamples{
283  HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
284  + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
285  },
286  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
287 {
288  std::string strCommand;
289  if (!request.params[1].isNull())
290  strCommand = request.params[1].get_str();
291  if (request.fHelp || request.params.size() != 2 ||
292  (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
293  throw std::runtime_error(
294  self.ToString());
295 
296  NodeContext& node = EnsureNodeContext(request.context);
297  if(!node.connman)
298  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
299 
300  std::string strNode = request.params[0].get_str();
301 
302  if (strCommand == "onetry")
303  {
304  CAddress addr;
305  node.connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL);
306  return NullUniValue;
307  }
308 
309  if (strCommand == "add")
310  {
311  if(!node.connman->AddNode(strNode))
312  throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
313  }
314  else if(strCommand == "remove")
315  {
316  if(!node.connman->RemoveAddedNode(strNode))
317  throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node could not be removed. It has not been added previously.");
318  }
319 
320  return NullUniValue;
321 },
322  };
323 }
324 
326 {
327  return RPCHelpMan{"disconnectnode",
328  "\nImmediately disconnects from the specified peer node.\n"
329  "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
330  "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
331  {
332  {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"},
333  {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"},
334  },
336  RPCExamples{
337  HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
338  + HelpExampleCli("disconnectnode", "\"\" 1")
339  + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
340  + HelpExampleRpc("disconnectnode", "\"\", 1")
341  },
342  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
343 {
344  NodeContext& node = EnsureNodeContext(request.context);
345  if(!node.connman)
346  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
347 
348  bool success;
349  const UniValue &address_arg = request.params[0];
350  const UniValue &id_arg = request.params[1];
351 
352  if (!address_arg.isNull() && id_arg.isNull()) {
353  /* handle disconnect-by-address */
354  success = node.connman->DisconnectNode(address_arg.get_str());
355  } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
356  /* handle disconnect-by-id */
357  NodeId nodeid = (NodeId) id_arg.get_int64();
358  success = node.connman->DisconnectNode(nodeid);
359  } else {
360  throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
361  }
362 
363  if (!success) {
364  throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
365  }
366 
367  return NullUniValue;
368 },
369  };
370 }
371 
373 {
374  return RPCHelpMan{"getaddednodeinfo",
375  "\nReturns information about the given added node, or all added nodes\n"
376  "(note that onetry addnodes are not listed here)\n",
377  {
378  {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."},
379  },
380  RPCResult{
381  RPCResult::Type::ARR, "", "",
382  {
383  {RPCResult::Type::OBJ, "", "",
384  {
385  {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"},
386  {RPCResult::Type::BOOL, "connected", "If connected"},
387  {RPCResult::Type::ARR, "addresses", "Only when connected = true",
388  {
389  {RPCResult::Type::OBJ, "", "",
390  {
391  {RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"},
392  {RPCResult::Type::STR, "connected", "connection, inbound or outbound"},
393  }},
394  }},
395  }},
396  }
397  },
398  RPCExamples{
399  HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
400  + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
401  },
402  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
403 {
404  NodeContext& node = EnsureNodeContext(request.context);
405  if(!node.connman)
406  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
407 
408  std::vector<AddedNodeInfo> vInfo = node.connman->GetAddedNodeInfo();
409 
410  if (!request.params[0].isNull()) {
411  bool found = false;
412  for (const AddedNodeInfo& info : vInfo) {
413  if (info.strAddedNode == request.params[0].get_str()) {
414  vInfo.assign(1, info);
415  found = true;
416  break;
417  }
418  }
419  if (!found) {
420  throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
421  }
422  }
423 
425 
426  for (const AddedNodeInfo& info : vInfo) {
428  obj.pushKV("addednode", info.strAddedNode);
429  obj.pushKV("connected", info.fConnected);
430  UniValue addresses(UniValue::VARR);
431  if (info.fConnected) {
432  UniValue address(UniValue::VOBJ);
433  address.pushKV("address", info.resolvedAddress.ToString());
434  address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
435  addresses.push_back(address);
436  }
437  obj.pushKV("addresses", addresses);
438  ret.push_back(obj);
439  }
440 
441  return ret;
442 },
443  };
444 }
445 
447 {
448  return RPCHelpMan{"getnettotals",
449  "\nReturns information about network traffic, including bytes in, bytes out,\n"
450  "and current time.\n",
451  {},
452  RPCResult{
453  RPCResult::Type::OBJ, "", "",
454  {
455  {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
456  {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
457  {RPCResult::Type::NUM_TIME, "timemillis", "Current " + UNIX_EPOCH_TIME + " in milliseconds"},
458  {RPCResult::Type::OBJ, "uploadtarget", "",
459  {
460  {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
461  {RPCResult::Type::NUM, "target", "Target in bytes"},
462  {RPCResult::Type::BOOL, "target_reached", "True if target is reached"},
463  {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},
464  {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},
465  {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},
466  }},
467  }
468  },
469  RPCExamples{
470  HelpExampleCli("getnettotals", "")
471  + HelpExampleRpc("getnettotals", "")
472  },
473  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
474 {
475  NodeContext& node = EnsureNodeContext(request.context);
476  if(!node.connman)
477  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
478 
480  obj.pushKV("totalbytesrecv", node.connman->GetTotalBytesRecv());
481  obj.pushKV("totalbytessent", node.connman->GetTotalBytesSent());
482  obj.pushKV("timemillis", GetTimeMillis());
483 
484  UniValue outboundLimit(UniValue::VOBJ);
485  outboundLimit.pushKV("timeframe", node.connman->GetMaxOutboundTimeframe());
486  outboundLimit.pushKV("target", node.connman->GetMaxOutboundTarget());
487  outboundLimit.pushKV("target_reached", node.connman->OutboundTargetReached(false));
488  outboundLimit.pushKV("serve_historical_blocks", !node.connman->OutboundTargetReached(true));
489  outboundLimit.pushKV("bytes_left_in_cycle", node.connman->GetOutboundTargetBytesLeft());
490  outboundLimit.pushKV("time_left_in_cycle", node.connman->GetMaxOutboundTimeLeftInCycle());
491  obj.pushKV("uploadtarget", outboundLimit);
492  return obj;
493 },
494  };
495 }
496 
498 {
499  UniValue networks(UniValue::VARR);
500  for (int n = 0; n < NET_MAX; ++n) {
501  enum Network network = static_cast<enum Network>(n);
502  if (network == NET_UNROUTABLE || network == NET_I2P || network == NET_CJDNS || network == NET_INTERNAL) continue;
503  proxyType proxy;
505  GetProxy(network, proxy);
506  obj.pushKV("name", GetNetworkName(network));
507  obj.pushKV("limited", !IsReachable(network));
508  obj.pushKV("reachable", IsReachable(network));
509  obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
510  obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
511  networks.push_back(obj);
512  }
513  return networks;
514 }
515 
517 {
518  return RPCHelpMan{"getnetworkinfo",
519  "Returns an object containing various state info regarding P2P networking.\n",
520  {},
521  RPCResult{
522  RPCResult::Type::OBJ, "", "",
523  {
524  {RPCResult::Type::NUM, "version", "the server version"},
525  {RPCResult::Type::STR, "subversion", "the server subversion string"},
526  {RPCResult::Type::NUM, "protocolversion", "the protocol version"},
527  {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"},
528  {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form",
529  {
530  {RPCResult::Type::STR, "SERVICE_NAME", "the service name"},
531  }},
532  {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"},
533  {RPCResult::Type::NUM, "timeoffset", "the time offset"},
534  {RPCResult::Type::NUM, "connections", "the total number of connections"},
535  {RPCResult::Type::NUM, "connections_in", "the number of inbound connections"},
536  {RPCResult::Type::NUM, "connections_out", "the number of outbound connections"},
537  {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"},
538  {RPCResult::Type::ARR, "networks", "information per network",
539  {
540  {RPCResult::Type::OBJ, "", "",
541  {
542  {RPCResult::Type::STR, "name", "network (ipv4, ipv6 or onion)"},
543  {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"},
544  {RPCResult::Type::BOOL, "reachable", "is the network reachable?"},
545  {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"},
546  {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"},
547  }},
548  }},
549  {RPCResult::Type::NUM, "relayfee", "minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB"},
550  {RPCResult::Type::NUM, "incrementalfee", "minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB"},
551  {RPCResult::Type::ARR, "localaddresses", "list of local addresses",
552  {
553  {RPCResult::Type::OBJ, "", "",
554  {
555  {RPCResult::Type::STR, "address", "network address"},
556  {RPCResult::Type::NUM, "port", "network port"},
557  {RPCResult::Type::NUM, "score", "relative score"},
558  }},
559  }},
560  {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"},
561  }
562  },
563  RPCExamples{
564  HelpExampleCli("getnetworkinfo", "")
565  + HelpExampleRpc("getnetworkinfo", "")
566  },
567  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
568 {
569  LOCK(cs_main);
571  obj.pushKV("version", CLIENT_VERSION);
572  obj.pushKV("subversion", strSubVersion);
573  obj.pushKV("protocolversion",PROTOCOL_VERSION);
574  NodeContext& node = EnsureNodeContext(request.context);
575  if (node.connman) {
576  ServiceFlags services = node.connman->GetLocalServices();
577  obj.pushKV("localservices", strprintf("%016x", services));
578  obj.pushKV("localservicesnames", GetServicesNames(services));
579  }
580  obj.pushKV("localrelay", g_relay_txes);
581  obj.pushKV("timeoffset", GetTimeOffset());
582  if (node.connman) {
583  obj.pushKV("networkactive", node.connman->GetNetworkActive());
584  obj.pushKV("connections", (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
585  obj.pushKV("connections_in", (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_IN));
586  obj.pushKV("connections_out", (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_OUT));
587  }
588  obj.pushKV("networks", GetNetworksInfo());
589  obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
590  obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
591  UniValue localAddresses(UniValue::VARR);
592  {
594  for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
595  {
597  rec.pushKV("address", item.first.ToString());
598  rec.pushKV("port", item.second.nPort);
599  rec.pushKV("score", item.second.nScore);
600  localAddresses.push_back(rec);
601  }
602  }
603  obj.pushKV("localaddresses", localAddresses);
604  obj.pushKV("warnings", GetWarnings(false).original);
605  return obj;
606 },
607  };
608 }
609 
611 {
612  return RPCHelpMan{"setban",
613  "\nAttempts to add or remove an IP/Subnet from the banned list.\n",
614  {
615  {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
616  {"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"},
617  {"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)"},
618  {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
619  },
621  RPCExamples{
622  HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
623  + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
624  + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
625  },
626  [&](const RPCHelpMan& help, const JSONRPCRequest& request) -> UniValue
627 {
628  std::string strCommand;
629  if (!request.params[1].isNull())
630  strCommand = request.params[1].get_str();
631  if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
632  throw std::runtime_error(help.ToString());
633  }
634  NodeContext& node = EnsureNodeContext(request.context);
635  if (!node.banman) {
636  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
637  }
638 
639  CSubNet subNet;
640  CNetAddr netAddr;
641  bool isSubnet = false;
642 
643  if (request.params[0].get_str().find('/') != std::string::npos)
644  isSubnet = true;
645 
646  if (!isSubnet) {
647  CNetAddr resolved;
648  LookupHost(request.params[0].get_str(), resolved, false);
649  netAddr = resolved;
650  }
651  else
652  LookupSubNet(request.params[0].get_str(), subNet);
653 
654  if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
655  throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
656 
657  if (strCommand == "add")
658  {
659  if (isSubnet ? node.banman->IsBanned(subNet) : node.banman->IsBanned(netAddr)) {
660  throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
661  }
662 
663  int64_t banTime = 0; //use standard bantime if not specified
664  if (!request.params[2].isNull())
665  banTime = request.params[2].get_int64();
666 
667  bool absolute = false;
668  if (request.params[3].isTrue())
669  absolute = true;
670 
671  if (isSubnet) {
672  node.banman->Ban(subNet, banTime, absolute);
673  if (node.connman) {
674  node.connman->DisconnectNode(subNet);
675  }
676  } else {
677  node.banman->Ban(netAddr, banTime, absolute);
678  if (node.connman) {
679  node.connman->DisconnectNode(netAddr);
680  }
681  }
682  }
683  else if(strCommand == "remove")
684  {
685  if (!( isSubnet ? node.banman->Unban(subNet) : node.banman->Unban(netAddr) )) {
686  throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");
687  }
688  }
689  return NullUniValue;
690 },
691  };
692 }
693 
695 {
696  return RPCHelpMan{"listbanned",
697  "\nList all manually banned IPs/Subnets.\n",
698  {},
700  {
701  {RPCResult::Type::OBJ, "", "",
702  {
703  {RPCResult::Type::STR, "address", ""},
704  {RPCResult::Type::NUM_TIME, "banned_until", ""},
705  {RPCResult::Type::NUM_TIME, "ban_created", ""},
706  }},
707  }},
708  RPCExamples{
709  HelpExampleCli("listbanned", "")
710  + HelpExampleRpc("listbanned", "")
711  },
712  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
713 {
714  NodeContext& node = EnsureNodeContext(request.context);
715  if(!node.banman) {
716  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
717  }
718 
719  banmap_t banMap;
720  node.banman->GetBanned(banMap);
721 
722  UniValue bannedAddresses(UniValue::VARR);
723  for (const auto& entry : banMap)
724  {
725  const CBanEntry& banEntry = entry.second;
727  rec.pushKV("address", entry.first.ToString());
728  rec.pushKV("banned_until", banEntry.nBanUntil);
729  rec.pushKV("ban_created", banEntry.nCreateTime);
730 
731  bannedAddresses.push_back(rec);
732  }
733 
734  return bannedAddresses;
735 },
736  };
737 }
738 
740 {
741  return RPCHelpMan{"clearbanned",
742  "\nClear all banned IPs.\n",
743  {},
745  RPCExamples{
746  HelpExampleCli("clearbanned", "")
747  + HelpExampleRpc("clearbanned", "")
748  },
749  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
750 {
751  NodeContext& node = EnsureNodeContext(request.context);
752  if (!node.banman) {
753  throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
754  }
755 
756  node.banman->ClearBanned();
757 
758  return NullUniValue;
759 },
760  };
761 }
762 
764 {
765  return RPCHelpMan{"setnetworkactive",
766  "\nDisable/enable all p2p network activity.\n",
767  {
768  {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
769  },
770  RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
771  RPCExamples{""},
772  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
773 {
774  NodeContext& node = EnsureNodeContext(request.context);
775  if (!node.connman) {
776  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
777  }
778 
779  node.connman->SetNetworkActive(request.params[0].get_bool());
780 
781  return node.connman->GetNetworkActive();
782 },
783  };
784 }
785 
787 {
788  return RPCHelpMan{"getnodeaddresses",
789  "\nReturn known addresses which can potentially be used to find new nodes in the network\n",
790  {
791  {"count", RPCArg::Type::NUM, /* default */ "1", "The maximum number of addresses to return. Specify 0 to return all known addresses."},
792  },
793  RPCResult{
794  RPCResult::Type::ARR, "", "",
795  {
796  {RPCResult::Type::OBJ, "", "",
797  {
798  {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " of when the node was last seen"},
799  {RPCResult::Type::NUM, "services", "The services offered"},
800  {RPCResult::Type::STR, "address", "The address of the node"},
801  {RPCResult::Type::NUM, "port", "The port of the node"},
802  }},
803  }
804  },
805  RPCExamples{
806  HelpExampleCli("getnodeaddresses", "8")
807  + HelpExampleRpc("getnodeaddresses", "8")
808  },
809  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
810 {
811  NodeContext& node = EnsureNodeContext(request.context);
812  if (!node.connman) {
813  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
814  }
815 
816  int count = 1;
817  if (!request.params[0].isNull()) {
818  count = request.params[0].get_int();
819  if (count < 0) {
820  throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range");
821  }
822  }
823  // returns a shuffled list of CAddress
824  std::vector<CAddress> vAddr = node.connman->GetAddresses(count, /* max_pct */ 0);
826 
827  for (const CAddress& addr : vAddr) {
829  obj.pushKV("time", (int)addr.nTime);
830  obj.pushKV("services", (uint64_t)addr.nServices);
831  obj.pushKV("address", addr.ToStringIP());
832  obj.pushKV("port", addr.GetPort());
833  ret.push_back(obj);
834  }
835  return ret;
836 },
837  };
838 }
839 
841 {
842  return RPCHelpMan{"addpeeraddress",
843  "\nAdd the address of a potential peer to the address manager. This RPC is for testing only.\n",
844  {
845  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address of the peer"},
846  {"port", RPCArg::Type::NUM, RPCArg::Optional::NO, "The port of the peer"},
847  },
848  RPCResult{
849  RPCResult::Type::OBJ, "", "",
850  {
851  {RPCResult::Type::BOOL, "success", "whether the peer address was successfully added to the address manager"},
852  },
853  },
854  RPCExamples{
855  HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 8333")
856  + HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 8333")
857  },
858  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
859 {
860  NodeContext& node = EnsureNodeContext(request.context);
861  if (!node.connman) {
862  throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
863  }
864 
866 
867  std::string addr_string = request.params[0].get_str();
868  uint16_t port = request.params[1].get_int();
869 
870  CNetAddr net_addr;
871  if (!LookupHost(addr_string, net_addr, false)) {
872  obj.pushKV("success", false);
873  return obj;
874  }
875  CAddress address = CAddress({net_addr, port}, ServiceFlags(NODE_NETWORK|NODE_WITNESS));
876  address.nTime = GetAdjustedTime();
877  // The source address is set equal to the address. This is equivalent to the peer
878  // announcing itself.
879  if (!node.connman->AddNewAddresses({address}, address)) {
880  obj.pushKV("success", false);
881  return obj;
882  }
883 
884  obj.pushKV("success", true);
885  return obj;
886 },
887  };
888 }
889 
891 {
892 // clang-format off
893 static const CRPCCommand commands[] =
894 { // category name actor (function) argNames
895  // --------------------- ------------------------ ----------------------- ----------
896  { "network", "getconnectioncount", &getconnectioncount, {} },
897  { "network", "ping", &ping, {} },
898  { "network", "getpeerinfo", &getpeerinfo, {} },
899  { "network", "addnode", &addnode, {"node","command"} },
900  { "network", "disconnectnode", &disconnectnode, {"address", "nodeid"} },
901  { "network", "getaddednodeinfo", &getaddednodeinfo, {"node"} },
902  { "network", "getnettotals", &getnettotals, {} },
903  { "network", "getnetworkinfo", &getnetworkinfo, {} },
904  { "network", "setban", &setban, {"subnet", "command", "bantime", "absolute"} },
905  { "network", "listbanned", &listbanned, {} },
906  { "network", "clearbanned", &clearbanned, {} },
907  { "network", "setnetworkactive", &setnetworkactive, {"state"} },
908  { "network", "getnodeaddresses", &getnodeaddresses, {"count"} },
909  { "hidden", "addpeeraddress", &addpeeraddress, {"address", "port"} },
910 };
911 // clang-format on
912  for (const auto& c : commands) {
913  t.appendCommand(c.name, &c);
914  }
915 }
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
ServiceFlags
nServices flags
Definition: protocol.h:269
static RPCHelpMan clearbanned()
Definition: net.cpp:739
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:57
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:890
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:497
static RPCHelpMan addpeeraddress()
Definition: net.cpp:840
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:446
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:786
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:325
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:610
static RPCHelpMan addnode()
Definition: net.cpp:270
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:763
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:516
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:372
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:694
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