Bitcoin Core  0.21.1
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules
bitcoin-cli.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #if defined(HAVE_CONFIG_H)
8 #endif
9 
10 #include <chainparamsbase.h>
11 #include <clientversion.h>
12 #include <optional.h>
13 #include <rpc/client.h>
14 #include <rpc/mining.h>
15 #include <rpc/protocol.h>
16 #include <rpc/request.h>
17 #include <tinyformat.h>
18 #include <util/strencodings.h>
19 #include <util/system.h>
20 #include <util/translation.h>
21 #include <util/url.h>
22 
23 #include <algorithm>
24 #include <functional>
25 #include <memory>
26 #include <stdio.h>
27 #include <string>
28 #include <tuple>
29 
30 #include <event2/buffer.h>
31 #include <event2/keyvalq_struct.h>
32 #include <support/events.h>
33 
34 #include <univalue.h>
35 #include <compat/stdin.h>
36 
37 const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
39 
40 static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
41 static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
42 static const bool DEFAULT_NAMED=false;
43 static const int CONTINUE_EXECUTION=-1;
44 
46 static const std::string DEFAULT_NBLOCKS = "1";
47 
48 static void SetupCliArgs(ArgsManager& argsman)
49 {
50  SetupHelpOptions(argsman);
51 
52  const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
53  const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
54  const auto signetBaseParams = CreateBaseChainParams(CBaseChainParams::SIGNET);
55  const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
56 
57  argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
58  argsman.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
59  argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
60  argsman.AddArg("-generate", strprintf("Generate blocks immediately, equivalent to RPC generatenewaddress followed by RPC generatetoaddress. Optional positional integer arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000", DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
61  argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
62  argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0).", ArgsManager::ALLOW_INT, OptionsCategory::OPTIONS);
63 
65  argsman.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
66  argsman.AddArg("-rpcclienttimeout=<n>", strprintf("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
67  argsman.AddArg("-rpcconnect=<ip>", strprintf("Send commands to node running on <ip> (default: %s)", DEFAULT_RPCCONNECT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
68  argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
69  argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
70  argsman.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u, testnet: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
71  argsman.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
72  argsman.AddArg("-rpcwait", "Wait for RPC server to start", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
73  argsman.AddArg("-rpcwallet=<walletname>", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind). This changes the RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname>", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
74  argsman.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
75  argsman.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password. When combined with -stdinwalletpassphrase, -stdinrpcpass consumes the first line, and -stdinwalletpassphrase consumes the second.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
76  argsman.AddArg("-stdinwalletpassphrase", "Read wallet passphrase from standard input as a single line. When combined with -stdin, the first line from standard input is used for the wallet passphrase.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
77 }
78 
80 static void libevent_log_cb(int severity, const char *msg)
81 {
82 #ifndef EVENT_LOG_ERR // EVENT_LOG_ERR was added in 2.0.19; but before then _EVENT_LOG_ERR existed.
83 # define EVENT_LOG_ERR _EVENT_LOG_ERR
84 #endif
85  // Ignore everything other than errors
86  if (severity >= EVENT_LOG_ERR) {
87  throw std::runtime_error(strprintf("libevent error: %s", msg));
88  }
89 }
90 
91 //
92 // Exception thrown on connection error. This error is used to determine
93 // when to wait if -rpcwait is given.
94 //
95 class CConnectionFailed : public std::runtime_error
96 {
97 public:
98 
99  explicit inline CConnectionFailed(const std::string& msg) :
100  std::runtime_error(msg)
101  {}
102 
103 };
104 
105 //
106 // This function returns either one of EXIT_ codes when it's expected to stop the process or
107 // CONTINUE_EXECUTION when it's expected to continue further.
108 //
109 static int AppInitRPC(int argc, char* argv[])
110 {
112  std::string error;
113  if (!gArgs.ParseParameters(argc, argv, error)) {
114  tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
115  return EXIT_FAILURE;
116  }
117  if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
118  std::string strUsage = PACKAGE_NAME " RPC client version " + FormatFullVersion() + "\n";
119  if (!gArgs.IsArgSet("-version")) {
120  strUsage += "\n"
121  "Usage: bitcoin-cli [options] <command> [params] Send command to " PACKAGE_NAME "\n"
122  "or: bitcoin-cli [options] -named <command> [name=value]... Send command to " PACKAGE_NAME " (with named arguments)\n"
123  "or: bitcoin-cli [options] help List commands\n"
124  "or: bitcoin-cli [options] help <command> Get help for a command\n";
125  strUsage += "\n" + gArgs.GetHelpMessage();
126  }
127 
128  tfm::format(std::cout, "%s", strUsage);
129  if (argc < 2) {
130  tfm::format(std::cerr, "Error: too few parameters\n");
131  return EXIT_FAILURE;
132  }
133  return EXIT_SUCCESS;
134  }
135  if (!CheckDataDirOption()) {
136  tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", ""));
137  return EXIT_FAILURE;
138  }
139  if (!gArgs.ReadConfigFiles(error, true)) {
140  tfm::format(std::cerr, "Error reading configuration file: %s\n", error);
141  return EXIT_FAILURE;
142  }
143  // Check for chain settings (BaseParams() calls are only valid after this clause)
144  try {
146  } catch (const std::exception& e) {
147  tfm::format(std::cerr, "Error: %s\n", e.what());
148  return EXIT_FAILURE;
149  }
150  return CONTINUE_EXECUTION;
151 }
152 
153 
155 struct HTTPReply
156 {
157  HTTPReply(): status(0), error(-1) {}
158 
159  int status;
160  int error;
161  std::string body;
162 };
163 
164 static std::string http_errorstring(int code)
165 {
166  switch(code) {
167 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
168  case EVREQ_HTTP_TIMEOUT:
169  return "timeout reached";
170  case EVREQ_HTTP_EOF:
171  return "EOF reached";
172  case EVREQ_HTTP_INVALID_HEADER:
173  return "error while reading header, or invalid header";
174  case EVREQ_HTTP_BUFFER_ERROR:
175  return "error encountered while reading or writing";
176  case EVREQ_HTTP_REQUEST_CANCEL:
177  return "request was canceled";
178  case EVREQ_HTTP_DATA_TOO_LONG:
179  return "response body is larger than allowed";
180 #endif
181  default:
182  return "unknown";
183  }
184 }
185 
186 static void http_request_done(struct evhttp_request *req, void *ctx)
187 {
188  HTTPReply *reply = static_cast<HTTPReply*>(ctx);
189 
190  if (req == nullptr) {
191  /* If req is nullptr, it means an error occurred while connecting: the
192  * error code will have been passed to http_error_cb.
193  */
194  reply->status = 0;
195  return;
196  }
197 
198  reply->status = evhttp_request_get_response_code(req);
199 
200  struct evbuffer *buf = evhttp_request_get_input_buffer(req);
201  if (buf)
202  {
203  size_t size = evbuffer_get_length(buf);
204  const char *data = (const char*)evbuffer_pullup(buf, size);
205  if (data)
206  reply->body = std::string(data, size);
207  evbuffer_drain(buf, size);
208  }
209 }
210 
211 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
212 static void http_error_cb(enum evhttp_request_error err, void *ctx)
213 {
214  HTTPReply *reply = static_cast<HTTPReply*>(ctx);
215  reply->error = err;
216 }
217 #endif
218 
223 {
224 public:
225  virtual ~BaseRequestHandler() {}
226  virtual UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) = 0;
227  virtual UniValue ProcessReply(const UniValue &batch_in) = 0;
228 };
229 
232 {
233 public:
234  const int ID_NETWORKINFO = 0;
235  const int ID_BLOCKCHAININFO = 1;
236  const int ID_WALLETINFO = 2;
237  const int ID_BALANCES = 3;
238 
240  UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
241  {
242  if (!args.empty()) {
243  throw std::runtime_error("-getinfo takes no arguments");
244  }
245  UniValue result(UniValue::VARR);
246  result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
247  result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue, ID_BLOCKCHAININFO));
248  result.push_back(JSONRPCRequestObj("getwalletinfo", NullUniValue, ID_WALLETINFO));
249  result.push_back(JSONRPCRequestObj("getbalances", NullUniValue, ID_BALANCES));
250  return result;
251  }
252 
254  UniValue ProcessReply(const UniValue &batch_in) override
255  {
256  UniValue result(UniValue::VOBJ);
257  const std::vector<UniValue> batch = JSONRPCProcessBatchReply(batch_in);
258  // Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass them on;
259  // getwalletinfo() and getbalances() are allowed to fail if there is no wallet.
260  if (!batch[ID_NETWORKINFO]["error"].isNull()) {
261  return batch[ID_NETWORKINFO];
262  }
263  if (!batch[ID_BLOCKCHAININFO]["error"].isNull()) {
264  return batch[ID_BLOCKCHAININFO];
265  }
266  result.pushKV("version", batch[ID_NETWORKINFO]["result"]["version"]);
267  result.pushKV("blocks", batch[ID_BLOCKCHAININFO]["result"]["blocks"]);
268  result.pushKV("headers", batch[ID_BLOCKCHAININFO]["result"]["headers"]);
269  result.pushKV("verificationprogress", batch[ID_BLOCKCHAININFO]["result"]["verificationprogress"]);
270  result.pushKV("timeoffset", batch[ID_NETWORKINFO]["result"]["timeoffset"]);
271 
272  UniValue connections(UniValue::VOBJ);
273  connections.pushKV("in", batch[ID_NETWORKINFO]["result"]["connections_in"]);
274  connections.pushKV("out", batch[ID_NETWORKINFO]["result"]["connections_out"]);
275  connections.pushKV("total", batch[ID_NETWORKINFO]["result"]["connections"]);
276  result.pushKV("connections", connections);
277 
278  result.pushKV("proxy", batch[ID_NETWORKINFO]["result"]["networks"][0]["proxy"]);
279  result.pushKV("difficulty", batch[ID_BLOCKCHAININFO]["result"]["difficulty"]);
280  result.pushKV("chain", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"]));
281  if (!batch[ID_WALLETINFO]["result"].isNull()) {
282  result.pushKV("keypoolsize", batch[ID_WALLETINFO]["result"]["keypoolsize"]);
283  if (!batch[ID_WALLETINFO]["result"]["unlocked_until"].isNull()) {
284  result.pushKV("unlocked_until", batch[ID_WALLETINFO]["result"]["unlocked_until"]);
285  }
286  result.pushKV("paytxfee", batch[ID_WALLETINFO]["result"]["paytxfee"]);
287  }
288  if (!batch[ID_BALANCES]["result"].isNull()) {
289  result.pushKV("balance", batch[ID_BALANCES]["result"]["mine"]["trusted"]);
290  }
291  result.pushKV("relayfee", batch[ID_NETWORKINFO]["result"]["relayfee"]);
292  result.pushKV("warnings", batch[ID_NETWORKINFO]["result"]["warnings"]);
293  return JSONRPCReplyObj(result, NullUniValue, 1);
294  }
295 };
296 
299 {
300 private:
301  static constexpr int8_t UNKNOWN_NETWORK{-1};
302  static constexpr uint8_t m_networks_size{3};
303  const std::array<std::string, m_networks_size> m_networks{{"ipv4", "ipv6", "onion"}};
304  std::array<std::array<uint16_t, m_networks_size + 2>, 3> m_counts{{{}}};
305  int8_t NetworkStringToId(const std::string& str) const
306  {
307  for (uint8_t i = 0; i < m_networks_size; ++i) {
308  if (str == m_networks.at(i)) return i;
309  }
310  return UNKNOWN_NETWORK;
311  }
312  uint8_t m_details_level{0};
313  bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
314  bool IsAddressSelected() const { return m_details_level == 2 || m_details_level == 4; }
315  bool IsVersionSelected() const { return m_details_level == 3 || m_details_level == 4; }
316  bool m_is_asmap_on{false};
317  size_t m_max_addr_length{0};
318  size_t m_max_age_length{4};
319  size_t m_max_id_length{2};
320  struct Peer {
321  std::string addr;
322  std::string sub_version;
323  std::string network;
324  std::string age;
325  double min_ping;
326  double ping;
327  int64_t last_blck;
328  int64_t last_recv;
329  int64_t last_send;
330  int64_t last_trxn;
331  int id;
333  int version;
336  bool operator<(const Peer& rhs) const { return std::tie(is_outbound, min_ping) < std::tie(rhs.is_outbound, rhs.min_ping); }
337  };
338  std::vector<Peer> m_peers;
339  std::string ChainToString() const
340  {
341  if (gArgs.GetChainName() == CBaseChainParams::TESTNET) return " testnet";
342  if (gArgs.GetChainName() == CBaseChainParams::SIGNET) return " signet";
343  if (gArgs.GetChainName() == CBaseChainParams::REGTEST) return " regtest";
344  return "";
345  }
346  std::string PingTimeToString(double seconds) const
347  {
348  if (seconds < 0) return "";
349  const double milliseconds{round(1000 * seconds)};
350  return milliseconds > 999999 ? "-" : ToString(milliseconds);
351  }
353 
354 public:
355  static constexpr int ID_PEERINFO = 0;
356  static constexpr int ID_NETWORKINFO = 1;
357 
358  UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
359  {
360  if (!args.empty()) {
361  uint8_t n{0};
362  if (ParseUInt8(args.at(0), &n)) {
363  m_details_level = n;
364  }
365  }
366  UniValue result(UniValue::VARR);
367  result.push_back(JSONRPCRequestObj("getpeerinfo", NullUniValue, ID_PEERINFO));
368  result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
369  return result;
370  }
371 
372  UniValue ProcessReply(const UniValue& batch_in) override
373  {
374  const std::vector<UniValue> batch{JSONRPCProcessBatchReply(batch_in)};
375  if (!batch[ID_PEERINFO]["error"].isNull()) return batch[ID_PEERINFO];
376  if (!batch[ID_NETWORKINFO]["error"].isNull()) return batch[ID_NETWORKINFO];
377 
378  const UniValue& networkinfo{batch[ID_NETWORKINFO]["result"]};
379  if (networkinfo["version"].get_int() < 209900) {
380  throw std::runtime_error("-netinfo requires bitcoind server to be running v0.21.0 and up");
381  }
382 
383  // Count peer connection totals, and if DetailsRequested(), store peer data in a vector of structs.
384  for (const UniValue& peer : batch[ID_PEERINFO]["result"].getValues()) {
385  const std::string network{peer["network"].get_str()};
386  const int8_t network_id{NetworkStringToId(network)};
387  if (network_id == UNKNOWN_NETWORK) continue;
388  const bool is_outbound{!peer["inbound"].get_bool()};
389  const bool is_block_relay{!peer["relaytxes"].get_bool()};
390  ++m_counts.at(is_outbound).at(network_id); // in/out by network
391  ++m_counts.at(is_outbound).at(m_networks_size); // in/out overall
392  ++m_counts.at(2).at(network_id); // total by network
393  ++m_counts.at(2).at(m_networks_size); // total overall
394  if (is_block_relay) {
395  ++m_counts.at(is_outbound).at(m_networks_size + 1); // in/out block-relay
396  ++m_counts.at(2).at(m_networks_size + 1); // total block-relay
397  }
398  if (DetailsRequested()) {
399  // Push data for this peer to the peers vector.
400  const int peer_id{peer["id"].get_int()};
401  const int mapped_as{peer["mapped_as"].isNull() ? 0 : peer["mapped_as"].get_int()};
402  const int version{peer["version"].get_int()};
403  const int64_t conn_time{peer["conntime"].get_int64()};
404  const int64_t last_blck{peer["last_block"].get_int64()};
405  const int64_t last_recv{peer["lastrecv"].get_int64()};
406  const int64_t last_send{peer["lastsend"].get_int64()};
407  const int64_t last_trxn{peer["last_transaction"].get_int64()};
408  const double min_ping{peer["minping"].isNull() ? -1 : peer["minping"].get_real()};
409  const double ping{peer["pingtime"].isNull() ? -1 : peer["pingtime"].get_real()};
410  const std::string addr{peer["addr"].get_str()};
411  const std::string age{conn_time == 0 ? "" : ToString((m_time_now - conn_time) / 60)};
412  const std::string sub_version{peer["subver"].get_str()};
413  m_peers.push_back({addr, sub_version, network, age, min_ping, ping, last_blck, last_recv, last_send, last_trxn, peer_id, mapped_as, version, is_block_relay, is_outbound});
414  m_max_addr_length = std::max(addr.length() + 1, m_max_addr_length);
415  m_max_age_length = std::max(age.length(), m_max_age_length);
416  m_max_id_length = std::max(ToString(peer_id).length(), m_max_id_length);
417  m_is_asmap_on |= (mapped_as != 0);
418  }
419  }
420 
421  // Generate report header.
422  std::string result{strprintf("%s %s%s - %i%s\n\n", PACKAGE_NAME, FormatFullVersion(), ChainToString(), networkinfo["protocolversion"].get_int(), networkinfo["subversion"].get_str())};
423 
424  // Report detailed peer connections list sorted by direction and minimum ping time.
425  if (DetailsRequested() && !m_peers.empty()) {
426  std::sort(m_peers.begin(), m_peers.end());
427  result += strprintf("Peer connections sorted by direction and min ping\n<-> relay net mping ping send recv txn blk %*s ", m_max_age_length, "age");
428  if (m_is_asmap_on) result += " asmap ";
429  result += strprintf("%*s %-*s%s\n", m_max_id_length, "id", IsAddressSelected() ? m_max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
430  for (const Peer& peer : m_peers) {
431  std::string version{ToString(peer.version) + peer.sub_version};
432  result += strprintf(
433  "%3s %5s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s\n",
434  peer.is_outbound ? "out" : "in",
435  peer.is_block_relay ? "block" : "full",
436  peer.network,
437  PingTimeToString(peer.min_ping),
438  PingTimeToString(peer.ping),
439  peer.last_send == 0 ? "" : ToString(m_time_now - peer.last_send),
440  peer.last_recv == 0 ? "" : ToString(m_time_now - peer.last_recv),
441  peer.last_trxn == 0 ? "" : ToString((m_time_now - peer.last_trxn) / 60),
442  peer.last_blck == 0 ? "" : ToString((m_time_now - peer.last_blck) / 60),
443  m_max_age_length, // variable spacing
444  peer.age,
445  m_is_asmap_on ? 7 : 0, // variable spacing
446  m_is_asmap_on && peer.mapped_as != 0 ? ToString(peer.mapped_as) : "",
447  m_max_id_length, // variable spacing
448  peer.id,
449  IsAddressSelected() ? m_max_addr_length : 0, // variable spacing
450  IsAddressSelected() ? peer.addr : "",
451  IsVersionSelected() && version != "0" ? version : "");
452  }
453  result += strprintf(" ms ms sec sec min min %*s\n\n", m_max_age_length, "min");
454  }
455 
456  // Report peer connection totals by type.
457  result += " ipv4 ipv6 onion total block-relay\n";
458  const std::array<std::string, 3> rows{{"in", "out", "total"}};
459  for (uint8_t i = 0; i < m_networks_size; ++i) {
460  result += strprintf("%-5s %5i %5i %5i %5i %5i\n", rows.at(i), m_counts.at(i).at(0), m_counts.at(i).at(1), m_counts.at(i).at(2), m_counts.at(i).at(m_networks_size), m_counts.at(i).at(m_networks_size + 1));
461  }
462 
463  // Report local addresses, ports, and scores.
464  result += "\nLocal addresses";
465  const std::vector<UniValue>& local_addrs{networkinfo["localaddresses"].getValues()};
466  if (local_addrs.empty()) {
467  result += ": n/a\n";
468  } else {
469  size_t max_addr_size{0};
470  for (const UniValue& addr : local_addrs) {
471  max_addr_size = std::max(addr["address"].get_str().length() + 1, max_addr_size);
472  }
473  for (const UniValue& addr : local_addrs) {
474  result += strprintf("\n%-*s port %6i score %6i", max_addr_size, addr["address"].get_str(), addr["port"].get_int(), addr["score"].get_int());
475  }
476  }
477 
478  return JSONRPCReplyObj(UniValue{result}, NullUniValue, 1);
479  }
480 };
481 
484 {
485 public:
486  UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
487  {
488  address_str = args.at(1);
489  UniValue params{RPCConvertValues("generatetoaddress", args)};
490  return JSONRPCRequestObj("generatetoaddress", params, 1);
491  }
492 
493  UniValue ProcessReply(const UniValue &reply) override
494  {
495  UniValue result(UniValue::VOBJ);
496  result.pushKV("address", address_str);
497  result.pushKV("blocks", reply.get_obj()["result"]);
498  return JSONRPCReplyObj(result, NullUniValue, 1);
499  }
500 protected:
501  std::string address_str;
502 };
503 
506 public:
507  UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
508  {
509  UniValue params;
510  if(gArgs.GetBoolArg("-named", DEFAULT_NAMED)) {
511  params = RPCConvertNamedValues(method, args);
512  } else {
513  params = RPCConvertValues(method, args);
514  }
515  return JSONRPCRequestObj(method, params, 1);
516  }
517 
518  UniValue ProcessReply(const UniValue &reply) override
519  {
520  return reply.get_obj();
521  }
522 };
523 
524 static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const Optional<std::string>& rpcwallet = {})
525 {
526  std::string host;
527  // In preference order, we choose the following for the port:
528  // 1. -rpcport
529  // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
530  // 3. default port for chain
531  int port = BaseParams().RPCPort();
532  SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
533  port = gArgs.GetArg("-rpcport", port);
534 
535  // Obtain event base
536  raii_event_base base = obtain_event_base();
537 
538  // Synchronously look up hostname
539  raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port);
540 
541  // Set connection timeout
542  {
543  const int timeout = gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT);
544  if (timeout > 0) {
545  evhttp_connection_set_timeout(evcon.get(), timeout);
546  } else {
547  // Indefinite request timeouts are not possible in libevent-http, so we
548  // set the timeout to a very long time period instead.
549 
550  constexpr int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar
551  evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
552  }
553  }
554 
555  HTTPReply response;
556  raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response);
557  if (req == nullptr)
558  throw std::runtime_error("create http request failed");
559 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
560  evhttp_request_set_error_cb(req.get(), http_error_cb);
561 #endif
562 
563  // Get credentials
564  std::string strRPCUserColonPass;
565  bool failedToGetAuthCookie = false;
566  if (gArgs.GetArg("-rpcpassword", "") == "") {
567  // Try fall back to cookie-based authentication if no password is provided
568  if (!GetAuthCookie(&strRPCUserColonPass)) {
569  failedToGetAuthCookie = true;
570  }
571  } else {
572  strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", "");
573  }
574 
575  struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
576  assert(output_headers);
577  evhttp_add_header(output_headers, "Host", host.c_str());
578  evhttp_add_header(output_headers, "Connection", "close");
579  evhttp_add_header(output_headers, "Content-Type", "application/json");
580  evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());
581 
582  // Attach request data
583  std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n";
584  struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
585  assert(output_buffer);
586  evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
587 
588  // check if we should use a special wallet endpoint
589  std::string endpoint = "/";
590  if (rpcwallet) {
591  char* encodedURI = evhttp_uriencode(rpcwallet->data(), rpcwallet->size(), false);
592  if (encodedURI) {
593  endpoint = "/wallet/" + std::string(encodedURI);
594  free(encodedURI);
595  } else {
596  throw CConnectionFailed("uri-encode failed");
597  }
598  }
599  int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, endpoint.c_str());
600  req.release(); // ownership moved to evcon in above call
601  if (r != 0) {
602  throw CConnectionFailed("send http request failed");
603  }
604 
605  event_base_dispatch(base.get());
606 
607  if (response.status == 0) {
608  std::string responseErrorMessage;
609  if (response.error != -1) {
610  responseErrorMessage = strprintf(" (error code %d - \"%s\")", response.error, http_errorstring(response.error));
611  }
612  throw CConnectionFailed(strprintf("Could not connect to the server %s:%d%s\n\nMake sure the bitcoind server is running and that you are connecting to the correct RPC port.", host, port, responseErrorMessage));
613  } else if (response.status == HTTP_UNAUTHORIZED) {
614  if (failedToGetAuthCookie) {
615  throw std::runtime_error(strprintf(
616  "Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
617  GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()));
618  } else {
619  throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
620  }
621  } else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
622  throw std::runtime_error(strprintf("server returned HTTP error %d", response.status));
623  else if (response.body.empty())
624  throw std::runtime_error("no response from server");
625 
626  // Parse reply
627  UniValue valReply(UniValue::VSTR);
628  if (!valReply.read(response.body))
629  throw std::runtime_error("couldn't parse reply from server");
630  const UniValue reply = rh->ProcessReply(valReply);
631  if (reply.empty())
632  throw std::runtime_error("expected reply to have result, error and id properties");
633 
634  return reply;
635 }
636 
646 static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const Optional<std::string>& rpcwallet = {})
647 {
648  UniValue response(UniValue::VOBJ);
649  // Execute and handle connection failures with -rpcwait.
650  const bool fWait = gArgs.GetBoolArg("-rpcwait", false);
651  do {
652  try {
653  response = CallRPC(rh, strMethod, args, rpcwallet);
654  if (fWait) {
655  const UniValue& error = find_value(response, "error");
656  if (!error.isNull() && error["code"].get_int() == RPC_IN_WARMUP) {
657  throw CConnectionFailed("server in warmup");
658  }
659  }
660  break; // Connection succeeded, no need to retry.
661  } catch (const CConnectionFailed&) {
662  if (fWait) {
663  UninterruptibleSleep(std::chrono::milliseconds{1000});
664  } else {
665  throw;
666  }
667  }
668  } while (fWait);
669  return response;
670 }
671 
673 static void ParseResult(const UniValue& result, std::string& strPrint)
674 {
675  if (result.isNull()) return;
676  strPrint = result.isStr() ? result.get_str() : result.write(2);
677 }
678 
680 static void ParseError(const UniValue& error, std::string& strPrint, int& nRet)
681 {
682  if (error.isObject()) {
683  const UniValue& err_code = find_value(error, "code");
684  const UniValue& err_msg = find_value(error, "message");
685  if (!err_code.isNull()) {
686  strPrint = "error code: " + err_code.getValStr() + "\n";
687  }
688  if (err_msg.isStr()) {
689  strPrint += ("error message:\n" + err_msg.get_str());
690  }
691  if (err_code.isNum() && err_code.get_int() == RPC_WALLET_NOT_SPECIFIED) {
692  strPrint += "\nTry adding \"-rpcwallet=<filename>\" option to bitcoin-cli command line.";
693  }
694  } else {
695  strPrint = "error: " + error.write();
696  }
697  nRet = abs(error["code"].get_int());
698 }
699 
706 static void GetWalletBalances(UniValue& result)
707 {
709  const UniValue listwallets = ConnectAndCallRPC(&rh, "listwallets", /* args=*/{});
710  if (!find_value(listwallets, "error").isNull()) return;
711  const UniValue& wallets = find_value(listwallets, "result");
712  if (wallets.size() <= 1) return;
713 
714  UniValue balances(UniValue::VOBJ);
715  for (const UniValue& wallet : wallets.getValues()) {
716  const std::string wallet_name = wallet.get_str();
717  const UniValue getbalances = ConnectAndCallRPC(&rh, "getbalances", /* args=*/{}, wallet_name);
718  const UniValue& balance = find_value(getbalances, "result")["mine"]["trusted"];
719  balances.pushKV(wallet_name, balance);
720  }
721  result.pushKV("balances", balances);
722 }
723 
729 {
730  Optional<std::string> wallet_name{};
731  if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", "");
733  return ConnectAndCallRPC(&rh, "getnewaddress", /* args=*/{}, wallet_name);
734 }
735 
741 static void SetGenerateToAddressArgs(const std::string& address, std::vector<std::string>& args)
742 {
743  if (args.size() > 2) throw std::runtime_error("too many arguments (maximum 2 for nblocks and maxtries)");
744  if (args.size() == 0) {
745  args.emplace_back(DEFAULT_NBLOCKS);
746  } else if (args.at(0) == "0") {
747  throw std::runtime_error("the first argument (number of blocks to generate, default: " + DEFAULT_NBLOCKS + ") must be an integer value greater than zero");
748  }
749  args.emplace(args.begin() + 1, address);
750 }
751 
752 static int CommandLineRPC(int argc, char *argv[])
753 {
754  std::string strPrint;
755  int nRet = 0;
756  try {
757  // Skip switches
758  while (argc > 1 && IsSwitchChar(argv[1][0])) {
759  argc--;
760  argv++;
761  }
762  std::string rpcPass;
763  if (gArgs.GetBoolArg("-stdinrpcpass", false)) {
764  NO_STDIN_ECHO();
765  if (!StdinReady()) {
766  fputs("RPC password> ", stderr);
767  fflush(stderr);
768  }
769  if (!std::getline(std::cin, rpcPass)) {
770  throw std::runtime_error("-stdinrpcpass specified but failed to read from standard input");
771  }
772  if (StdinTerminal()) {
773  fputc('\n', stdout);
774  }
775  gArgs.ForceSetArg("-rpcpassword", rpcPass);
776  }
777  std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
778  if (gArgs.GetBoolArg("-stdinwalletpassphrase", false)) {
779  NO_STDIN_ECHO();
780  std::string walletPass;
781  if (args.size() < 1 || args[0].substr(0, 16) != "walletpassphrase") {
782  throw std::runtime_error("-stdinwalletpassphrase is only applicable for walletpassphrase(change)");
783  }
784  if (!StdinReady()) {
785  fputs("Wallet passphrase> ", stderr);
786  fflush(stderr);
787  }
788  if (!std::getline(std::cin, walletPass)) {
789  throw std::runtime_error("-stdinwalletpassphrase specified but failed to read from standard input");
790  }
791  if (StdinTerminal()) {
792  fputc('\n', stdout);
793  }
794  args.insert(args.begin() + 1, walletPass);
795  }
796  if (gArgs.GetBoolArg("-stdin", false)) {
797  // Read one arg per line from stdin and append
798  std::string line;
799  while (std::getline(std::cin, line)) {
800  args.push_back(line);
801  }
802  if (StdinTerminal()) {
803  fputc('\n', stdout);
804  }
805  }
806  std::unique_ptr<BaseRequestHandler> rh;
807  std::string method;
808  if (gArgs.IsArgSet("-getinfo")) {
809  rh.reset(new GetinfoRequestHandler());
810  } else if (gArgs.GetBoolArg("-netinfo", false)) {
811  rh.reset(new NetinfoRequestHandler());
812  } else if (gArgs.GetBoolArg("-generate", false)) {
814  const UniValue& error{find_value(getnewaddress, "error")};
815  if (error.isNull()) {
816  SetGenerateToAddressArgs(find_value(getnewaddress, "result").get_str(), args);
817  rh.reset(new GenerateToAddressRequestHandler());
818  } else {
819  ParseError(error, strPrint, nRet);
820  }
821  } else {
822  rh.reset(new DefaultRequestHandler());
823  if (args.size() < 1) {
824  throw std::runtime_error("too few parameters (need at least command)");
825  }
826  method = args[0];
827  args.erase(args.begin()); // Remove trailing method name from arguments vector
828  }
829  if (nRet == 0) {
830  // Perform RPC call
831  Optional<std::string> wallet_name{};
832  if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", "");
833  const UniValue reply = ConnectAndCallRPC(rh.get(), method, args, wallet_name);
834 
835  // Parse reply
836  UniValue result = find_value(reply, "result");
837  const UniValue& error = find_value(reply, "error");
838  if (error.isNull()) {
839  if (gArgs.IsArgSet("-getinfo") && !gArgs.IsArgSet("-rpcwallet")) {
840  GetWalletBalances(result); // fetch multiwallet balances and append to result
841  }
842  ParseResult(result, strPrint);
843  } else {
844  ParseError(error, strPrint, nRet);
845  }
846  }
847  } catch (const std::exception& e) {
848  strPrint = std::string("error: ") + e.what();
849  nRet = EXIT_FAILURE;
850  } catch (...) {
851  PrintExceptionContinue(nullptr, "CommandLineRPC()");
852  throw;
853  }
854 
855  if (strPrint != "") {
856  tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
857  }
858  return nRet;
859 }
860 
861 #ifdef WIN32
862 // Export main() and ensure working ASLR on Windows.
863 // Exporting a symbol will prevent the linker from stripping
864 // the .reloc section from the binary, which is a requirement
865 // for ASLR. This is a temporary workaround until a fixed
866 // version of binutils is used for releases.
867 __declspec(dllexport) int main(int argc, char* argv[])
868 {
869  util::WinCmdLineArgs winArgs;
870  std::tie(argc, argv) = winArgs.get();
871 #else
872 int main(int argc, char* argv[])
873 {
874 #endif
876  if (!SetupNetworking()) {
877  tfm::format(std::cerr, "Error: Initializing networking failed\n");
878  return EXIT_FAILURE;
879  }
880  event_set_log_callback(&libevent_log_cb);
881 
882  try {
883  int ret = AppInitRPC(argc, argv);
884  if (ret != CONTINUE_EXECUTION)
885  return ret;
886  }
887  catch (const std::exception& e) {
888  PrintExceptionContinue(&e, "AppInitRPC()");
889  return EXIT_FAILURE;
890  } catch (...) {
891  PrintExceptionContinue(nullptr, "AppInitRPC()");
892  return EXIT_FAILURE;
893  }
894 
895  int ret = EXIT_FAILURE;
896  try {
897  ret = CommandLineRPC(argc, argv);
898  }
899  catch (const std::exception& e) {
900  PrintExceptionContinue(&e, "CommandLineRPC()");
901  } catch (...) {
902  PrintExceptionContinue(nullptr, "CommandLineRPC()");
903  }
904  return ret;
905 }
NODISCARD bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:845
int get_int() const
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:80
static const std::string DEFAULT_NBLOCKS
Default number of blocks to generate for RPC generatetoaddress.
Definition: bitcoin-cli.cpp:46
static RPCHelpMan ping()
Definition: net.cpp:64
bool StdinTerminal()
Definition: stdin.cpp:47
const std::string & get_str() const
std::unique_ptr< CBaseChainParams > CreateBaseChainParams(const std::string &chain)
Port numbers for incoming Tor connections (8334, 18334, 38334, 18445) have been chosen arbitrarily to...
size_t size() const
Definition: univalue.h:68
bool StdinReady()
Definition: stdin.cpp:56
static int CommandLineRPC(int argc, char *argv[])
static UniValue ConnectAndCallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args, const Optional< std::string > &rpcwallet={})
ConnectAndCallRPC wraps CallRPC with -rpcwait and an exception handler.
raii_event_base obtain_event_base()
Definition: events.h:30
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
static int AppInitRPC(int argc, char *argv[])
std::string PingTimeToString(double seconds) const
static void libevent_log_cb(int severity, const char *msg)
libevent event log callback
Definition: bitcoin-cli.cpp:80
static const std::string REGTEST
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:479
static std::string strRPCUserColonPass
Definition: httprpc.cpp:68
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
UrlDecodeFn urlDecode
Definition: url.h:11
static constexpr int ID_NETWORKINFO
UniValue ProcessReply(const UniValue &reply) override
static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args, const Optional< std::string > &rpcwallet={})
bool empty() const
Definition: univalue.h:66
const std::vector< UniValue > & getValues() const
virtual ~BaseRequestHandler()
static const int DEFAULT_HTTP_CLIENT_TIMEOUT
Definition: bitcoin-cli.cpp:41
void SetupEnvironment()
Definition: system.cpp:1228
static constexpr int ID_PEERINFO
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
#define PACKAGE_NAME
void format(std::ostream &out, const char *fmt, const Args &...args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1062
static RPCHelpMan listwallets()
Definition: rpcwallet.cpp:2559
raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg)
Definition: events.h:45
NODISCARD bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: system.cpp:284
std::vector< Peer > m_peers
static std::string http_errorstring(int code)
uint8_t m_details_level
Optional user-supplied arg to set dashboard details level.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: system.cpp:501
bool IsVersionSelected() const
const char *const BITCOIN_CONF_FILENAME
Definition: system.cpp:74
bool SetupNetworking()
Definition: system.cpp:1265
int64_t GetSystemTimeInSeconds()
Returns the system time (not mockable)
Definition: time.cpp:76
Client still warming up.
Definition: protocol.h:49
#define NO_STDIN_ECHO()
Definition: stdin.h:13
virtual UniValue ProcessReply(const UniValue &batch_in)=0
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
Create a simulated getinfo request.
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:234
static const std::string MAIN
Chain name strings.
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:238
bool CheckDataDirOption()
Definition: system.cpp:751
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in)
Parse JSON-RPC batch reply into a vector.
Definition: request.cpp:133
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:71
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:371
std::string EncodeBase64(Span< const unsigned char > input)
bool error(const char *fmt, const Args &...args)
Definition: system.h:52
static const char DEFAULT_RPCCONNECT[]
Definition: bitcoin-cli.cpp:40
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
std::array< std::array< uint16_t, m_networks_size+2 >, 3 > m_counts
Peer counts by (in/out/total, networks/total/block-relay)
static CAmount balance
static void ParseError(const UniValue &error, std::string &strPrint, int &nRet)
Parse UniValue error to update the message to print to std::cerr and the code to return.
bool isNum() const
Definition: univalue.h:82
static secp256k1_context * ctx
Definition: tests.c:36
Process netinfo requests.
static RPCHelpMan getbalances()
Definition: rpcwallet.cpp:2359
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: system.cpp:507
bool HelpRequested(const ArgsManager &args)
Definition: system.cpp:602
#define EVENT_LOG_ERR
static const uint64_t DEFAULT_MAX_TRIES
Default max iterations to try in RPC generatetodescriptor, generatetoaddress, and generateblock...
Definition: mining.h:9
static const int CONTINUE_EXECUTION
Definition: bitcoin-cli.cpp:43
virtual UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args)=0
raii_evhttp_connection obtain_evhttp_connection_base(struct event_base *base, std::string host, uint16_t port)
Definition: events.h:49
static void GetWalletBalances(UniValue &result)
GetWalletBalances calls listwallets; if more than one wallet is loaded, it then fetches mine...
uint16_t RPCPort() const
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: system.cpp:644
int main(int argc, char *argv[])
bool DetailsRequested() const
UniValue ProcessReply(const UniValue &batch_in) override
Collect values from the batch and form a simulated getinfo reply.
Class that handles the conversion from a command-line to a JSON-RPC request, as well as converting ba...
std::string FormatFullVersion()
const int64_t m_time_now
static constexpr int8_t UNKNOWN_NETWORK
static void SetupCliArgs(ArgsManager &argsman)
Definition: bitcoin-cli.cpp:48
static void ParseResult(const UniValue &result, std::string &strPrint)
Parse UniValue result to update the message to print to std::cout.
CConnectionFailed(const std::string &msg)
Definition: bitcoin-cli.cpp:99
bool IsAddressSelected() const
const std::string & getValStr() const
Definition: univalue.h:65
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:21
fs::path GetConfigFile(const std::string &confPath)
Definition: system.cpp:766
const std::array< std::string, m_networks_size > m_networks
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:467
Process RPC generatetoaddress request.
std::string GetHelpMessage() const
Get the help string.
Definition: system.cpp:533
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:33
Process default single requests.
ArgsManager gArgs
Definition: system.cpp:77
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
Definition: bitcoin-cli.cpp:37
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params, const UniValue &id)
JSON-RPC protocol.
Definition: request.cpp:24
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
Definition: system.cpp:607
static RPCHelpMan getnewaddress()
Definition: rpcwallet.cpp:233
std::string body
const UniValue NullUniValue
Definition: univalue.cpp:13
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
bool operator<(const Peer &rhs) const
UrlDecodeFn *const URL_DECODE
Definition: bitcoin-cli.cpp:38
int8_t NetworkStringToId(const std::string &str) const
std::string ChainToString() const
UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert named arguments to command-specific RPC representation.
Definition: client.cpp:257
static const std::string TESTNET
bool isObject() const
Definition: univalue.h:84
static const bool DEFAULT_NAMED
Definition: bitcoin-cli.cpp:42
static UniValue GetNewAddress()
Call RPC getnewaddress.
std::string GetChainName() const
Returns the appropriate chain name from the program arguments.
Definition: system.cpp:932
bool IsSwitchChar(char c)
Definition: system.h:122
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
bool ParseUInt8(const std::string &str, uint8_t *out)
Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:14
static constexpr uint8_t m_networks_size
UniValue ProcessReply(const UniValue &batch_in) override
void SelectBaseParams(const std::string &chain)
Sets the params returned by Params() to those for the given network.
const UniValue & get_obj() const
bool isNull() const
Definition: univalue.h:77
Process getinfo requests.
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
Definition: request.cpp:108
static const std::string SIGNET
static void SetGenerateToAddressArgs(const std::string &address, std::vector< std::string > &args)
Check bounds and set up args for RPC generatetoaddress params: nblocks, address, maxtries.
bool isStr() const
Definition: univalue.h:81
static void http_request_done(struct evhttp_request *req, void *ctx)
Reply structure for request_done to fill in.
UniValue ProcessReply(const UniValue &reply) override
std::string(const std::string &url_encoded) UrlDecodeFn
Definition: url.h:10
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)