Bitcoin Core  21.99.0
P2P Digital Currency
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). Pass \"help\" for detailed help documentation.", ArgsManager::ALLOW_ANY, 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 m_is_help_requested{false};
314  bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
315  bool IsAddressSelected() const { return m_details_level == 2 || m_details_level == 4; }
316  bool IsVersionSelected() const { return m_details_level == 3 || m_details_level == 4; }
317  bool m_is_asmap_on{false};
318  size_t m_max_addr_length{0};
319  size_t m_max_age_length{4};
320  size_t m_max_id_length{2};
321  struct Peer {
322  std::string addr;
323  std::string sub_version;
324  std::string network;
325  std::string age;
326  double min_ping;
327  double ping;
328  int64_t last_blck;
329  int64_t last_recv;
330  int64_t last_send;
331  int64_t last_trxn;
332  int id;
334  int version;
337  bool operator<(const Peer& rhs) const { return std::tie(is_outbound, min_ping) < std::tie(rhs.is_outbound, rhs.min_ping); }
338  };
339  std::vector<Peer> m_peers;
340  std::string ChainToString() const
341  {
342  if (gArgs.GetChainName() == CBaseChainParams::TESTNET) return " testnet";
343  if (gArgs.GetChainName() == CBaseChainParams::SIGNET) return " signet";
344  if (gArgs.GetChainName() == CBaseChainParams::REGTEST) return " regtest";
345  return "";
346  }
347  std::string PingTimeToString(double seconds) const
348  {
349  if (seconds < 0) return "";
350  const double milliseconds{round(1000 * seconds)};
351  return milliseconds > 999999 ? "-" : ToString(milliseconds);
352  }
354  {
355  return std::string{
356  "-netinfo level|\"help\" \n\n"
357  "Returns a network peer connections dashboard with information from the remote server.\n"
358  "Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.\n"
359  "An optional integer argument from 0 to 4 can be passed for different peers listings.\n"
360  "Pass \"help\" to see this detailed help documentation.\n"
361  "If more than one argument is passed, only the first one is read and parsed.\n"
362  "Suggestion: use with the Linux watch(1) command for a live dashboard; see example below.\n\n"
363  "Arguments:\n"
364  "1. level (integer 0-4, optional) Specify the info level of the peers dashboard (default 0):\n"
365  " 0 - Connection counts and local addresses\n"
366  " 1 - Like 0 but with a peers listing (without address or version columns)\n"
367  " 2 - Like 1 but with an address column\n"
368  " 3 - Like 1 but with a version column\n"
369  " 4 - Like 1 but with both address and version columns\n"
370  "2. help (string \"help\", optional) Print this help documentation instead of the dashboard.\n\n"
371  "Result:\n\n"
372  "* The peers listing in levels 1-4 displays all of the peers sorted by direction and minimum ping time:\n\n"
373  " Column Description\n"
374  " ------ -----------\n"
375  " <-> Direction\n"
376  " \"in\" - inbound connections are those initiated by the peer\n"
377  " \"out\" - outbound connections are those initiated by us\n"
378  " type Type of peer connection\n"
379  " \"full\" - full relay, the default\n"
380  " \"block\" - block relay; like full relay but does not relay transactions or addresses\n"
381  " net Network the peer connected through (\"ipv4\", \"ipv6\", \"onion\", \"i2p\", or \"cjdns\")\n"
382  " mping Minimum observed ping time, in milliseconds (ms)\n"
383  " ping Last observed ping time, in milliseconds (ms)\n"
384  " send Time since last message sent to the peer, in seconds\n"
385  " recv Time since last message received from the peer, in seconds\n"
386  " txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes\n"
387  " blk Time since last novel block passing initial validity checks received from the peer, in minutes\n"
388  " age Duration of connection to the peer, in minutes\n"
389  " asmap Mapped AS (Autonomous System) number in the BGP route to the peer, used for diversifying\n"
390  " peer selection (only displayed if the -asmap config option is set)\n"
391  " id Peer index, in increasing order of peer connections since node startup\n"
392  " address IP address and port of the peer\n"
393  " version Peer version and subversion concatenated, e.g. \"70016/Satoshi:21.0.0/\"\n\n"
394  "* The connection counts table displays the number of peers by direction, network, and the totals\n"
395  " for each, as well as a column for block relay peers.\n\n"
396  "* The local addresses table lists each local address broadcast by the node, the port, and the score.\n\n"
397  "Examples:\n\n"
398  "Connection counts and local addresses only\n"
399  "> bitcoin-cli -netinfo\n\n"
400  "Compact peers listing\n"
401  "> bitcoin-cli -netinfo 1\n\n"
402  "Full dashboard\n"
403  "> bitcoin-cli -netinfo 4\n\n"
404  "Full live dashboard, adjust --interval or --no-title as needed (Linux)\n"
405  "> watch --interval 1 --no-title bitcoin-cli -netinfo 4\n\n"
406  "See this help\n"
407  "> bitcoin-cli -netinfo help\n"};
408  }
409  const int64_t m_time_now{GetSystemTimeInSeconds()};
410 
411 public:
412  static constexpr int ID_PEERINFO = 0;
413  static constexpr int ID_NETWORKINFO = 1;
414 
415  UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
416  {
417  if (!args.empty()) {
418  uint8_t n{0};
419  if (ParseUInt8(args.at(0), &n)) {
420  m_details_level = n;
421  } else if (args.at(0) == "help") {
422  m_is_help_requested = true;
423  } else {
424  throw std::runtime_error(strprintf("invalid -netinfo argument: %s", args.at(0)));
425  }
426  }
427  UniValue result(UniValue::VARR);
428  result.push_back(JSONRPCRequestObj("getpeerinfo", NullUniValue, ID_PEERINFO));
429  result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
430  return result;
431  }
432 
433  UniValue ProcessReply(const UniValue& batch_in) override
434  {
435  if (m_is_help_requested) {
436  return JSONRPCReplyObj(NetinfoHelp(), NullUniValue, 1);
437  }
438  const std::vector<UniValue> batch{JSONRPCProcessBatchReply(batch_in)};
439  if (!batch[ID_PEERINFO]["error"].isNull()) return batch[ID_PEERINFO];
440  if (!batch[ID_NETWORKINFO]["error"].isNull()) return batch[ID_NETWORKINFO];
441 
442  const UniValue& networkinfo{batch[ID_NETWORKINFO]["result"]};
443  if (networkinfo["version"].get_int() < 209900) {
444  throw std::runtime_error("-netinfo requires bitcoind server to be running v0.21.0 and up");
445  }
446 
447  // Count peer connection totals, and if DetailsRequested(), store peer data in a vector of structs.
448  for (const UniValue& peer : batch[ID_PEERINFO]["result"].getValues()) {
449  const std::string network{peer["network"].get_str()};
450  const int8_t network_id{NetworkStringToId(network)};
451  if (network_id == UNKNOWN_NETWORK) continue;
452  const bool is_outbound{!peer["inbound"].get_bool()};
453  const bool is_block_relay{!peer["relaytxes"].get_bool()};
454  ++m_counts.at(is_outbound).at(network_id); // in/out by network
455  ++m_counts.at(is_outbound).at(m_networks_size); // in/out overall
456  ++m_counts.at(2).at(network_id); // total by network
457  ++m_counts.at(2).at(m_networks_size); // total overall
458  if (is_block_relay) {
459  ++m_counts.at(is_outbound).at(m_networks_size + 1); // in/out block-relay
460  ++m_counts.at(2).at(m_networks_size + 1); // total block-relay
461  }
462  if (DetailsRequested()) {
463  // Push data for this peer to the peers vector.
464  const int peer_id{peer["id"].get_int()};
465  const int mapped_as{peer["mapped_as"].isNull() ? 0 : peer["mapped_as"].get_int()};
466  const int version{peer["version"].get_int()};
467  const int64_t conn_time{peer["conntime"].get_int64()};
468  const int64_t last_blck{peer["last_block"].get_int64()};
469  const int64_t last_recv{peer["lastrecv"].get_int64()};
470  const int64_t last_send{peer["lastsend"].get_int64()};
471  const int64_t last_trxn{peer["last_transaction"].get_int64()};
472  const double min_ping{peer["minping"].isNull() ? -1 : peer["minping"].get_real()};
473  const double ping{peer["pingtime"].isNull() ? -1 : peer["pingtime"].get_real()};
474  const std::string addr{peer["addr"].get_str()};
475  const std::string age{conn_time == 0 ? "" : ToString((m_time_now - conn_time) / 60)};
476  const std::string sub_version{peer["subver"].get_str()};
477  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});
478  m_max_addr_length = std::max(addr.length() + 1, m_max_addr_length);
479  m_max_age_length = std::max(age.length(), m_max_age_length);
480  m_max_id_length = std::max(ToString(peer_id).length(), m_max_id_length);
481  m_is_asmap_on |= (mapped_as != 0);
482  }
483  }
484 
485  // Generate report header.
486  std::string result{strprintf("%s %s%s - %i%s\n\n", PACKAGE_NAME, FormatFullVersion(), ChainToString(), networkinfo["protocolversion"].get_int(), networkinfo["subversion"].get_str())};
487 
488  // Report detailed peer connections list sorted by direction and minimum ping time.
489  if (DetailsRequested() && !m_peers.empty()) {
490  std::sort(m_peers.begin(), m_peers.end());
491  result += strprintf("<-> relay net mping ping send recv txn blk %*s ", m_max_age_length, "age");
492  if (m_is_asmap_on) result += " asmap ";
493  result += strprintf("%*s %-*s%s\n", m_max_id_length, "id", IsAddressSelected() ? m_max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
494  for (const Peer& peer : m_peers) {
495  std::string version{ToString(peer.version) + peer.sub_version};
496  result += strprintf(
497  "%3s %5s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s\n",
498  peer.is_outbound ? "out" : "in",
499  peer.is_block_relay ? "block" : "full",
500  peer.network,
501  PingTimeToString(peer.min_ping),
502  PingTimeToString(peer.ping),
503  peer.last_send == 0 ? "" : ToString(m_time_now - peer.last_send),
504  peer.last_recv == 0 ? "" : ToString(m_time_now - peer.last_recv),
505  peer.last_trxn == 0 ? "" : ToString((m_time_now - peer.last_trxn) / 60),
506  peer.last_blck == 0 ? "" : ToString((m_time_now - peer.last_blck) / 60),
507  m_max_age_length, // variable spacing
508  peer.age,
509  m_is_asmap_on ? 7 : 0, // variable spacing
510  m_is_asmap_on && peer.mapped_as != 0 ? ToString(peer.mapped_as) : "",
511  m_max_id_length, // variable spacing
512  peer.id,
513  IsAddressSelected() ? m_max_addr_length : 0, // variable spacing
514  IsAddressSelected() ? peer.addr : "",
515  IsVersionSelected() && version != "0" ? version : "");
516  }
517  result += strprintf(" ms ms sec sec min min %*s\n\n", m_max_age_length, "min");
518  }
519 
520  // Report peer connection totals by type.
521  result += " ipv4 ipv6 onion total block-relay\n";
522  const std::array<std::string, 3> rows{{"in", "out", "total"}};
523  for (uint8_t i = 0; i < m_networks_size; ++i) {
524  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));
525  }
526 
527  // Report local addresses, ports, and scores.
528  result += "\nLocal addresses";
529  const std::vector<UniValue>& local_addrs{networkinfo["localaddresses"].getValues()};
530  if (local_addrs.empty()) {
531  result += ": n/a\n";
532  } else {
533  size_t max_addr_size{0};
534  for (const UniValue& addr : local_addrs) {
535  max_addr_size = std::max(addr["address"].get_str().length() + 1, max_addr_size);
536  }
537  for (const UniValue& addr : local_addrs) {
538  result += strprintf("\n%-*s port %6i score %6i", max_addr_size, addr["address"].get_str(), addr["port"].get_int(), addr["score"].get_int());
539  }
540  }
541 
542  return JSONRPCReplyObj(UniValue{result}, NullUniValue, 1);
543  }
544 };
545 
548 {
549 public:
550  UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
551  {
552  address_str = args.at(1);
553  UniValue params{RPCConvertValues("generatetoaddress", args)};
554  return JSONRPCRequestObj("generatetoaddress", params, 1);
555  }
556 
557  UniValue ProcessReply(const UniValue &reply) override
558  {
559  UniValue result(UniValue::VOBJ);
560  result.pushKV("address", address_str);
561  result.pushKV("blocks", reply.get_obj()["result"]);
562  return JSONRPCReplyObj(result, NullUniValue, 1);
563  }
564 protected:
565  std::string address_str;
566 };
567 
570 public:
571  UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
572  {
573  UniValue params;
574  if(gArgs.GetBoolArg("-named", DEFAULT_NAMED)) {
575  params = RPCConvertNamedValues(method, args);
576  } else {
577  params = RPCConvertValues(method, args);
578  }
579  return JSONRPCRequestObj(method, params, 1);
580  }
581 
582  UniValue ProcessReply(const UniValue &reply) override
583  {
584  return reply.get_obj();
585  }
586 };
587 
588 static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const Optional<std::string>& rpcwallet = {})
589 {
590  std::string host;
591  // In preference order, we choose the following for the port:
592  // 1. -rpcport
593  // 2. port in -rpcconnect (ie following : in ipv4 or ]: in ipv6)
594  // 3. default port for chain
595  int port = BaseParams().RPCPort();
596  SplitHostPort(gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT), port, host);
597  port = gArgs.GetArg("-rpcport", port);
598 
599  // Obtain event base
600  raii_event_base base = obtain_event_base();
601 
602  // Synchronously look up hostname
603  raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port);
604 
605  // Set connection timeout
606  {
607  const int timeout = gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT);
608  if (timeout > 0) {
609  evhttp_connection_set_timeout(evcon.get(), timeout);
610  } else {
611  // Indefinite request timeouts are not possible in libevent-http, so we
612  // set the timeout to a very long time period instead.
613 
614  constexpr int YEAR_IN_SECONDS = 31556952; // Average length of year in Gregorian calendar
615  evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
616  }
617  }
618 
619  HTTPReply response;
620  raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response);
621  if (req == nullptr)
622  throw std::runtime_error("create http request failed");
623 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
624  evhttp_request_set_error_cb(req.get(), http_error_cb);
625 #endif
626 
627  // Get credentials
628  std::string strRPCUserColonPass;
629  bool failedToGetAuthCookie = false;
630  if (gArgs.GetArg("-rpcpassword", "") == "") {
631  // Try fall back to cookie-based authentication if no password is provided
632  if (!GetAuthCookie(&strRPCUserColonPass)) {
633  failedToGetAuthCookie = true;
634  }
635  } else {
636  strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", "");
637  }
638 
639  struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
640  assert(output_headers);
641  evhttp_add_header(output_headers, "Host", host.c_str());
642  evhttp_add_header(output_headers, "Connection", "close");
643  evhttp_add_header(output_headers, "Content-Type", "application/json");
644  evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());
645 
646  // Attach request data
647  std::string strRequest = rh->PrepareRequest(strMethod, args).write() + "\n";
648  struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
649  assert(output_buffer);
650  evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
651 
652  // check if we should use a special wallet endpoint
653  std::string endpoint = "/";
654  if (rpcwallet) {
655  char* encodedURI = evhttp_uriencode(rpcwallet->data(), rpcwallet->size(), false);
656  if (encodedURI) {
657  endpoint = "/wallet/" + std::string(encodedURI);
658  free(encodedURI);
659  } else {
660  throw CConnectionFailed("uri-encode failed");
661  }
662  }
663  int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, endpoint.c_str());
664  req.release(); // ownership moved to evcon in above call
665  if (r != 0) {
666  throw CConnectionFailed("send http request failed");
667  }
668 
669  event_base_dispatch(base.get());
670 
671  if (response.status == 0) {
672  std::string responseErrorMessage;
673  if (response.error != -1) {
674  responseErrorMessage = strprintf(" (error code %d - \"%s\")", response.error, http_errorstring(response.error));
675  }
676  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));
677  } else if (response.status == HTTP_UNAUTHORIZED) {
678  if (failedToGetAuthCookie) {
679  throw std::runtime_error(strprintf(
680  "Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
681  GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()));
682  } else {
683  throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
684  }
685  } else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
686  throw std::runtime_error(strprintf("server returned HTTP error %d", response.status));
687  else if (response.body.empty())
688  throw std::runtime_error("no response from server");
689 
690  // Parse reply
691  UniValue valReply(UniValue::VSTR);
692  if (!valReply.read(response.body))
693  throw std::runtime_error("couldn't parse reply from server");
694  const UniValue reply = rh->ProcessReply(valReply);
695  if (reply.empty())
696  throw std::runtime_error("expected reply to have result, error and id properties");
697 
698  return reply;
699 }
700 
710 static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& strMethod, const std::vector<std::string>& args, const Optional<std::string>& rpcwallet = {})
711 {
712  UniValue response(UniValue::VOBJ);
713  // Execute and handle connection failures with -rpcwait.
714  const bool fWait = gArgs.GetBoolArg("-rpcwait", false);
715  do {
716  try {
717  response = CallRPC(rh, strMethod, args, rpcwallet);
718  if (fWait) {
719  const UniValue& error = find_value(response, "error");
720  if (!error.isNull() && error["code"].get_int() == RPC_IN_WARMUP) {
721  throw CConnectionFailed("server in warmup");
722  }
723  }
724  break; // Connection succeeded, no need to retry.
725  } catch (const CConnectionFailed&) {
726  if (fWait) {
727  UninterruptibleSleep(std::chrono::milliseconds{1000});
728  } else {
729  throw;
730  }
731  }
732  } while (fWait);
733  return response;
734 }
735 
737 static void ParseResult(const UniValue& result, std::string& strPrint)
738 {
739  if (result.isNull()) return;
740  strPrint = result.isStr() ? result.get_str() : result.write(2);
741 }
742 
744 static void ParseError(const UniValue& error, std::string& strPrint, int& nRet)
745 {
746  if (error.isObject()) {
747  const UniValue& err_code = find_value(error, "code");
748  const UniValue& err_msg = find_value(error, "message");
749  if (!err_code.isNull()) {
750  strPrint = "error code: " + err_code.getValStr() + "\n";
751  }
752  if (err_msg.isStr()) {
753  strPrint += ("error message:\n" + err_msg.get_str());
754  }
755  if (err_code.isNum() && err_code.get_int() == RPC_WALLET_NOT_SPECIFIED) {
756  strPrint += "\nTry adding \"-rpcwallet=<filename>\" option to bitcoin-cli command line.";
757  }
758  } else {
759  strPrint = "error: " + error.write();
760  }
761  nRet = abs(error["code"].get_int());
762 }
763 
770 static void GetWalletBalances(UniValue& result)
771 {
773  const UniValue listwallets = ConnectAndCallRPC(&rh, "listwallets", /* args=*/{});
774  if (!find_value(listwallets, "error").isNull()) return;
775  const UniValue& wallets = find_value(listwallets, "result");
776  if (wallets.size() <= 1) return;
777 
778  UniValue balances(UniValue::VOBJ);
779  for (const UniValue& wallet : wallets.getValues()) {
780  const std::string wallet_name = wallet.get_str();
781  const UniValue getbalances = ConnectAndCallRPC(&rh, "getbalances", /* args=*/{}, wallet_name);
782  const UniValue& balance = find_value(getbalances, "result")["mine"]["trusted"];
783  balances.pushKV(wallet_name, balance);
784  }
785  result.pushKV("balances", balances);
786 }
787 
793 {
794  Optional<std::string> wallet_name{};
795  if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", "");
797  return ConnectAndCallRPC(&rh, "getnewaddress", /* args=*/{}, wallet_name);
798 }
799 
805 static void SetGenerateToAddressArgs(const std::string& address, std::vector<std::string>& args)
806 {
807  if (args.size() > 2) throw std::runtime_error("too many arguments (maximum 2 for nblocks and maxtries)");
808  if (args.size() == 0) {
809  args.emplace_back(DEFAULT_NBLOCKS);
810  } else if (args.at(0) == "0") {
811  throw std::runtime_error("the first argument (number of blocks to generate, default: " + DEFAULT_NBLOCKS + ") must be an integer value greater than zero");
812  }
813  args.emplace(args.begin() + 1, address);
814 }
815 
816 static int CommandLineRPC(int argc, char *argv[])
817 {
818  std::string strPrint;
819  int nRet = 0;
820  try {
821  // Skip switches
822  while (argc > 1 && IsSwitchChar(argv[1][0])) {
823  argc--;
824  argv++;
825  }
826  std::string rpcPass;
827  if (gArgs.GetBoolArg("-stdinrpcpass", false)) {
828  NO_STDIN_ECHO();
829  if (!StdinReady()) {
830  fputs("RPC password> ", stderr);
831  fflush(stderr);
832  }
833  if (!std::getline(std::cin, rpcPass)) {
834  throw std::runtime_error("-stdinrpcpass specified but failed to read from standard input");
835  }
836  if (StdinTerminal()) {
837  fputc('\n', stdout);
838  }
839  gArgs.ForceSetArg("-rpcpassword", rpcPass);
840  }
841  std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
842  if (gArgs.GetBoolArg("-stdinwalletpassphrase", false)) {
843  NO_STDIN_ECHO();
844  std::string walletPass;
845  if (args.size() < 1 || args[0].substr(0, 16) != "walletpassphrase") {
846  throw std::runtime_error("-stdinwalletpassphrase is only applicable for walletpassphrase(change)");
847  }
848  if (!StdinReady()) {
849  fputs("Wallet passphrase> ", stderr);
850  fflush(stderr);
851  }
852  if (!std::getline(std::cin, walletPass)) {
853  throw std::runtime_error("-stdinwalletpassphrase specified but failed to read from standard input");
854  }
855  if (StdinTerminal()) {
856  fputc('\n', stdout);
857  }
858  args.insert(args.begin() + 1, walletPass);
859  }
860  if (gArgs.GetBoolArg("-stdin", false)) {
861  // Read one arg per line from stdin and append
862  std::string line;
863  while (std::getline(std::cin, line)) {
864  args.push_back(line);
865  }
866  if (StdinTerminal()) {
867  fputc('\n', stdout);
868  }
869  }
870  std::unique_ptr<BaseRequestHandler> rh;
871  std::string method;
872  if (gArgs.IsArgSet("-getinfo")) {
873  rh.reset(new GetinfoRequestHandler());
874  } else if (gArgs.GetBoolArg("-netinfo", false)) {
875  rh.reset(new NetinfoRequestHandler());
876  } else if (gArgs.GetBoolArg("-generate", false)) {
878  const UniValue& error{find_value(getnewaddress, "error")};
879  if (error.isNull()) {
880  SetGenerateToAddressArgs(find_value(getnewaddress, "result").get_str(), args);
881  rh.reset(new GenerateToAddressRequestHandler());
882  } else {
883  ParseError(error, strPrint, nRet);
884  }
885  } else {
886  rh.reset(new DefaultRequestHandler());
887  if (args.size() < 1) {
888  throw std::runtime_error("too few parameters (need at least command)");
889  }
890  method = args[0];
891  args.erase(args.begin()); // Remove trailing method name from arguments vector
892  }
893  if (nRet == 0) {
894  // Perform RPC call
895  Optional<std::string> wallet_name{};
896  if (gArgs.IsArgSet("-rpcwallet")) wallet_name = gArgs.GetArg("-rpcwallet", "");
897  const UniValue reply = ConnectAndCallRPC(rh.get(), method, args, wallet_name);
898 
899  // Parse reply
900  UniValue result = find_value(reply, "result");
901  const UniValue& error = find_value(reply, "error");
902  if (error.isNull()) {
903  if (gArgs.IsArgSet("-getinfo") && !gArgs.IsArgSet("-rpcwallet")) {
904  GetWalletBalances(result); // fetch multiwallet balances and append to result
905  }
906  ParseResult(result, strPrint);
907  } else {
908  ParseError(error, strPrint, nRet);
909  }
910  }
911  } catch (const std::exception& e) {
912  strPrint = std::string("error: ") + e.what();
913  nRet = EXIT_FAILURE;
914  } catch (...) {
915  PrintExceptionContinue(nullptr, "CommandLineRPC()");
916  throw;
917  }
918 
919  if (strPrint != "") {
920  tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
921  }
922  return nRet;
923 }
924 
925 #ifdef WIN32
926 // Export main() and ensure working ASLR on Windows.
927 // Exporting a symbol will prevent the linker from stripping
928 // the .reloc section from the binary, which is a requirement
929 // for ASLR. This is a temporary workaround until a fixed
930 // version of binutils is used for releases.
931 __declspec(dllexport) int main(int argc, char* argv[])
932 {
933  util::WinCmdLineArgs winArgs;
934  std::tie(argc, argv) = winArgs.get();
935 #else
936 int main(int argc, char* argv[])
937 {
938 #endif
940  if (!SetupNetworking()) {
941  tfm::format(std::cerr, "Error: Initializing networking failed\n");
942  return EXIT_FAILURE;
943  }
944  event_set_log_callback(&libevent_log_cb);
945 
946  try {
947  int ret = AppInitRPC(argc, argv);
948  if (ret != CONTINUE_EXECUTION)
949  return ret;
950  }
951  catch (const std::exception& e) {
952  PrintExceptionContinue(&e, "AppInitRPC()");
953  return EXIT_FAILURE;
954  } catch (...) {
955  PrintExceptionContinue(nullptr, "AppInitRPC()");
956  return EXIT_FAILURE;
957  }
958 
959  int ret = EXIT_FAILURE;
960  try {
961  ret = CommandLineRPC(argc, argv);
962  }
963  catch (const std::exception& e) {
964  PrintExceptionContinue(&e, "CommandLineRPC()");
965  } catch (...) {
966  PrintExceptionContinue(nullptr, "CommandLineRPC()");
967  }
968  return ret;
969 }
bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
Definition: system.cpp:845
No wallet specified (error when there are multiple wallets loaded)
Definition: protocol.h:81
std::string ChainToString() const
static const std::string DEFAULT_NBLOCKS
Default number of blocks to generate for RPC generatetoaddress.
Definition: bitcoin-cli.cpp:46
bool DetailsRequested() const
static RPCHelpMan ping()
Definition: net.cpp:65
bool isObject() const
Definition: univalue.h:84
bool StdinTerminal()
Definition: stdin.cpp:47
std::unique_ptr< CBaseChainParams > CreateBaseChainParams(const std::string &chain)
Port numbers for incoming Tor connections (8334, 18334, 38334, 18445) have been chosen arbitrarily to...
bool StdinReady()
Definition: stdin.cpp:56
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:371
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.
const std::vector< UniValue > & getValues() const
assert(!tx.IsCoinBase())
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
static int AppInitRPC(int argc, char *argv[])
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 read(const char *raw, size_t len)
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
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={})
int8_t NetworkStringToId(const std::string &str) const
virtual ~BaseRequestHandler()
static const int DEFAULT_HTTP_CLIENT_TIMEOUT
Definition: bitcoin-cli.cpp:41
void SetupEnvironment()
Definition: system.cpp:1237
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
#define PACKAGE_NAME
const std::string & get_str() const
static RPCHelpMan listwallets()
Definition: rpcwallet.cpp:2552
bool isNum() const
Definition: univalue.h:82
raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg)
Definition: events.h:45
bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: system.cpp:284
std::vector< Peer > m_peers
bool isStr() const
Definition: univalue.h:81
static std::string http_errorstring(int code)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:479
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: system.cpp:501
const char *const BITCOIN_CONF_FILENAME
Definition: system.cpp:74
bool SetupNetworking()
Definition: system.cpp:1274
int64_t GetSystemTimeInSeconds()
Returns the system time (not mockable)
Definition: time.cpp:73
const std::string & getValStr() const
Definition: univalue.h:65
Client still warming up.
Definition: protocol.h:49
bool operator<(const Peer &rhs) const
#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:533
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
std::string EncodeBase64(Span< const unsigned char > input)
uint16_t RPCPort() const
static const char DEFAULT_RPCCONNECT[]
Definition: bitcoin-cli.cpp:40
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
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.
static secp256k1_context * ctx
Definition: tests.c:36
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
const UniValue NetinfoHelp()
Process netinfo requests.
static RPCHelpMan getbalances()
Definition: rpcwallet.cpp:2352
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
bool empty() const
Definition: univalue.h:66
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
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
static void GetWalletBalances(UniValue &result)
GetWalletBalances calls listwallets; if more than one wallet is loaded, it then fetches mine...
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:644
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:77
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:48
bool IsVersionSelected() const
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
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:19
fs::path GetConfigFile(const std::string &confPath)
Definition: system.cpp:766
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:467
Process RPC generatetoaddress request.
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
UrlDecodeFn *const URL_DECODE
Definition: bitcoin-cli.cpp:38
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
static const bool DEFAULT_NAMED
Definition: bitcoin-cli.cpp:42
std::string GetChainName() const
Returns the appropriate chain name from the program arguments.
Definition: system.cpp:932
static UniValue GetNewAddress()
Call RPC getnewaddress.
bool IsSwitchChar(char c)
Definition: system.h:134
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.
size_t size() const
Definition: univalue.h:68
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.
bool IsAddressSelected() const
std::string PingTimeToString(double seconds) const
Process getinfo requests.
bool error(const char *fmt, const Args &... args)
Definition: system.h:52
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.
std::optional< T > Optional
Substitute for C++17 std::optional DEPRECATED use std::optional in new code.
Definition: optional.h:14
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)