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