Bitcoin ABC  0.26.3
P2P Digital Currency
bitcoin-cli.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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)
7 #include <config/bitcoin-config.h>
8 #endif
9 
10 #include <chainparamsbase.h>
11 #include <clientversion.h>
12 #include <common/args.h>
13 #include <common/system.h>
14 #include <currencyunit.h>
15 #include <rpc/client.h>
16 #include <rpc/mining.h>
17 #include <rpc/protocol.h>
18 #include <rpc/request.h>
19 #include <support/events.h>
20 #include <tinyformat.h>
21 #include <util/exception.h>
22 #include <util/strencodings.h>
23 #include <util/string.h>
24 #include <util/time.h>
25 #include <util/translation.h>
26 
27 #include <event2/buffer.h>
28 #include <event2/keyvalq_struct.h>
29 
30 #include <compat/stdin.h>
31 #include <univalue.h>
32 
33 #include <algorithm>
34 #include <chrono>
35 #include <cmath>
36 #include <cstdio>
37 #include <functional>
38 #include <memory>
39 #include <string>
40 #include <tuple>
41 
42 // The server returns time values from a mockable system clock, but it is not
43 // trivial to get the mocked time from the server, nor is it needed for now, so
44 // just use a plain system_clock.
45 using CliClock = std::chrono::system_clock;
46 
47 const std::function<std::string(const char *)> G_TRANSLATION_FUN = nullptr;
48 
49 static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
50 static const int DEFAULT_HTTP_CLIENT_TIMEOUT = 900;
51 static const bool DEFAULT_NAMED = false;
52 static const int CONTINUE_EXECUTION = -1;
54 static const std::string DEFAULT_NBLOCKS = "1";
55 
56 static void SetupCliArgs(ArgsManager &argsman) {
57  SetupHelpOptions(argsman);
58 
59  const auto defaultBaseParams =
61  const auto testnetBaseParams =
63  const auto regtestBaseParams =
65 
66  SetupCurrencyUnitOptions(argsman);
67  argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY,
69  argsman.AddArg(
70  "-conf=<file>",
71  strprintf("Specify configuration file. Relative paths will be "
72  "prefixed by datadir location. (default: %s)",
75  argsman.AddArg("-datadir=<dir>", "Specify data directory",
77  argsman.AddArg(
78  "-generate",
79  strprintf(
80  "Generate blocks immediately, equivalent to RPC getnewaddress "
81  "followed by RPC generatetoaddress. Optional positional integer "
82  "arguments are number of blocks to generate (default: %s) and "
83  "maximum iterations to try (default: %s), equivalent to RPC "
84  "generatetoaddress nblocks and maxtries arguments. Example: "
85  "bitcoin-cli -generate 4 1000",
88  argsman.AddArg(
89  "-getinfo",
90  "Get general information from the remote server. Note that unlike "
91  "server-side RPC calls, the results of -getinfo is the result of "
92  "multiple non-atomic requests. Some entries in the result may "
93  "represent results from different states (e.g. wallet balance may be "
94  "as of a different block from the chain state reported)",
96  argsman.AddArg("-netinfo",
97  "Get network peer connection information from the remote "
98  "server. An optional integer argument from 0 to 4 can be "
99  "passed for different peers listings (default: 0).",
101 
103  argsman.AddArg(
104  "-named",
105  strprintf("Pass named instead of positional arguments (default: %s)",
106  DEFAULT_NAMED),
108  argsman.AddArg(
109  "-rpcconnect=<ip>",
110  strprintf("Send commands to node running on <ip> (default: %s)",
113  argsman.AddArg(
114  "-rpccookiefile=<loc>",
115  "Location of the auth cookie. Relative paths will be prefixed "
116  "by a net-specific datadir location. (default: data dir)",
118  argsman.AddArg("-rpcport=<port>",
119  strprintf("Connect to JSON-RPC on <port> (default: %u, "
120  "testnet: %u, regtest: %u)",
121  defaultBaseParams->RPCPort(),
122  testnetBaseParams->RPCPort(),
123  regtestBaseParams->RPCPort()),
126  argsman.AddArg("-rpcwait", "Wait for RPC server to start",
128  argsman.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections",
130  argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections",
132  argsman.AddArg(
133  "-rpcclienttimeout=<n>",
134  strprintf("Timeout in seconds during HTTP requests, or 0 for "
135  "no timeout. (default: %d)",
138 
139  argsman.AddArg("-stdinrpcpass",
140  "Read RPC password from standard input as a single "
141  "line. When combined with -stdin, the first line "
142  "from standard input is used for the RPC password. When "
143  "combined with -stdinwalletpassphrase, -stdinrpcpass "
144  "consumes the first line, and -stdinwalletpassphrase "
145  "consumes the second.",
147  argsman.AddArg("-stdinwalletpassphrase",
148  "Read wallet passphrase from standard input as a single "
149  "line. When combined with -stdin, the first line "
150  "from standard input is used for the wallet passphrase.",
152  argsman.AddArg(
153  "-stdin",
154  "Read extra arguments from standard input, one per line until "
155  "EOF/Ctrl-D (recommended for sensitive information such as "
156  "passphrases). When combined with -stdinrpcpass, the first "
157  "line from standard input is used for the RPC password.",
159  argsman.AddArg(
160  "-rpcwallet=<walletname>",
161  "Send RPC for non-default wallet on RPC server (needs to exactly match "
162  "corresponding -wallet option passed to bitcoind). This changes the "
163  "RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname>",
165 }
166 
168 static void libevent_log_cb(int severity, const char *msg) {
169 #ifndef EVENT_LOG_ERR
170 // EVENT_LOG_ERR was added in 2.0.19; but before then _EVENT_LOG_ERR existed.
171 #define EVENT_LOG_ERR _EVENT_LOG_ERR
172 #endif
173  // Ignore everything other than errors
174  if (severity >= EVENT_LOG_ERR) {
175  throw std::runtime_error(strprintf("libevent error: %s", msg));
176  }
177 }
178 
180 //
181 // Start
182 //
183 
184 //
185 // Exception thrown on connection error. This error is used to determine when
186 // to wait if -rpcwait is given.
187 //
188 class CConnectionFailed : public std::runtime_error {
189 public:
190  explicit inline CConnectionFailed(const std::string &msg)
191  : std::runtime_error(msg) {}
192 };
193 
194 //
195 // This function returns either one of EXIT_ codes when it's expected to stop
196 // the process or CONTINUE_EXECUTION when it's expected to continue further.
197 //
198 static int AppInitRPC(int argc, char *argv[]) {
199  //
200  // Parameters
201  //
203  std::string error;
204  if (!gArgs.ParseParameters(argc, argv, error)) {
205  tfm::format(std::cerr, "Error parsing command line arguments: %s\n",
206  error);
207  return EXIT_FAILURE;
208  }
209  if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
210  std::string strUsage =
211  PACKAGE_NAME " RPC client version " + FormatFullVersion() + "\n";
212 
213  if (gArgs.IsArgSet("-version")) {
214  strUsage += FormatParagraph(LicenseInfo());
215  } else {
216  strUsage += "\n"
217  "Usage: bitcoin-cli [options] <command> [params] "
218  "Send command to " PACKAGE_NAME "\n"
219  "or: bitcoin-cli [options] -named <command> "
220  "[name=value]... Send command to " PACKAGE_NAME
221  " (with named arguments)\n"
222  "or: bitcoin-cli [options] help "
223  "List commands\n"
224  "or: bitcoin-cli [options] help <command> Get "
225  "help for a command\n";
226 
227  strUsage += "\n" + gArgs.GetHelpMessage();
228  }
229 
230  tfm::format(std::cout, "%s", strUsage);
231  if (argc < 2) {
232  tfm::format(std::cerr, "Error: too few parameters\n");
233  return EXIT_FAILURE;
234  }
235  return EXIT_SUCCESS;
236  }
237  if (!CheckDataDirOption(gArgs)) {
238  tfm::format(std::cerr,
239  "Error: Specified data directory \"%s\" does not exist.\n",
240  gArgs.GetArg("-datadir", ""));
241  return EXIT_FAILURE;
242  }
243  if (!gArgs.ReadConfigFiles(error, true)) {
244  tfm::format(std::cerr, "Error reading configuration file: %s\n", error);
245  return EXIT_FAILURE;
246  }
247  // Check for -chain, -testnet or -regtest parameter (BaseParams() calls are
248  // only valid after this clause)
249  try {
251  } catch (const std::exception &e) {
252  tfm::format(std::cerr, "Error: %s\n", e.what());
253  return EXIT_FAILURE;
254  }
255  return CONTINUE_EXECUTION;
256 }
257 
259 struct HTTPReply {
260  HTTPReply() : status(0), error(-1) {}
261 
262  int status;
263  int error;
264  std::string body;
265 };
266 
267 static std::string http_errorstring(int code) {
268  switch (code) {
269 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
270  case EVREQ_HTTP_TIMEOUT:
271  return "timeout reached";
272  case EVREQ_HTTP_EOF:
273  return "EOF reached";
274  case EVREQ_HTTP_INVALID_HEADER:
275  return "error while reading header, or invalid header";
276  case EVREQ_HTTP_BUFFER_ERROR:
277  return "error encountered while reading or writing";
278  case EVREQ_HTTP_REQUEST_CANCEL:
279  return "request was canceled";
280  case EVREQ_HTTP_DATA_TOO_LONG:
281  return "response body is larger than allowed";
282 #endif
283  default:
284  return "unknown";
285  }
286 }
287 
288 static void http_request_done(struct evhttp_request *req, void *ctx) {
289  HTTPReply *reply = static_cast<HTTPReply *>(ctx);
290 
291  if (req == nullptr) {
296  reply->status = 0;
297  return;
298  }
299 
300  reply->status = evhttp_request_get_response_code(req);
301 
302  struct evbuffer *buf = evhttp_request_get_input_buffer(req);
303  if (buf) {
304  size_t size = evbuffer_get_length(buf);
305  const char *data = (const char *)evbuffer_pullup(buf, size);
306  if (data) {
307  reply->body = std::string(data, size);
308  }
309  evbuffer_drain(buf, size);
310  }
311 }
312 
313 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
314 static void http_error_cb(enum evhttp_request_error err, void *ctx) {
315  HTTPReply *reply = static_cast<HTTPReply *>(ctx);
316  reply->error = err;
317 }
318 #endif
319 
325 public:
326  virtual ~BaseRequestHandler() {}
327  virtual UniValue PrepareRequest(const std::string &method,
328  const std::vector<std::string> &args) = 0;
329  virtual UniValue ProcessReply(const UniValue &batch_in) = 0;
330 };
331 
334 public:
335  const int ID_NETWORKINFO = 0;
336  const int ID_BLOCKCHAININFO = 1;
337  const int ID_WALLETINFO = 2;
338  const int ID_BALANCES = 3;
339 
341  UniValue PrepareRequest(const std::string &method,
342  const std::vector<std::string> &args) override {
343  if (!args.empty()) {
344  throw std::runtime_error("-getinfo takes no arguments");
345  }
346  UniValue result(UniValue::VARR);
347  result.push_back(
348  JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
349  result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue,
351  result.push_back(
352  JSONRPCRequestObj("getwalletinfo", NullUniValue, ID_WALLETINFO));
353  result.push_back(
354  JSONRPCRequestObj("getbalances", NullUniValue, ID_BALANCES));
355  return result;
356  }
357 
359  UniValue ProcessReply(const UniValue &batch_in) override {
360  UniValue result(UniValue::VOBJ);
361  const std::vector<UniValue> batch = JSONRPCProcessBatchReply(batch_in);
362  // Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass
363  // them on; getwalletinfo() and getbalances are allowed to fail if there
364  // is no wallet.
365  if (!batch[ID_NETWORKINFO]["error"].isNull()) {
366  return batch[ID_NETWORKINFO];
367  }
368  if (!batch[ID_BLOCKCHAININFO]["error"].isNull()) {
369  return batch[ID_BLOCKCHAININFO];
370  }
371  result.pushKV("version", batch[ID_NETWORKINFO]["result"]["version"]);
372  result.pushKV("blocks", batch[ID_BLOCKCHAININFO]["result"]["blocks"]);
373  result.pushKV("headers", batch[ID_BLOCKCHAININFO]["result"]["headers"]);
374  result.pushKV(
375  "verificationprogress",
376  batch[ID_BLOCKCHAININFO]["result"]["verificationprogress"]);
377  result.pushKV("timeoffset",
378  batch[ID_NETWORKINFO]["result"]["timeoffset"]);
379 
380  UniValue connections(UniValue::VOBJ);
381  connections.pushKV("in",
382  batch[ID_NETWORKINFO]["result"]["connections_in"]);
383  connections.pushKV("out",
384  batch[ID_NETWORKINFO]["result"]["connections_out"]);
385  connections.pushKV("total",
386  batch[ID_NETWORKINFO]["result"]["connections"]);
387  result.pushKV("connections", connections);
388 
389  result.pushKV("proxy",
390  batch[ID_NETWORKINFO]["result"]["networks"][0]["proxy"]);
391  result.pushKV("difficulty",
392  batch[ID_BLOCKCHAININFO]["result"]["difficulty"]);
393  result.pushKV("chain",
394  UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"]));
395  if (!batch[ID_WALLETINFO]["result"].isNull()) {
396  result.pushKV("keypoolsize",
397  batch[ID_WALLETINFO]["result"]["keypoolsize"]);
398  if (!batch[ID_WALLETINFO]["result"]["unlocked_until"].isNull()) {
399  result.pushKV("unlocked_until",
400  batch[ID_WALLETINFO]["result"]["unlocked_until"]);
401  }
402  result.pushKV("paytxfee",
403  batch[ID_WALLETINFO]["result"]["paytxfee"]);
404  }
405  if (!batch[ID_BALANCES]["result"].isNull()) {
406  result.pushKV("balance",
407  batch[ID_BALANCES]["result"]["mine"]["trusted"]);
408  }
409  result.pushKV("relayfee", batch[ID_NETWORKINFO]["result"]["relayfee"]);
410  result.pushKV("warnings", batch[ID_NETWORKINFO]["result"]["warnings"]);
411  return JSONRPCReplyObj(result, NullUniValue, 1);
412  }
413 };
414 
417 private:
418  static constexpr int8_t UNKNOWN_NETWORK{-1};
419  static constexpr uint8_t m_networks_size{3};
420  const std::array<std::string, m_networks_size> m_networks{
421  {"ipv4", "ipv6", "onion"}};
423  std::array<std::array<uint16_t, m_networks_size + 2>, 3> m_counts{{{}}};
424  int8_t NetworkStringToId(const std::string &str) const {
425  for (uint8_t i = 0; i < m_networks_size; ++i) {
426  if (str == m_networks.at(i)) {
427  return i;
428  }
429  }
430  return UNKNOWN_NETWORK;
431  }
433  uint8_t m_details_level{0};
434  bool DetailsRequested() const {
435  return m_details_level > 0 && m_details_level < 5;
436  }
437  bool IsAddressSelected() const {
438  return m_details_level == 2 || m_details_level == 4;
439  }
440  bool IsVersionSelected() const {
441  return m_details_level == 3 || m_details_level == 4;
442  }
443  bool m_is_asmap_on{false};
444  size_t m_max_addr_length{0};
445  size_t m_max_age_length{4};
446  size_t m_max_id_length{2};
447  struct Peer {
448  std::string addr;
449  std::string sub_version;
450  std::string network;
451  std::string age;
452  double min_ping;
453  double ping;
454  int64_t last_blck;
455  int64_t last_recv;
456  int64_t last_send;
457  int64_t last_trxn;
458  int id;
460  int version;
463  bool operator<(const Peer &rhs) const {
464  return std::tie(is_outbound, min_ping) <
465  std::tie(rhs.is_outbound, rhs.min_ping);
466  }
467  };
468  std::vector<Peer> m_peers;
469  std::string ChainToString() const {
471  return " testnet";
472  }
474  return " regtest";
475  }
476  return "";
477  }
478  std::string PingTimeToString(double seconds) const {
479  if (seconds < 0) {
480  return "";
481  }
482  const double milliseconds{round(1000 * seconds)};
483  return milliseconds > 999999 ? "-" : ToString(milliseconds);
484  }
485  const int64_t m_time_now{
486  TicksSinceEpoch<std::chrono::seconds>(CliClock::now())};
487 
488 public:
489  static constexpr int ID_PEERINFO = 0;
490  static constexpr int ID_NETWORKINFO = 1;
491 
492  UniValue PrepareRequest(const std::string &method,
493  const std::vector<std::string> &args) override {
494  if (!args.empty()) {
495  uint8_t n{0};
496  if (ParseUInt8(args.at(0), &n)) {
497  m_details_level = n;
498  }
499  }
500  UniValue result(UniValue::VARR);
501  result.push_back(
502  JSONRPCRequestObj("getpeerinfo", NullUniValue, ID_PEERINFO));
503  result.push_back(
504  JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
505  return result;
506  }
507 
508  UniValue ProcessReply(const UniValue &batch_in) override {
509  const std::vector<UniValue> batch{JSONRPCProcessBatchReply(batch_in)};
510  if (!batch[ID_PEERINFO]["error"].isNull()) {
511  return batch[ID_PEERINFO];
512  }
513  if (!batch[ID_NETWORKINFO]["error"].isNull()) {
514  return batch[ID_NETWORKINFO];
515  }
516 
517  const UniValue &networkinfo{batch[ID_NETWORKINFO]["result"]};
518  if (networkinfo["version"].getInt<int>() < 230000) {
519  throw std::runtime_error("-netinfo requires bitcoind server to be "
520  "running v0.23.0 and up");
521  }
522 
523  // Count peer connection totals, and if DetailsRequested(), store peer
524  // data in a vector of structs.
525  for (const UniValue &peer : batch[ID_PEERINFO]["result"].getValues()) {
526  const std::string network{peer["network"].get_str()};
527  const int8_t network_id{NetworkStringToId(network)};
528  if (network_id == UNKNOWN_NETWORK) {
529  continue;
530  }
531  const bool is_outbound{!peer["inbound"].get_bool()};
532  const bool is_block_relay{!peer["relaytxes"].get_bool()};
533  // in/out by network
534  ++m_counts.at(is_outbound).at(network_id);
535  // in/out overall
536  ++m_counts.at(is_outbound).at(m_networks_size);
537  // total by network
538  ++m_counts.at(2).at(network_id);
539  // total overall
540  ++m_counts.at(2).at(m_networks_size);
541  if (is_block_relay) {
542  // in/out block-relay
543  ++m_counts.at(is_outbound).at(m_networks_size + 1);
544  // total block-relay
545  ++m_counts.at(2).at(m_networks_size + 1);
546  }
547  if (DetailsRequested()) {
548  // Push data for this peer to the peers vector.
549  const int peer_id{peer["id"].getInt<int>()};
550  const int mapped_as{peer["mapped_as"].isNull()
551  ? 0
552  : peer["mapped_as"].getInt<int>()};
553  const int version{peer["version"].getInt<int>()};
554  const int64_t conn_time{peer["conntime"].getInt<int64_t>()};
555  const int64_t last_blck{peer["last_block"].getInt<int64_t>()};
556  const int64_t last_recv{peer["lastrecv"].getInt<int64_t>()};
557  const int64_t last_send{peer["lastsend"].getInt<int64_t>()};
558  const int64_t last_trxn{
559  peer["last_transaction"].getInt<int64_t>()};
560  const double min_ping{
561  peer["minping"].isNull() ? -1 : peer["minping"].get_real()};
562  const double ping{peer["pingtime"].isNull()
563  ? -1
564  : peer["pingtime"].get_real()};
565  const std::string addr{peer["addr"].get_str()};
566  const std::string age{
567  conn_time == 0 ? ""
568  : ToString((m_time_now - conn_time) / 60)};
569  const std::string sub_version{peer["subver"].get_str()};
570  m_peers.push_back({addr, sub_version, network, age, min_ping,
571  ping, last_blck, last_recv, last_send,
572  last_trxn, peer_id, mapped_as, version,
573  is_block_relay, is_outbound});
575  std::max(addr.length() + 1, m_max_addr_length);
576  m_max_age_length = std::max(age.length(), m_max_age_length);
578  std::max(ToString(peer_id).length(), m_max_id_length);
579  m_is_asmap_on |= (mapped_as != 0);
580  }
581  }
582 
583  // Generate report header.
584  std::string result{strprintf(
585  "%s %s%s - %i%s\n\n", PACKAGE_NAME, FormatFullVersion(),
586  ChainToString(), networkinfo["protocolversion"].getInt<int>(),
587  networkinfo["subversion"].get_str())};
588 
589  // Report detailed peer connections list sorted by direction and minimum
590  // ping time.
591  if (DetailsRequested() && !m_peers.empty()) {
592  std::sort(m_peers.begin(), m_peers.end());
593  result += strprintf(
594  "Peer connections sorted by direction and min ping\n<-> relay "
595  " net mping ping send recv txn blk %*s ",
596  m_max_age_length, "age");
597  if (m_is_asmap_on) {
598  result += " asmap ";
599  }
600  result += strprintf("%*s %-*s%s\n", m_max_id_length, "id",
602  IsAddressSelected() ? "address" : "",
603  IsVersionSelected() ? "version" : "");
604  for (const Peer &peer : m_peers) {
605  std::string version{ToString(peer.version) + peer.sub_version};
606  result += strprintf(
607  "%3s %5s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s\n",
608  peer.is_outbound ? "out" : "in",
609  peer.is_block_relay ? "block" : "full", peer.network,
610  PingTimeToString(peer.min_ping),
611  PingTimeToString(peer.ping),
612  peer.last_send == 0 ? ""
613  : ToString(m_time_now - peer.last_send),
614  peer.last_recv == 0 ? ""
615  : ToString(m_time_now - peer.last_recv),
616  peer.last_trxn == 0
617  ? ""
618  : ToString((m_time_now - peer.last_trxn) / 60),
619  peer.last_blck == 0
620  ? ""
621  : ToString((m_time_now - peer.last_blck) / 60),
622  // variable spacing
623  m_max_age_length, peer.age,
624  // variable spacing
625  m_is_asmap_on ? 7 : 0,
626  m_is_asmap_on && peer.mapped_as != 0
627  ? ToString(peer.mapped_as)
628  : "",
629  // variable spacing
630  m_max_id_length, peer.id,
631  // variable spacing
633  IsAddressSelected() ? peer.addr : "",
634  IsVersionSelected() && version != "0" ? version : "");
635  }
636  result += strprintf(
637  " ms ms sec sec min min %*s\n\n",
638  m_max_age_length, "min");
639  }
640 
641  // Report peer connection totals by type.
642  result += " ipv4 ipv6 onion total block-relay\n";
643  const std::array<std::string, 3> rows{{"in", "out", "total"}};
644  for (uint8_t i = 0; i < m_networks_size; ++i) {
645  result += strprintf("%-5s %5i %5i %5i %5i %5i\n",
646  rows.at(i), m_counts.at(i).at(0),
647  m_counts.at(i).at(1), m_counts.at(i).at(2),
648  m_counts.at(i).at(m_networks_size),
649  m_counts.at(i).at(m_networks_size + 1));
650  }
651 
652  // Report local addresses, ports, and scores.
653  result += "\nLocal addresses";
654  const std::vector<UniValue> &local_addrs{
655  networkinfo["localaddresses"].getValues()};
656  if (local_addrs.empty()) {
657  result += ": n/a\n";
658  } else {
659  size_t max_addr_size{0};
660  for (const UniValue &addr : local_addrs) {
661  max_addr_size = std::max(addr["address"].get_str().length() + 1,
662  max_addr_size);
663  }
664  for (const UniValue &addr : local_addrs) {
665  result += strprintf("\n%-*s port %6i score %6i",
666  max_addr_size, addr["address"].get_str(),
667  addr["port"].getInt<int>(),
668  addr["score"].getInt<int>());
669  }
670  }
671 
672  return JSONRPCReplyObj(UniValue{result}, NullUniValue, 1);
673  }
674 };
675 
678 public:
679  UniValue PrepareRequest(const std::string &method,
680  const std::vector<std::string> &args) override {
681  address_str = args.at(1);
682  UniValue params{RPCConvertValues("generatetoaddress", args)};
683  return JSONRPCRequestObj("generatetoaddress", params, 1);
684  }
685 
686  UniValue ProcessReply(const UniValue &reply) override {
687  UniValue result(UniValue::VOBJ);
688  result.pushKV("address", address_str);
689  result.pushKV("blocks", reply.get_obj()["result"]);
690  return JSONRPCReplyObj(result, NullUniValue, 1);
691  }
692 
693 protected:
694  std::string address_str;
695 };
696 
699 public:
700  UniValue PrepareRequest(const std::string &method,
701  const std::vector<std::string> &args) override {
702  UniValue params;
703  if (gArgs.GetBoolArg("-named", DEFAULT_NAMED)) {
704  params = RPCConvertNamedValues(method, args);
705  } else {
706  params = RPCConvertValues(method, args);
707  }
708  return JSONRPCRequestObj(method, params, 1);
709  }
710 
711  UniValue ProcessReply(const UniValue &reply) override {
712  return reply.get_obj();
713  }
714 };
715 
716 static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod,
717  const std::vector<std::string> &args,
718  const std::optional<std::string> &rpcwallet = {}) {
719  std::string host;
720  // In preference order, we choose the following for the port:
721  // 1. -rpcport
722  // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
723  // 3. default port for chain
724  uint16_t port{BaseParams().RPCPort()};
725  SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
726  port = static_cast<uint16_t>(gArgs.GetIntArg("-rpcport", port));
727 
728  // Obtain event base
729  raii_event_base base = obtain_event_base();
730 
731  // Synchronously look up hostname
732  raii_evhttp_connection evcon =
733  obtain_evhttp_connection_base(base.get(), host, port);
734 
735  // Set connection timeout
736  {
737  const int timeout =
738  gArgs.GetIntArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT);
739  if (timeout > 0) {
740  evhttp_connection_set_timeout(evcon.get(), timeout);
741  } else {
742  // Indefinite request timeouts are not possible in libevent-http,
743  // so we set the timeout to a very long time period instead.
744 
745  // Average length of year in Gregorian calendar
746  constexpr int YEAR_IN_SECONDS = 31556952;
747  evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
748  }
749  }
750 
752  raii_evhttp_request req =
754  if (req == nullptr) {
755  throw std::runtime_error("create http request failed");
756  }
757 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
758  evhttp_request_set_error_cb(req.get(), http_error_cb);
759 #endif
760 
761  // Get credentials
762  std::string strRPCUserColonPass;
763  bool failedToGetAuthCookie = false;
764  if (gArgs.GetArg("-rpcpassword", "") == "") {
765  // Try fall back to cookie-based authentication if no password is
766  // provided
768  failedToGetAuthCookie = true;
769  }
770  } else {
771  strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" +
772  gArgs.GetArg("-rpcpassword", "");
773  }
774 
775  struct evkeyvalq *output_headers =
776  evhttp_request_get_output_headers(req.get());
777  assert(output_headers);
778  evhttp_add_header(output_headers, "Host", host.c_str());
779  evhttp_add_header(output_headers, "Connection", "close");
780  evhttp_add_header(output_headers, "Content-Type", "application/json");
781  evhttp_add_header(
782  output_headers, "Authorization",
783  (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());
784 
785  // Attach request data
786  std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n";
787  struct evbuffer *output_buffer =
788  evhttp_request_get_output_buffer(req.get());
789  assert(output_buffer);
790  evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
791 
792  // check if we should use a special wallet endpoint
793  std::string endpoint = "/";
794  if (rpcwallet) {
795  char *encodedURI =
796  evhttp_uriencode(rpcwallet->data(), rpcwallet->size(), false);
797  if (encodedURI) {
798  endpoint = "/wallet/" + std::string(encodedURI);
799  free(encodedURI);
800  } else {
801  throw CConnectionFailed("uri-encode failed");
802  }
803  }
804  int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST,
805  endpoint.c_str());
806  // ownership moved to evcon in above call
807  req.release();
808  if (r != 0) {
809  throw CConnectionFailed("send http request failed");
810  }
811 
812  event_base_dispatch(base.get());
813 
814  if (response.status == 0) {
815  std::string responseErrorMessage;
816  if (response.error != -1) {
817  responseErrorMessage =
818  strprintf(" (error code %d - \"%s\")", response.error,
819  http_errorstring(response.error));
820  }
821  throw CConnectionFailed(
822  strprintf("Could not connect to the server %s:%d%s\n\nMake sure "
823  "the bitcoind server is running and that you are "
824  "connecting to the correct RPC port.",
825  host, port, responseErrorMessage));
826  } else if (response.status == HTTP_UNAUTHORIZED) {
827  if (failedToGetAuthCookie) {
828  throw std::runtime_error(strprintf(
829  "Could not locate RPC credentials. No authentication cookie "
830  "could be found, and RPC password is not set. See "
831  "-rpcpassword and -stdinrpcpass. Configuration file: (%s)",
833  } else {
834  throw std::runtime_error(
835  "Authorization failed: Incorrect rpcuser or rpcpassword");
836  }
837  } else if (response.status == HTTP_SERVICE_UNAVAILABLE) {
838  throw std::runtime_error(
839  strprintf("Server response: %s", response.body));
840  } else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST &&
841  response.status != HTTP_NOT_FOUND &&
843  throw std::runtime_error(
844  strprintf("server returned HTTP error %d", response.status));
845  } else if (response.body.empty()) {
846  throw std::runtime_error("no response from server");
847  }
848 
849  // Parse reply
850  UniValue valReply(UniValue::VSTR);
851  if (!valReply.read(response.body)) {
852  throw std::runtime_error("couldn't parse reply from server");
853  }
854  const UniValue reply = rh->ProcessReply(valReply);
855  if (reply.empty()) {
856  throw std::runtime_error(
857  "expected reply to have result, error and id properties");
858  }
859 
860  return reply;
861 }
862 
874 static UniValue
875 ConnectAndCallRPC(BaseRequestHandler *rh, const std::string &strMethod,
876  const std::vector<std::string> &args,
877  const std::optional<std::string> &rpcwallet = {}) {
879  // Execute and handle connection failures with -rpcwait.
880  const bool fWait = gArgs.GetBoolArg("-rpcwait", false);
881  do {
882  try {
883  response = CallRPC(rh, strMethod, args, rpcwallet);
884  if (fWait) {
885  const UniValue &error = response.find_value("error");
886  if (!error.isNull() &&
887  error["code"].getInt<int>() == RPC_IN_WARMUP) {
888  throw CConnectionFailed("server in warmup");
889  }
890  }
891  break; // Connection succeeded, no need to retry.
892  } catch (const CConnectionFailed &) {
893  if (fWait) {
894  UninterruptibleSleep(std::chrono::milliseconds{1000});
895  } else {
896  throw;
897  }
898  }
899  } while (fWait);
900  return response;
901 }
902 
904 static void ParseResult(const UniValue &result, std::string &strPrint) {
905  if (result.isNull()) {
906  return;
907  }
908  strPrint = result.isStr() ? result.get_str() : result.write(2);
909 }
910 
915 static void ParseError(const UniValue &error, std::string &strPrint,
916  int &nRet) {
917  if (error.isObject()) {
918  const UniValue &err_code = error.find_value("code");
919  const UniValue &err_msg = error.find_value("message");
920  if (!err_code.isNull()) {
921  strPrint = "error code: " + err_code.getValStr() + "\n";
922  }
923  if (err_msg.isStr()) {
924  strPrint += ("error message:\n" + err_msg.get_str());
925  }
926  if (err_code.isNum() &&
927  err_code.getInt<int>() == RPC_WALLET_NOT_SPECIFIED) {
928  strPrint += "\nTry adding \"-rpcwallet=<filename>\" option to "
929  "bitcoin-cli command line.";
930  }
931  } else {
932  strPrint = "error: " + error.write();
933  }
934  nRet = abs(error["code"].getInt<int>());
935 }
936 
945 static void GetWalletBalances(UniValue &result) {
947  const UniValue listwallets =
948  ConnectAndCallRPC(&rh, "listwallets", /* args=*/{});
949  if (!listwallets.find_value("error").isNull()) {
950  return;
951  }
952  const UniValue &wallets = listwallets.find_value("result");
953  if (wallets.size() <= 1) {
954  return;
955  }
956 
957  UniValue balances(UniValue::VOBJ);
958  for (const UniValue &wallet : wallets.getValues()) {
959  const std::string wallet_name = wallet.get_str();
960  const UniValue getbalances =
961  ConnectAndCallRPC(&rh, "getbalances", /* args=*/{}, wallet_name);
962  const UniValue &balance =
963  getbalances.find_value("result")["mine"]["trusted"];
964  balances.pushKV(wallet_name, balance);
965  }
966  result.pushKV("balances", balances);
967 }
968 
974  std::optional<std::string> wallet_name{};
975  if (gArgs.IsArgSet("-rpcwallet")) {
976  wallet_name = gArgs.GetArg("-rpcwallet", "");
977  }
979  return ConnectAndCallRPC(&rh, "getnewaddress", /* args=*/{}, wallet_name);
980 }
981 
989 static void SetGenerateToAddressArgs(const std::string &address,
990  std::vector<std::string> &args) {
991  if (args.size() > 2) {
992  throw std::runtime_error(
993  "too many arguments (maximum 2 for nblocks and maxtries)");
994  }
995  if (args.size() == 0) {
996  args.emplace_back(DEFAULT_NBLOCKS);
997  } else if (args.at(0) == "0") {
998  throw std::runtime_error(
999  "the first argument (number of blocks to generate, default: " +
1000  DEFAULT_NBLOCKS + ") must be an integer value greater than zero");
1001  }
1002  args.emplace(args.begin() + 1, address);
1003 }
1004 
1005 static int CommandLineRPC(int argc, char *argv[]) {
1006  std::string strPrint;
1007  int nRet = 0;
1008  try {
1009  // Skip switches
1010  while (argc > 1 && IsSwitchChar(argv[1][0])) {
1011  argc--;
1012  argv++;
1013  }
1014  std::string rpcPass;
1015  if (gArgs.GetBoolArg("-stdinrpcpass", false)) {
1016  NO_STDIN_ECHO();
1017  if (!StdinReady()) {
1018  fputs("RPC password> ", stderr);
1019  fflush(stderr);
1020  }
1021  if (!std::getline(std::cin, rpcPass)) {
1022  throw std::runtime_error("-stdinrpcpass specified but failed "
1023  "to read from standard input");
1024  }
1025  if (StdinTerminal()) {
1026  fputc('\n', stdout);
1027  }
1028  gArgs.ForceSetArg("-rpcpassword", rpcPass);
1029  }
1030  std::vector<std::string> args =
1031  std::vector<std::string>(&argv[1], &argv[argc]);
1032  if (gArgs.GetBoolArg("-stdinwalletpassphrase", false)) {
1033  NO_STDIN_ECHO();
1034  std::string walletPass;
1035  if (args.size() < 1 ||
1036  args[0].substr(0, 16) != "walletpassphrase") {
1037  throw std::runtime_error(
1038  "-stdinwalletpassphrase is only applicable for "
1039  "walletpassphrase(change)");
1040  }
1041  if (!StdinReady()) {
1042  fputs("Wallet passphrase> ", stderr);
1043  fflush(stderr);
1044  }
1045  if (!std::getline(std::cin, walletPass)) {
1046  throw std::runtime_error("-stdinwalletpassphrase specified but "
1047  "failed to read from standard input");
1048  }
1049  if (StdinTerminal()) {
1050  fputc('\n', stdout);
1051  }
1052  args.insert(args.begin() + 1, walletPass);
1053  }
1054  if (gArgs.GetBoolArg("-stdin", false)) {
1055  // Read one arg per line from stdin and append
1056  std::string line;
1057  while (std::getline(std::cin, line)) {
1058  args.push_back(line);
1059  }
1060  if (StdinTerminal()) {
1061  fputc('\n', stdout);
1062  }
1063  }
1064  std::unique_ptr<BaseRequestHandler> rh;
1065  std::string method;
1066  if (gArgs.IsArgSet("-getinfo")) {
1067  rh.reset(new GetinfoRequestHandler());
1068  } else if (gArgs.GetBoolArg("-generate", false)) {
1070  const UniValue &error{getnewaddress.find_value("error")};
1071  if (error.isNull()) {
1073  getnewaddress.find_value("result").get_str(), args);
1074  rh.reset(new GenerateToAddressRequestHandler());
1075  } else {
1076  ParseError(error, strPrint, nRet);
1077  }
1078  } else if (gArgs.GetBoolArg("-netinfo", false)) {
1079  rh.reset(new NetinfoRequestHandler());
1080  } else {
1081  rh.reset(new DefaultRequestHandler());
1082  if (args.size() < 1) {
1083  throw std::runtime_error(
1084  "too few parameters (need at least command)");
1085  }
1086  method = args[0];
1087  // Remove trailing method name from arguments vector
1088  args.erase(args.begin());
1089  }
1090 
1091  if (nRet == 0) {
1092  // Perform RPC call
1093  std::optional<std::string> wallet_name{};
1094  if (gArgs.IsArgSet("-rpcwallet")) {
1095  wallet_name = gArgs.GetArg("-rpcwallet", "");
1096  }
1097  const UniValue reply =
1098  ConnectAndCallRPC(rh.get(), method, args, wallet_name);
1099 
1100  // Parse reply
1101  UniValue result = reply.find_value("result");
1102  const UniValue &error = reply.find_value("error");
1103  if (error.isNull()) {
1104  if (gArgs.IsArgSet("-getinfo") &&
1105  !gArgs.IsArgSet("-rpcwallet")) {
1106  // fetch multiwallet balances and append to result
1107  GetWalletBalances(result);
1108  }
1109  ParseResult(result, strPrint);
1110  } else {
1111  ParseError(error, strPrint, nRet);
1112  }
1113  }
1114  } catch (const std::exception &e) {
1115  strPrint = std::string("error: ") + e.what();
1116  nRet = EXIT_FAILURE;
1117  } catch (...) {
1118  PrintExceptionContinue(nullptr, "CommandLineRPC()");
1119  throw;
1120  }
1121 
1122  if (strPrint != "") {
1123  tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
1124  }
1125  return nRet;
1126 }
1127 
1128 #ifdef WIN32
1129 // Export main() and ensure working ASLR on Windows.
1130 // Exporting a symbol will prevent the linker from stripping
1131 // the .reloc section from the binary, which is a requirement
1132 // for ASLR. This is a temporary workaround until a fixed
1133 // version of binutils is used for releases.
1134 __declspec(dllexport) int main(int argc, char *argv[]) {
1135  common::WinCmdLineArgs winArgs;
1136  std::tie(argc, argv) = winArgs.get();
1137 #else
1138 int main(int argc, char *argv[]) {
1139 #endif
1140  SetupEnvironment();
1141  if (!SetupNetworking()) {
1142  tfm::format(std::cerr, "Error: Initializing networking failed\n");
1143  return EXIT_FAILURE;
1144  }
1145  event_set_log_callback(&libevent_log_cb);
1146 
1147  try {
1148  int ret = AppInitRPC(argc, argv);
1149  if (ret != CONTINUE_EXECUTION) {
1150  return ret;
1151  }
1152  } catch (const std::exception &e) {
1153  PrintExceptionContinue(&e, "AppInitRPC()");
1154  return EXIT_FAILURE;
1155  } catch (...) {
1156  PrintExceptionContinue(nullptr, "AppInitRPC()");
1157  return EXIT_FAILURE;
1158  }
1159 
1160  int ret = EXIT_FAILURE;
1161  try {
1162  ret = CommandLineRPC(argc, argv);
1163  } catch (const std::exception &e) {
1164  PrintExceptionContinue(&e, "CommandLineRPC()");
1165  } catch (...) {
1166  PrintExceptionContinue(nullptr, "CommandLineRPC()");
1167  }
1168  return ret;
1169 }
bool HelpRequested(const ArgsManager &args)
Definition: args.cpp:732
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
Definition: args.cpp:737
bool CheckDataDirOption(const ArgsManager &args)
Definition: args.cpp:784
ArgsManager gArgs
Definition: args.cpp:38
const char *const BITCOIN_CONF_FILENAME
Definition: args.cpp:35
bool IsSwitchChar(char c)
Definition: args.h:47
secp256k1_context * ctx
static const char DEFAULT_RPCCONNECT[]
Definition: bitcoin-cli.cpp:49
int main(int argc, char *argv[])
static const int CONTINUE_EXECUTION
Definition: bitcoin-cli.cpp:52
static int AppInitRPC(int argc, char *argv[])
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.
static int CommandLineRPC(int argc, char *argv[])
static const int DEFAULT_HTTP_CLIENT_TIMEOUT
Definition: bitcoin-cli.cpp:50
static void http_request_done(struct evhttp_request *req, void *ctx)
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
Definition: bitcoin-cli.cpp:47
static void ParseResult(const UniValue &result, std::string &strPrint)
Parse UniValue result to update the message to print to std::cout.
static const std::string DEFAULT_NBLOCKS
Default number of blocks to generate for RPC generatetoaddress.
Definition: bitcoin-cli.cpp:54
static UniValue ConnectAndCallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args, const std::optional< std::string > &rpcwallet={})
ConnectAndCallRPC wraps CallRPC with -rpcwait and an exception handler.
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.
static void GetWalletBalances(UniValue &result)
GetWalletBalances calls listwallets; if more than one wallet is loaded, it then fetches mine....
static void SetupCliArgs(ArgsManager &argsman)
Definition: bitcoin-cli.cpp:56
std::chrono::system_clock CliClock
Definition: bitcoin-cli.cpp:45
#define EVENT_LOG_ERR
static std::string http_errorstring(int code)
static void libevent_log_cb(int severity, const char *msg)
libevent event log callback
static const bool DEFAULT_NAMED
Definition: bitcoin-cli.cpp:51
static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args, const std::optional< std::string > &rpcwallet={})
static UniValue GetNewAddress()
Call RPC getnewaddress.
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
void SelectBaseParams(const std::string &chain)
Sets the params returned by Params() to those for the given network.
std::unique_ptr< CBaseChainParams > CreateBaseChainParams(const std::string &chain)
Port numbers for incoming Tor connections (8334, 18334, 38334, 18445) have been chosen arbitrarily to...
@ NETWORK_ONLY
Definition: args.h:110
@ ALLOW_ANY
Definition: args.h:103
@ ALLOW_INT
Definition: args.h:101
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: args.cpp:597
bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: args.cpp:201
std::string GetHelpMessage() const
Get the help string.
Definition: args.cpp:653
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:381
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: args.cpp:526
fs::path GetConfigFilePath() const
Return config file path (read-only)
Definition: args.cpp:789
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:494
bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: configfile.cpp:130
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:556
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: args.cpp:620
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: args.cpp:793
Class that handles the conversion from a command-line to a JSON-RPC request, as well as converting ba...
virtual ~BaseRequestHandler()
virtual UniValue ProcessReply(const UniValue &batch_in)=0
virtual UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args)=0
uint16_t RPCPort() const
static const std::string REGTEST
static const std::string TESTNET
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
CConnectionFailed(const std::string &msg)
Process default single requests.
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
UniValue ProcessReply(const UniValue &reply) override
Process RPC generatetoaddress request.
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
UniValue ProcessReply(const UniValue &reply) override
Process getinfo requests.
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
Create a simulated getinfo request.
UniValue ProcessReply(const UniValue &batch_in) override
Collect values from the batch and form a simulated getinfo reply.
Process netinfo requests.
bool DetailsRequested() const
std::vector< Peer > m_peers
UniValue ProcessReply(const UniValue &batch_in) override
uint8_t m_details_level
Optional user-supplied arg to set dashboard details level.
std::array< std::array< uint16_t, m_networks_size+2 >, 3 > m_counts
Peer counts by (in/out/total, networks/total/block-relay)
bool IsAddressSelected() const
static constexpr int8_t UNKNOWN_NETWORK
bool IsVersionSelected() const
int8_t NetworkStringToId(const std::string &str) const
static constexpr int ID_PEERINFO
std::string ChainToString() const
const int64_t m_time_now
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
static constexpr int ID_NETWORKINFO
const std::array< std::string, m_networks_size > m_networks
std::string PingTimeToString(double seconds) const
static constexpr uint8_t m_networks_size
void push_back(UniValue val)
Definition: univalue.cpp:96
const std::string & get_str() const
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:229
@ VOBJ
Definition: univalue.h:31
@ VSTR
Definition: univalue.h:33
@ VARR
Definition: univalue.h:32
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool isNull() const
Definition: univalue.h:104
const UniValue & get_obj() const
const std::string & getValStr() const
Definition: univalue.h:89
size_t size() const
Definition: univalue.h:92
const std::vector< UniValue > & getValues() const
bool empty() const
Definition: univalue.h:90
bool isStr() const
Definition: univalue.h:108
Int getInt() const
Definition: univalue.h:157
bool isNum() const
Definition: univalue.h:109
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:115
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:272
UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert named arguments to command-specific RPC representation.
Definition: client.cpp:284
std::string FormatFullVersion()
std::string LicenseInfo()
Returns licensing information (for -version)
static Amount balance
void SetupCurrencyUnitOptions(ArgsManager &argsman)
Definition: currencyunit.cpp:9
raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg)
Definition: events.h:46
raii_evhttp_connection obtain_evhttp_connection_base(struct event_base *base, std::string host, uint16_t port)
Definition: events.h:51
raii_event_base obtain_event_base()
Definition: events.h:28
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: exception.cpp:38
static std::string strRPCUserColonPass
Definition: httprpc.cpp:69
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
static const uint64_t DEFAULT_MAX_TRIES
Default max iterations to try in RPC generatetodescriptor, generatetoaddress, and generateblock.
Definition: mining.h:12
static bool isNull(const AnyVoteItem &item)
Definition: processor.cpp:402
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:142
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:257
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:1112
Response response
Definition: processor.cpp:487
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in)
Parse JSON-RPC batch reply into a vector.
Definition: request.cpp:144
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
Definition: request.cpp:118
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params, const UniValue &id)
JSON-RPC protocol.
Definition: request.cpp:30
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:39
static RPCHelpMan ping()
Definition: net.cpp:56
@ HTTP_BAD_REQUEST
Definition: protocol.h:12
@ HTTP_SERVICE_UNAVAILABLE
Definition: protocol.h:18
@ HTTP_UNAUTHORIZED
Definition: protocol.h:13
@ HTTP_NOT_FOUND
Definition: protocol.h:15
@ HTTP_INTERNAL_SERVER_ERROR
Definition: protocol.h:17
@ RPC_WALLET_NOT_SPECIFIED
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:111
@ RPC_IN_WARMUP
Client still warming up.
Definition: protocol.h:58
static RPCHelpMan getnewaddress()
Definition: rpcwallet.cpp:95
static RPCHelpMan listwallets()
Definition: rpcwallet.cpp:2645
static RPCHelpMan getbalances()
Definition: rpcwallet.cpp:2373
bool StdinReady()
Definition: stdin.cpp:54
bool StdinTerminal()
Definition: stdin.cpp:46
#define NO_STDIN_ECHO()
Definition: stdin.h:13
std::string EncodeBase64(Span< const uint8_t > input)
std::string FormatParagraph(const std::string &in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line.
void SplitHostPort(std::string in, uint16_t &portOut, std::string &hostOut)
bool ParseUInt8(const std::string &str, uint8_t *out)
Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:86
Reply structure for request_done to fill in.
std::string body
bool operator<(const Peer &rhs) const
bool SetupNetworking()
Definition: system.cpp:98
void SetupEnvironment()
Definition: system.cpp:70
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:23
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
const UniValue NullUniValue
Definition: univalue.cpp:16
assert(!tx.IsCoinBase())