Bitcoin ABC  0.22.13
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 <rpc/client.h>
13 #include <rpc/protocol.h>
14 #include <rpc/request.h>
15 #include <support/events.h>
16 #include <util/strencodings.h>
17 #include <util/system.h>
18 #include <util/translation.h>
19 
20 #include <event2/buffer.h>
21 #include <event2/keyvalq_struct.h>
22 
23 #include <compat/stdin.h>
24 #include <univalue.h>
25 
26 #include <cstdio>
27 #include <functional>
28 #include <memory>
29 #include <tuple>
30 
31 const std::function<std::string(const char *)> G_TRANSLATION_FUN = nullptr;
32 
33 static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
34 static const int DEFAULT_HTTP_CLIENT_TIMEOUT = 900;
35 static const bool DEFAULT_NAMED = false;
36 static const int CONTINUE_EXECUTION = -1;
37 
38 static void SetupCliArgs(ArgsManager &argsman) {
39  SetupHelpOptions(argsman);
40 
41  const auto defaultBaseParams =
43  const auto testnetBaseParams =
45  const auto regtestBaseParams =
47 
48  argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY,
50  argsman.AddArg(
51  "-conf=<file>",
52  strprintf("Specify configuration file. Relative paths will be "
53  "prefixed by datadir location. (default: %s)",
56  argsman.AddArg("-datadir=<dir>", "Specify data directory",
58  argsman.AddArg(
59  "-getinfo",
60  "Get general information from the remote server. Note that unlike "
61  "server-side RPC calls, the results of -getinfo is the result of "
62  "multiple non-atomic requests. Some entries in the result may "
63  "represent results from different states (e.g. wallet balance may be "
64  "as of a different block from the chain state reported)",
67  argsman.AddArg(
68  "-named",
69  strprintf("Pass named instead of positional arguments (default: %s)",
72  argsman.AddArg(
73  "-rpcconnect=<ip>",
74  strprintf("Send commands to node running on <ip> (default: %s)",
77  argsman.AddArg(
78  "-rpccookiefile=<loc>",
79  "Location of the auth cookie. Relative paths will be prefixed "
80  "by a net-specific datadir location. (default: data dir)",
82  argsman.AddArg("-rpcport=<port>",
83  strprintf("Connect to JSON-RPC on <port> (default: %u, "
84  "testnet: %u, regtest: %u)",
85  defaultBaseParams->RPCPort(),
86  testnetBaseParams->RPCPort(),
87  regtestBaseParams->RPCPort()),
90  argsman.AddArg("-rpcwait", "Wait for RPC server to start",
92  argsman.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections",
94  argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections",
96  argsman.AddArg(
97  "-rpcclienttimeout=<n>",
98  strprintf("Timeout in seconds during HTTP requests, or 0 for "
99  "no timeout. (default: %d)",
102 
103  argsman.AddArg("-stdinrpcpass",
104  "Read RPC password from standard input as a single "
105  "line. When combined with -stdin, the first line "
106  "from standard input is used for the RPC password. When "
107  "combined with -stdinwalletpassphrase, -stdinrpcpass "
108  "consumes the first line, and -stdinwalletpassphrase "
109  "consumes the second.",
111  argsman.AddArg("-stdinwalletpassphrase",
112  "Read wallet passphrase from standard input as a single "
113  "line. When combined with -stdin, the first line "
114  "from standard input is used for the wallet passphrase.",
116  argsman.AddArg(
117  "-stdin",
118  "Read extra arguments from standard input, one per line until "
119  "EOF/Ctrl-D (recommended for sensitive information such as "
120  "passphrases). When combined with -stdinrpcpass, the first "
121  "line from standard input is used for the RPC password.",
123  argsman.AddArg(
124  "-rpcwallet=<walletname>",
125  "Send RPC for non-default wallet on RPC server (needs to exactly match "
126  "corresponding -wallet option passed to bitcoind). This changes the "
127  "RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname>",
129 }
130 
132 static void libevent_log_cb(int severity, const char *msg) {
133 #ifndef EVENT_LOG_ERR
134 // EVENT_LOG_ERR was added in 2.0.19; but before then _EVENT_LOG_ERR existed.
135 #define EVENT_LOG_ERR _EVENT_LOG_ERR
136 #endif
137  // Ignore everything other than errors
138  if (severity >= EVENT_LOG_ERR) {
139  throw std::runtime_error(strprintf("libevent error: %s", msg));
140  }
141 }
142 
144 //
145 // Start
146 //
147 
148 //
149 // Exception thrown on connection error. This error is used to determine when
150 // to wait if -rpcwait is given.
151 //
152 class CConnectionFailed : public std::runtime_error {
153 public:
154  explicit inline CConnectionFailed(const std::string &msg)
155  : std::runtime_error(msg) {}
156 };
157 
158 //
159 // This function returns either one of EXIT_ codes when it's expected to stop
160 // the process or CONTINUE_EXECUTION when it's expected to continue further.
161 //
162 static int AppInitRPC(int argc, char *argv[]) {
163  //
164  // Parameters
165  //
167  std::string error;
168  if (!gArgs.ParseParameters(argc, argv, error)) {
169  tfm::format(std::cerr, "Error parsing command line arguments: %s\n",
170  error);
171  return EXIT_FAILURE;
172  }
173  if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
174  std::string strUsage =
175  PACKAGE_NAME " RPC client version " + FormatFullVersion() + "\n";
176  if (!gArgs.IsArgSet("-version")) {
177  strUsage += "\n"
178  "Usage: bitcoin-cli [options] <command> [params] "
179  "Send command to " PACKAGE_NAME "\n"
180  "or: bitcoin-cli [options] -named <command> "
181  "[name=value]... Send command to " PACKAGE_NAME
182  " (with named arguments)\n"
183  "or: bitcoin-cli [options] help "
184  "List commands\n"
185  "or: bitcoin-cli [options] help <command> Get "
186  "help for a command\n";
187 
188  strUsage += "\n" + gArgs.GetHelpMessage();
189  }
190 
191  tfm::format(std::cout, "%s", strUsage);
192  if (argc < 2) {
193  tfm::format(std::cerr, "Error: too few parameters\n");
194  return EXIT_FAILURE;
195  }
196  return EXIT_SUCCESS;
197  }
198  if (!CheckDataDirOption()) {
199  tfm::format(std::cerr,
200  "Error: Specified data directory \"%s\" does not exist.\n",
201  gArgs.GetArg("-datadir", ""));
202  return EXIT_FAILURE;
203  }
204  if (!gArgs.ReadConfigFiles(error, true)) {
205  tfm::format(std::cerr, "Error reading configuration file: %s\n", error);
206  return EXIT_FAILURE;
207  }
208  // Check for -chain, -testnet or -regtest parameter (BaseParams() calls are
209  // only valid after this clause)
210  try {
212  } catch (const std::exception &e) {
213  tfm::format(std::cerr, "Error: %s\n", e.what());
214  return EXIT_FAILURE;
215  }
216  return CONTINUE_EXECUTION;
217 }
218 
220 struct HTTPReply {
221  HTTPReply() : status(0), error(-1) {}
222 
223  int status;
224  int error;
225  std::string body;
226 };
227 
228 static const char *http_errorstring(int code) {
229  switch (code) {
230 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
231  case EVREQ_HTTP_TIMEOUT:
232  return "timeout reached";
233  case EVREQ_HTTP_EOF:
234  return "EOF reached";
235  case EVREQ_HTTP_INVALID_HEADER:
236  return "error while reading header, or invalid header";
237  case EVREQ_HTTP_BUFFER_ERROR:
238  return "error encountered while reading or writing";
239  case EVREQ_HTTP_REQUEST_CANCEL:
240  return "request was canceled";
241  case EVREQ_HTTP_DATA_TOO_LONG:
242  return "response body is larger than allowed";
243 #endif
244  default:
245  return "unknown";
246  }
247 }
248 
249 static void http_request_done(struct evhttp_request *req, void *ctx) {
250  HTTPReply *reply = static_cast<HTTPReply *>(ctx);
251 
252  if (req == nullptr) {
257  reply->status = 0;
258  return;
259  }
260 
261  reply->status = evhttp_request_get_response_code(req);
262 
263  struct evbuffer *buf = evhttp_request_get_input_buffer(req);
264  if (buf) {
265  size_t size = evbuffer_get_length(buf);
266  const char *data = (const char *)evbuffer_pullup(buf, size);
267  if (data) {
268  reply->body = std::string(data, size);
269  }
270  evbuffer_drain(buf, size);
271  }
272 }
273 
274 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
275 static void http_error_cb(enum evhttp_request_error err, void *ctx) {
276  HTTPReply *reply = static_cast<HTTPReply *>(ctx);
277  reply->error = err;
278 }
279 #endif
280 
286 public:
287  virtual ~BaseRequestHandler() {}
288  virtual UniValue PrepareRequest(const std::string &method,
289  const std::vector<std::string> &args) = 0;
290  virtual UniValue ProcessReply(const UniValue &batch_in) = 0;
291 };
292 
295 public:
296  const int ID_NETWORKINFO = 0;
297  const int ID_BLOCKCHAININFO = 1;
298  const int ID_WALLETINFO = 2;
299  const int ID_BALANCES = 3;
300 
302  UniValue PrepareRequest(const std::string &method,
303  const std::vector<std::string> &args) override {
304  if (!args.empty()) {
305  throw std::runtime_error("-getinfo takes no arguments");
306  }
307  UniValue result(UniValue::VARR);
308  result.push_back(
309  JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
310  result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue,
311  ID_BLOCKCHAININFO));
312  result.push_back(
313  JSONRPCRequestObj("getwalletinfo", NullUniValue, ID_WALLETINFO));
314  result.push_back(
315  JSONRPCRequestObj("getbalances", NullUniValue, ID_BALANCES));
316  return result;
317  }
318 
320  UniValue ProcessReply(const UniValue &batch_in) override {
321  UniValue result(UniValue::VOBJ);
322  std::vector<UniValue> batch =
323  JSONRPCProcessBatchReply(batch_in, batch_in.size());
324  // Errors in getnetworkinfo() and getblockchaininfo() are fatal, pass
325  // them on; getwalletinfo() and getbalances are allowed to fail if there
326  // is no wallet.
327  if (!batch[ID_NETWORKINFO]["error"].isNull()) {
328  return batch[ID_NETWORKINFO];
329  }
330  if (!batch[ID_BLOCKCHAININFO]["error"].isNull()) {
331  return batch[ID_BLOCKCHAININFO];
332  }
333  result.pushKV("version", batch[ID_NETWORKINFO]["result"]["version"]);
334  result.pushKV("blocks", batch[ID_BLOCKCHAININFO]["result"]["blocks"]);
335  result.pushKV("headers", batch[ID_BLOCKCHAININFO]["result"]["headers"]);
336  result.pushKV(
337  "verificationprogress",
338  batch[ID_BLOCKCHAININFO]["result"]["verificationprogress"]);
339  result.pushKV("timeoffset",
340  batch[ID_NETWORKINFO]["result"]["timeoffset"]);
341  result.pushKV("connections",
342  batch[ID_NETWORKINFO]["result"]["connections"]);
343  result.pushKV("proxy",
344  batch[ID_NETWORKINFO]["result"]["networks"][0]["proxy"]);
345  result.pushKV("difficulty",
346  batch[ID_BLOCKCHAININFO]["result"]["difficulty"]);
347  result.pushKV("chain",
348  UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"]));
349  if (!batch[ID_WALLETINFO]["result"].isNull()) {
350  result.pushKV("keypoolsize",
351  batch[ID_WALLETINFO]["result"]["keypoolsize"]);
352  if (!batch[ID_WALLETINFO]["result"]["unlocked_until"].isNull()) {
353  result.pushKV("unlocked_until",
354  batch[ID_WALLETINFO]["result"]["unlocked_until"]);
355  }
356  result.pushKV("paytxfee",
357  batch[ID_WALLETINFO]["result"]["paytxfee"]);
358  }
359  if (!batch[ID_BALANCES]["result"].isNull()) {
360  result.pushKV("balance",
361  batch[ID_BALANCES]["result"]["mine"]["trusted"]);
362  }
363  result.pushKV("relayfee", batch[ID_NETWORKINFO]["result"]["relayfee"]);
364  result.pushKV("warnings", batch[ID_NETWORKINFO]["result"]["warnings"]);
365  return JSONRPCReplyObj(result, NullUniValue, 1);
366  }
367 };
368 
371 public:
372  UniValue PrepareRequest(const std::string &method,
373  const std::vector<std::string> &args) override {
374  UniValue params;
375  if (gArgs.GetBoolArg("-named", DEFAULT_NAMED)) {
376  params = RPCConvertNamedValues(method, args);
377  } else {
378  params = RPCConvertValues(method, args);
379  }
380  return JSONRPCRequestObj(method, params, 1);
381  }
382 
383  UniValue ProcessReply(const UniValue &reply) override {
384  return reply.get_obj();
385  }
386 };
387 
388 static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod,
389  const std::vector<std::string> &args) {
390  std::string host;
391  // In preference order, we choose the following for the port:
392  // 1. -rpcport
393  // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
394  // 3. default port for chain
395  int port = BaseParams().RPCPort();
396  SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
397  port = gArgs.GetArg("-rpcport", port);
398 
399  // Obtain event base
400  raii_event_base base = obtain_event_base();
401 
402  // Synchronously look up hostname
403  raii_evhttp_connection evcon =
404  obtain_evhttp_connection_base(base.get(), host, port);
405 
406  // Set connection timeout
407  {
408  const int timeout =
409  gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT);
410  if (timeout > 0) {
411  evhttp_connection_set_timeout(evcon.get(), timeout);
412  } else {
413  // Indefinite request timeouts are not possible in libevent-http,
414  // so we set the timeout to a very long time period instead.
415 
416  // Average length of year in Gregorian calendar
417  constexpr int YEAR_IN_SECONDS = 31556952;
418  evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
419  }
420  }
421 
423  raii_evhttp_request req =
424  obtain_evhttp_request(http_request_done, (void *)&response);
425  if (req == nullptr) {
426  throw std::runtime_error("create http request failed");
427  }
428 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
429  evhttp_request_set_error_cb(req.get(), http_error_cb);
430 #endif
431 
432  // Get credentials
433  std::string strRPCUserColonPass;
434  bool failedToGetAuthCookie = false;
435  if (gArgs.GetArg("-rpcpassword", "") == "") {
436  // Try fall back to cookie-based authentication if no password is
437  // provided
438  if (!GetAuthCookie(&strRPCUserColonPass)) {
439  failedToGetAuthCookie = true;
440  }
441  } else {
442  strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" +
443  gArgs.GetArg("-rpcpassword", "");
444  }
445 
446  struct evkeyvalq *output_headers =
447  evhttp_request_get_output_headers(req.get());
448  assert(output_headers);
449  evhttp_add_header(output_headers, "Host", host.c_str());
450  evhttp_add_header(output_headers, "Connection", "close");
451  evhttp_add_header(
452  output_headers, "Authorization",
453  (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());
454 
455  // Attach request data
456  std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n";
457  struct evbuffer *output_buffer =
458  evhttp_request_get_output_buffer(req.get());
459  assert(output_buffer);
460  evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
461 
462  // check if we should use a special wallet endpoint
463  std::string endpoint = "/";
464  if (!gArgs.GetArgs("-rpcwallet").empty()) {
465  std::string walletName = gArgs.GetArg("-rpcwallet", "");
466  char *encodedURI =
467  evhttp_uriencode(walletName.data(), walletName.size(), false);
468  if (encodedURI) {
469  endpoint = "/wallet/" + std::string(encodedURI);
470  free(encodedURI);
471  } else {
472  throw CConnectionFailed("uri-encode failed");
473  }
474  }
475  int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST,
476  endpoint.c_str());
477  // ownership moved to evcon in above call
478  req.release();
479  if (r != 0) {
480  throw CConnectionFailed("send http request failed");
481  }
482 
483  event_base_dispatch(base.get());
484 
485  if (response.status == 0) {
486  std::string responseErrorMessage;
487  if (response.error != -1) {
488  responseErrorMessage =
489  strprintf(" (error code %d - \"%s\")", response.error,
490  http_errorstring(response.error));
491  }
492  throw CConnectionFailed(
493  strprintf("Could not connect to the server %s:%d%s\n\nMake sure "
494  "the bitcoind server is running and that you are "
495  "connecting to the correct RPC port.",
496  host, port, responseErrorMessage));
497  } else if (response.status == HTTP_UNAUTHORIZED) {
498  if (failedToGetAuthCookie) {
499  throw std::runtime_error(strprintf(
500  "Could not locate RPC credentials. No authentication cookie "
501  "could be found, and RPC password is not set. See "
502  "-rpcpassword and -stdinrpcpass. Configuration file: (%s)",
504  .string()));
505  } else {
506  throw std::runtime_error(
507  "Authorization failed: Incorrect rpcuser or rpcpassword");
508  }
509  } else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST &&
510  response.status != HTTP_NOT_FOUND &&
511  response.status != HTTP_INTERNAL_SERVER_ERROR) {
512  throw std::runtime_error(
513  strprintf("server returned HTTP error %d", response.status));
514  } else if (response.body.empty()) {
515  throw std::runtime_error("no response from server");
516  }
517 
518  // Parse reply
519  UniValue valReply(UniValue::VSTR);
520  if (!valReply.read(response.body)) {
521  throw std::runtime_error("couldn't parse reply from server");
522  }
523  const UniValue reply = rh->ProcessReply(valReply);
524  if (reply.empty()) {
525  throw std::runtime_error(
526  "expected reply to have result, error and id properties");
527  }
528 
529  return reply;
530 }
531 
532 static int CommandLineRPC(int argc, char *argv[]) {
533  std::string strPrint;
534  int nRet = 0;
535  try {
536  // Skip switches
537  while (argc > 1 && IsSwitchChar(argv[1][0])) {
538  argc--;
539  argv++;
540  }
541  std::string rpcPass;
542  if (gArgs.GetBoolArg("-stdinrpcpass", false)) {
543  NO_STDIN_ECHO();
544  if (!StdinReady()) {
545  fputs("RPC password> ", stderr);
546  fflush(stderr);
547  }
548  if (!std::getline(std::cin, rpcPass)) {
549  throw std::runtime_error("-stdinrpcpass specified but failed "
550  "to read from standard input");
551  }
552  if (StdinTerminal()) {
553  fputc('\n', stdout);
554  }
555  gArgs.ForceSetArg("-rpcpassword", rpcPass);
556  }
557  std::vector<std::string> args =
558  std::vector<std::string>(&argv[1], &argv[argc]);
559  if (gArgs.GetBoolArg("-stdinwalletpassphrase", false)) {
560  NO_STDIN_ECHO();
561  std::string walletPass;
562  if (args.size() < 1 ||
563  args[0].substr(0, 16) != "walletpassphrase") {
564  throw std::runtime_error(
565  "-stdinwalletpassphrase is only applicable for "
566  "walletpassphrase(change)");
567  }
568  if (!StdinReady()) {
569  fputs("Wallet passphrase> ", stderr);
570  fflush(stderr);
571  }
572  if (!std::getline(std::cin, walletPass)) {
573  throw std::runtime_error("-stdinwalletpassphrase specified but "
574  "failed to read from standard input");
575  }
576  if (StdinTerminal()) {
577  fputc('\n', stdout);
578  }
579  args.insert(args.begin() + 1, walletPass);
580  }
581  if (gArgs.GetBoolArg("-stdin", false)) {
582  // Read one arg per line from stdin and append
583  std::string line;
584  while (std::getline(std::cin, line)) {
585  args.push_back(line);
586  }
587  if (StdinTerminal()) {
588  fputc('\n', stdout);
589  }
590  }
591  std::unique_ptr<BaseRequestHandler> rh;
592  std::string method;
593  if (gArgs.GetBoolArg("-getinfo", false)) {
594  rh.reset(new GetinfoRequestHandler());
595  method = "";
596  } else {
597  rh.reset(new DefaultRequestHandler());
598  if (args.size() < 1) {
599  throw std::runtime_error(
600  "too few parameters (need at least command)");
601  }
602  method = args[0];
603  // Remove trailing method name from arguments vector
604  args.erase(args.begin());
605  }
606 
607  // Execute and handle connection failures with -rpcwait
608  const bool fWait = gArgs.GetBoolArg("-rpcwait", false);
609  do {
610  try {
611  const UniValue reply = CallRPC(rh.get(), method, args);
612 
613  // Parse reply
614  const UniValue &result = find_value(reply, "result");
615  const UniValue &error = find_value(reply, "error");
616 
617  if (!error.isNull()) {
618  // Error
619  int code = error["code"].get_int();
620  if (fWait && code == RPC_IN_WARMUP) {
621  throw CConnectionFailed("server in warmup");
622  }
623  strPrint = "error: " + error.write();
624  nRet = abs(code);
625  if (error.isObject()) {
626  UniValue errCode = find_value(error, "code");
627  UniValue errMsg = find_value(error, "message");
628  strPrint =
629  errCode.isNull()
630  ? ""
631  : "error code: " + errCode.getValStr() + "\n";
632 
633  if (errMsg.isStr()) {
634  strPrint += "error message:\n" + errMsg.get_str();
635  }
636 
637  if (errCode.isNum() &&
638  errCode.get_int() == RPC_WALLET_NOT_SPECIFIED) {
639  strPrint += "\nTry adding "
640  "\"-rpcwallet=<filename>\" option to "
641  "bitcoin-cli command line.";
642  }
643  }
644  } else {
645  // Result
646  if (result.isNull()) {
647  strPrint = "";
648  } else if (result.isStr()) {
649  strPrint = result.get_str();
650  } else {
651  strPrint = result.write(2);
652  }
653  }
654  // Connection succeeded, no need to retry.
655  break;
656  } catch (const CConnectionFailed &) {
657  if (fWait) {
658  UninterruptibleSleep(std::chrono::milliseconds{1000});
659  } else {
660  throw;
661  }
662  }
663  } while (fWait);
664  } catch (const std::exception &e) {
665  strPrint = std::string("error: ") + e.what();
666  nRet = EXIT_FAILURE;
667  } catch (...) {
668  PrintExceptionContinue(nullptr, "CommandLineRPC()");
669  throw;
670  }
671 
672  if (strPrint != "") {
673  tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
674  }
675  return nRet;
676 }
677 
678 int main(int argc, char *argv[]) {
679 #ifdef WIN32
680  util::WinCmdLineArgs winArgs;
681  std::tie(argc, argv) = winArgs.get();
682 #endif
684  if (!SetupNetworking()) {
685  tfm::format(std::cerr, "Error: Initializing networking failed\n");
686  return EXIT_FAILURE;
687  }
688  event_set_log_callback(&libevent_log_cb);
689 
690  try {
691  int ret = AppInitRPC(argc, argv);
692  if (ret != CONTINUE_EXECUTION) {
693  return ret;
694  }
695  } catch (const std::exception &e) {
696  PrintExceptionContinue(&e, "AppInitRPC()");
697  return EXIT_FAILURE;
698  } catch (...) {
699  PrintExceptionContinue(nullptr, "AppInitRPC()");
700  return EXIT_FAILURE;
701  }
702 
703  int ret = EXIT_FAILURE;
704  try {
705  ret = CommandLineRPC(argc, argv);
706  } catch (const std::exception &e) {
707  PrintExceptionContinue(&e, "CommandLineRPC()");
708  } catch (...) {
709  PrintExceptionContinue(nullptr, "CommandLineRPC()");
710  }
711  return ret;
712 }
NODISCARD bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:911
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:109
bool isObject() const
Definition: univalue.h:96
bool StdinTerminal()
Definition: stdin.cpp:46
std::unique_ptr< CBaseChainParams > CreateBaseChainParams(const std::string &chain)
Creates and returns a std::unique_ptr<CBaseChainParams> of the chosen chain.
bool StdinReady()
Definition: stdin.cpp:54
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:390
static int CommandLineRPC(int argc, char *argv[])
raii_event_base obtain_event_base()
Definition: events.h:28
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in, size_t num)
Parse JSON-RPC batch reply into a vector.
Definition: request.cpp:138
static int AppInitRPC(int argc, char *argv[])
static void libevent_log_cb(int severity, const char *msg)
libevent event log callback
static const std::string REGTEST
bool read(const char *raw, size_t len)
static std::string strRPCUserColonPass
Definition: httprpc.cpp:69
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
secp256k1_context * ctx
UniValue ProcessReply(const UniValue &reply) override
virtual ~BaseRequestHandler()
static const int DEFAULT_HTTP_CLIENT_TIMEOUT
Definition: bitcoin-cli.cpp:34
void SetupEnvironment()
Definition: system.cpp:1287
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
std::string EncodeBase64(const uint8_t *pch, size_t len)
const std::string & get_str() const
bool isNum() const
Definition: univalue.h:94
raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg)
Definition: events.h:46
NODISCARD bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: system.cpp:318
bool isStr() const
Definition: univalue.h:93
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:498
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: system.cpp:523
const char *const BITCOIN_CONF_FILENAME
Definition: system.cpp:73
bool SetupNetworking()
Definition: system.cpp:1325
const std::string & getValStr() const
Definition: univalue.h:77
Client still warming up.
Definition: protocol.h:58
#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
std::string GetHelpMessage() const
Get the help string.
Definition: system.cpp:579
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:214
bool CheckDataDirOption()
Definition: system.cpp:799
Response response
Definition: processor.cpp:249
static const char DEFAULT_RPCCONNECT[]
Definition: bitcoin-cli.cpp:33
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
static const char * http_errorstring(int code)
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:1111
static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args)
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: system.cpp:546
bool HelpRequested(const ArgsManager &args)
Definition: system.cpp:652
#define EVENT_LOG_ERR
static const int CONTINUE_EXECUTION
Definition: bitcoin-cli.cpp:36
bool empty() const
Definition: univalue.h:78
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:51
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
int get_int() const
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
Definition: system.cpp:697
int main(int argc, char *argv[])
UniValue ProcessReply(const UniValue &batch_in) override
Collect values from the batch and form a simulated getinfo reply.
bool isNull() const
Definition: univalue.h:89
Class that handles the conversion from a command-line to a JSON-RPC request, as well as converting ba...
std::string FormatFullVersion()
static void SetupCliArgs(ArgsManager &argsman)
Definition: bitcoin-cli.cpp:38
CConnectionFailed(const std::string &msg)
int RPCPort() const
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:20
fs::path GetConfigFile(const std::string &confPath)
Definition: system.cpp:812
const UniValue & get_obj() const
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:479
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:33
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
Definition: bitcoin-cli.cpp:31
Process default single requests.
ArgsManager gArgs
Definition: system.cpp:76
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:657
std::string body
const UniValue NullUniValue
Definition: univalue.cpp:13
UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert named arguments to command-specific RPC representation.
Definition: client.cpp:233
static const std::string TESTNET
static const bool DEFAULT_NAMED
Definition: bitcoin-cli.cpp:35
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Definition: system.cpp:1014
bool IsSwitchChar(char c)
Definition: system.h:115
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
size_t size() const
Definition: univalue.h:80
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: system.cpp:381
void SelectBaseParams(const std::string &chain)
Sets the params returned by Params() to those for the given network.
Process getinfo requests.
bool error(const char *fmt, const Args &... args)
Definition: system.h:47
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
Definition: request.cpp:112
static void http_request_done(struct evhttp_request *req, void *ctx)
Reply structure for request_done to fill in.
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)