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