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