6#include <bitcoin-build-config.h>
41#include <event2/buffer.h>
42#include <event2/keyvalq_struct.h>
63static constexpr std::array
NETWORKS{
"not_publicly_routable",
"ipv4",
"ipv6",
"onion",
"i2p",
"cjdns",
"internal"};
64static constexpr std::array
NETWORK_SHORT_NAMES{
"npr",
"ipv4",
"ipv6",
"onion",
"i2p",
"cjdns",
"int"};
86 argsman.
AddArg(
"-generate",
87 strprintf(
"Generate blocks, equivalent to RPC getnewaddress followed by RPC generatetoaddress. Optional positional integer "
88 "arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to "
89 "RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000",
93 argsman.
AddArg(
"-getinfo",
"Get general information from the remote server. Note that unlike server-side RPC calls, the output of -getinfo is the result of multiple non-atomic requests. Some entries in the output 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::CLI_COMMANDS);
94 argsman.
AddArg(
"-netinfo",
strprintf(
"Get network peer connection information from the remote server. An optional argument from 0 to %d can be passed for different peers listings (default: 0). If a non-zero value is passed, an additional \"outonly\" (or \"o\") argument can be passed to see outbound peers only. Pass \"help\" (or \"h\") for detailed help documentation.",
NETINFO_MAX_LEVEL),
ArgsManager::ALLOW_ANY,
OptionsCategory::CLI_COMMANDS);
103 argsman.
AddArg(
"-rpcport=<port>",
strprintf(
"Connect to JSON-RPC on <port> (default: %u, testnet: %u, testnet4: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), testnet4BaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()),
ArgsManager::ALLOW_ANY |
ArgsManager::NETWORK_ONLY,
OptionsCategory::OPTIONS);
107 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);
108 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);
109 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);
124 if (severity >= EVENT_LOG_ERR) {
125 throw std::runtime_error(
strprintf(
"libevent error: %s",
msg));
148 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n", error);
152 std::string strUsage = CLIENT_NAME
" RPC client version " +
FormatFullVersion() +
"\n";
158 "The bitcoin-cli utility provides a command line interface to interact with a " CLIENT_NAME
" RPC server.\n"
159 "\nIt can be used to query network information, manage wallets, create or broadcast transactions, and control the " CLIENT_NAME
" server.\n"
160 "\nUse the \"help\" command to list all commands. Use \"help <command>\" to show help for that command.\n"
161 "The -named option allows you to specify parameters using the key=value format, eliminating the need to pass unused positional parameters.\n"
163 "Usage: bitcoin-cli [options] <command> [params]\n"
164 "or: bitcoin-cli [options] -named <command> [name=value]...\n"
165 "or: bitcoin-cli [options] help\n"
166 "or: bitcoin-cli [options] help <command>\n"
173 tfm::format(std::cerr,
"Error: too few parameters\n");
179 tfm::format(std::cerr,
"Error: Specified data directory \"%s\" does not exist.\n",
gArgs.
GetArg(
"-datadir",
""));
183 tfm::format(std::cerr,
"Error reading configuration file: %s\n", error);
189 }
catch (
const std::exception& e) {
210 case EVREQ_HTTP_TIMEOUT:
211 return "timeout reached";
213 return "EOF reached";
214 case EVREQ_HTTP_INVALID_HEADER:
215 return "error while reading header, or invalid header";
216 case EVREQ_HTTP_BUFFER_ERROR:
217 return "error encountered while reading or writing";
218 case EVREQ_HTTP_REQUEST_CANCEL:
219 return "request was canceled";
220 case EVREQ_HTTP_DATA_TOO_LONG:
221 return "response body is larger than allowed";
231 if (req ==
nullptr) {
239 reply->
status = evhttp_request_get_response_code(req);
241 struct evbuffer *buf = evhttp_request_get_input_buffer(req);
244 size_t size = evbuffer_get_length(buf);
245 const char *
data = (
const char*)evbuffer_pullup(buf, size);
247 reply->
body = std::string(
data, size);
248 evbuffer_drain(buf, size);
260 for (
size_t i = 0; i <
NETWORKS.size(); ++i) {
280 throw std::runtime_error(
"-addrinfo takes no arguments");
288 if (!reply[
"error"].isNull())
return reply;
289 const std::vector<UniValue>& nodes{reply[
"result"].
getValues()};
290 if (!nodes.empty() && nodes.at(0)[
"network"].isNull()) {
291 throw std::runtime_error(
"-addrinfo requires bitcoind server to be running v22.0 and up");
294 std::array<uint64_t,
NETWORKS.size()> counts{{}};
296 std::string network_name{
node[
"network"].get_str()};
299 ++counts.at(network_id);
304 for (
size_t i = 1; i <
NETWORKS.size() - 1; ++i) {
305 addresses.pushKV(
NETWORKS[i], counts.at(i));
306 total += counts.at(i);
308 addresses.pushKV(
"total", total);
309 result.pushKV(
"addresses_known", std::move(addresses));
325 throw std::runtime_error(
"-getinfo takes no arguments");
358 result.
pushKV(
"connections", std::move(connections));
364 result.
pushKV(
"has_wallet",
true);
367 if (!batch[
ID_WALLETINFO][
"result"][
"unlocked_until"].isNull()) {
445 if (seconds < 0)
return "";
446 const double milliseconds{round(1000 * seconds)};
447 return milliseconds > 999999 ?
"-" :
ToString(milliseconds);
451 if (conn_type ==
"outbound-full-relay")
return "full";
452 if (conn_type ==
"block-relay-only")
return "block";
453 if (conn_type ==
"manual" || conn_type ==
"feeler")
return conn_type;
454 if (conn_type ==
"addr-fetch")
return "addr";
455 if (conn_type ==
"private-broadcast")
return "priv";
461 for (
size_t i = 0; i < services.
size(); ++i) {
462 const std::string
s{services[i].
get_str()};
463 str +=
s ==
"NETWORK_LIMITED" ?
'l' :
s ==
"P2P_V2" ?
'2' :
ToLower(
s[0]);
469 std::string str{services.
size() ? services[0].
get_str() :
""};
470 for (
size_t i{1}; i < services.
size(); ++i) {
471 str +=
", " + services[i].
get_str();
474 c = (c ==
'_' ?
' ' :
ToLower(c));
487 if (
const auto res{ToIntegral<uint8_t>(
args.at(0))}) {
491 throw std::runtime_error(
strprintf(
"invalid -netinfo level argument: %s\nFor more information, run: bitcoin-cli -netinfo help",
args.at(0)));
493 if (
args.size() > 1) {
494 if (std::string_view
s{
args.at(1)}; n && (
s ==
"o" ||
s ==
"outonly")) {
497 throw std::runtime_error(
strprintf(
"invalid -netinfo outonly argument: %s\nFor more information, run: bitcoin-cli -netinfo help",
s));
499 throw std::runtime_error(
strprintf(
"invalid -netinfo outonly argument: %s\nThe outonly argument is only valid for a level greater than 0 (the first argument). For more information, run: bitcoin-cli -netinfo help",
s));
516 if (networkinfo[
"version"].getInt<int>() < 209900) {
517 throw std::runtime_error(
"-netinfo requires bitcoind server to be running v0.21.0 and up");
519 const int64_t time_now{TicksSinceEpoch<std::chrono::seconds>(CliClock::now())};
523 const std::string network{peer[
"network"].get_str()};
526 const bool is_outbound{!peer[
"inbound"].get_bool()};
527 const bool is_tx_relay{peer[
"relaytxes"].isNull() ? true : peer[
"relaytxes"].get_bool()};
528 const std::string conn_type{peer[
"connection_type"].get_str()};
529 ++
m_counts.at(is_outbound).at(network_id);
538 const int peer_id{peer[
"id"].getInt<
int>()};
539 const int mapped_as{peer[
"mapped_as"].isNull() ? 0 : peer[
"mapped_as"].getInt<
int>()};
540 const int version{peer[
"version"].getInt<
int>()};
541 const int64_t addr_processed{peer[
"addr_processed"].isNull() ? 0 : peer[
"addr_processed"].getInt<int64_t>()};
542 const int64_t addr_rate_limited{peer[
"addr_rate_limited"].isNull() ? 0 : peer[
"addr_rate_limited"].getInt<int64_t>()};
543 const int64_t conn_time{peer[
"conntime"].getInt<int64_t>()};
544 const int64_t last_blck{peer[
"last_block"].getInt<int64_t>()};
545 const int64_t last_recv{peer[
"lastrecv"].getInt<int64_t>()};
546 const int64_t last_send{peer[
"lastsend"].getInt<int64_t>()};
547 const int64_t last_trxn{peer[
"last_transaction"].getInt<int64_t>()};
548 const double min_ping{peer[
"minping"].isNull() ? -1 : peer[
"minping"].get_real()};
549 const double ping{peer[
"pingtime"].isNull() ? -1 : peer[
"pingtime"].get_real()};
550 const std::string addr{peer[
"addr"].get_str()};
551 const std::string age{conn_time == 0 ?
"" :
ToString((time_now - conn_time) / 60)};
552 const std::string services{
FormatServices(peer[
"servicesnames"])};
553 const std::string sub_version{peer[
"subver"].get_str()};
554 const std::string transport{peer[
"transport_protocol_type"].isNull() ?
"v1" : peer[
"transport_protocol_type"].get_str()};
555 const bool is_addr_relay_enabled{peer[
"addr_relay_enabled"].isNull() ? false : peer[
"addr_relay_enabled"].get_bool()};
556 const bool is_bip152_hb_from{peer[
"bip152_hb_from"].get_bool()};
557 const bool is_bip152_hb_to{peer[
"bip152_hb_to"].get_bool()};
558 m_peers.push_back({addr, sub_version, conn_type,
NETWORK_SHORT_NAMES[network_id], age, services, transport, min_ping,
ping, addr_processed, addr_rate_limited, last_blck, last_recv, last_send, last_trxn, peer_id, mapped_as, version, is_addr_relay_enabled, is_bip152_hb_from, is_bip152_hb_to, is_outbound, is_tx_relay});
571 std::string result{
strprintf(
"%s client %s%s - server %i%s%s\n\n", CLIENT_NAME,
FormatFullVersion(),
ChainToString(), networkinfo[
"protocolversion"].getInt<int>(), networkinfo[
"subversion"].get_str(), services)};
576 result +=
strprintf(
"<-> type net %*s v mping ping send recv txn blk hb %*s%*s%*s ",
584 std::string version{
ToString(peer.version) + peer.sub_version};
586 "%3s %6s %5s %*s %2s%7s%7s%5s%5s%5s%5s %2s %*s%*s%*s%*i %*s %-*s%s\n",
587 peer.is_outbound ?
"out" :
"in",
592 (peer.transport_protocol_type.size() == 2 && peer.transport_protocol_type[0] ==
'v') ? peer.transport_protocol_type[1] :
' ',
595 peer.last_send ?
ToString(time_now - peer.last_send) :
"",
596 peer.last_recv ?
ToString(time_now - peer.last_recv) :
"",
597 peer.last_trxn ?
ToString((time_now - peer.last_trxn) / 60) : peer.is_tx_relay ?
"" :
"*",
598 peer.last_blck ?
ToString((time_now - peer.last_blck) / 60) :
"",
599 strprintf(
"%s%s", peer.is_bip152_hb_to ?
"." :
" ", peer.is_bip152_hb_from ?
"*" :
" "),
601 peer.addr_processed ?
ToString(peer.addr_processed) : peer.is_addr_relay_enabled ?
"" :
".",
603 peer.addr_rate_limited ?
ToString(peer.addr_rate_limited) :
"",
619 std::vector<int8_t> reachable_networks;
620 for (
const UniValue& network : networkinfo[
"networks"].getValues()) {
621 if (network[
"reachable"].get_bool()) {
622 const std::string& network_name{network[
"name"].get_str()};
625 result +=
strprintf(
"%8s", network_name);
626 reachable_networks.push_back(network_id);
631 if (
m_counts.at(2).at(network_id) == 0)
continue;
633 reachable_networks.push_back(network_id);
636 result +=
" total block";
639 const std::array rows{
"in",
"out",
"total"};
640 for (
size_t i = 0; i < rows.size(); ++i) {
642 for (int8_t n : reachable_networks) {
656 result +=
"\n\nLocal addresses";
657 const std::vector<UniValue>& local_addrs{networkinfo[
"localaddresses"].getValues()};
658 if (local_addrs.empty()) {
661 size_t max_addr_size{0};
662 for (
const UniValue& addr : local_addrs) {
663 max_addr_size = std::max(addr[
"address"].get_str().length() + 1, max_addr_size);
665 for (
const UniValue& addr : local_addrs) {
666 result +=
strprintf(
"\n%-*s port %6i score %6i", max_addr_size, addr[
"address"].get_str(), addr[
"port"].getInt<int>(), addr[
"score"].getInt<int>());
674 "-netinfo (level [outonly]) | help\n\n"
675 "Returns a network peer connections dashboard with information from the remote server.\n"
676 "This human-readable interface will change regularly and is not intended to be a stable API.\n"
677 "Under the hood, -netinfo fetches the data by calling getpeerinfo and getnetworkinfo.\n"
679 "If that argument is passed, an optional additional \"outonly\" argument may be passed to obtain the listing with outbound peers only.\n"
680 "Pass \"help\" or \"h\" to see this detailed help documentation.\n"
681 "If more than two arguments are passed, only the first two are read and parsed.\n"
682 "Suggestion: use -netinfo with the Linux watch(1) command for a live dashboard; see example below.\n\n"
684 +
strprintf(
"1. level (integer 0-%d, optional) Specify the info level of the peers dashboard (default 0):\n",
NETINFO_MAX_LEVEL) +
685 " 0 - Peer counts for each reachable network as well as for block relay peers\n"
686 " and manual peers, and the list of local addresses and ports\n"
687 " 1 - Like 0 but preceded by a peers listing (without address and version columns)\n"
688 " 2 - Like 1 but with an address column\n"
689 " 3 - Like 1 but with a version column\n"
690 " 4 - Like 1 but with both address and version columns\n"
691 "2. outonly (\"outonly\" or \"o\", optional) Return the peers listing with outbound peers only, i.e. to save screen space\n"
692 " when a node has many inbound peers. Only valid if a level is passed.\n\n"
693 "help (\"help\" or \"h\", optional) Print this help documentation instead of the dashboard.\n\n"
695 +
strprintf(
"* The peers listing in levels 1-%d displays all of the peers sorted by direction and minimum ping time:\n\n",
NETINFO_MAX_LEVEL) +
696 " Column Description\n"
697 " ------ -----------\n"
699 " \"in\" - inbound connections are those initiated by the peer\n"
700 " \"out\" - outbound connections are those initiated by us\n"
701 " type Type of peer connection\n"
702 " \"full\" - full relay, the default\n"
703 " \"block\" - block relay; like full relay but does not relay transactions or addresses\n"
704 " \"manual\" - peer we manually added using RPC addnode or the -addnode/-connect config options\n"
705 " \"feeler\" - short-lived connection for testing addresses\n"
706 " \"addr\" - address fetch; short-lived connection for requesting addresses\n"
707 " \"priv\" - private broadcast; short-lived connection for broadcasting our transactions\n"
708 " net Network the peer connected through (\"ipv4\", \"ipv6\", \"onion\", \"i2p\", \"cjdns\", or \"npr\" (not publicly routable))\n"
709 " serv Services offered by the peer\n"
710 " \"n\" - NETWORK: peer can serve the full block chain\n"
711 " \"b\" - BLOOM: peer can handle bloom-filtered connections (see BIP 111)\n"
712 " \"w\" - WITNESS: peer can be asked for blocks and transactions with witness data (SegWit)\n"
713 " \"c\" - COMPACT_FILTERS: peer can handle basic block filter requests (see BIPs 157 and 158)\n"
714 " \"l\" - NETWORK_LIMITED: peer limited to serving only the last 288 blocks (~2 days)\n"
715 " \"2\" - P2P_V2: peer supports version 2 P2P transport protocol, as defined in BIP 324\n"
716 " \"u\" - UNKNOWN: unrecognized bit flag\n"
717 " v Version of transport protocol used for the connection\n"
718 " mping Minimum observed ping time, in milliseconds (ms)\n"
719 " ping Last observed ping time, in milliseconds (ms)\n"
720 " send Time since last message sent to the peer, in seconds\n"
721 " recv Time since last message received from the peer, in seconds\n"
722 " txn Time since last novel transaction received from the peer and accepted into our mempool, in minutes\n"
723 " \"*\" - we do not relay transactions to this peer (getpeerinfo \"relaytxes\" is false)\n"
724 " blk Time since last novel block passing initial validity checks received from the peer, in minutes\n"
725 " hb High-bandwidth BIP152 compact block relay\n"
726 " \".\" (to) - we selected the peer as a high-bandwidth peer\n"
727 " \"*\" (from) - the peer selected us as a high-bandwidth peer\n"
728 " addrp Total number of addresses processed, excluding those dropped due to rate limiting\n"
729 " \".\" - we do not relay addresses to this peer (getpeerinfo \"addr_relay_enabled\" is false)\n"
730 " addrl Total number of addresses dropped due to rate limiting\n"
731 " age Duration of connection to the peer, in minutes\n"
732 " asmap Mapped AS (Autonomous System) number at the end of the BGP route to the peer, used for diversifying\n"
733 " peer selection (only displayed if the -asmap config option is set)\n"
734 " id Peer index, in increasing order of peer connections since node startup\n"
735 " address IP address and port of the peer\n"
736 " version Peer version and subversion concatenated, e.g. \"70016/Satoshi:21.0.0/\"\n\n"
737 "* The peer counts table displays the number of peers for each reachable network as well as\n"
738 " the number of block relay peers and manual peers.\n\n"
739 "* The local addresses table lists each local address broadcast by the node, the port, and the score.\n\n"
741 "Peer counts table of reachable networks and list of local addresses\n"
742 "> bitcoin-cli -netinfo\n\n"
743 "The same, preceded by a peers listing without address and version columns\n"
744 "> bitcoin-cli -netinfo 1\n\n"
747 "Full dashboard, but with outbound peers only\n"
749 "Full live dashboard, adjust --interval or --no-title as needed (Linux)\n"
752 "> bitcoin-cli -netinfo help\n"};
805 uint16_t rpcconnect_port{0};
811 throw std::runtime_error(
strprintf(
"Invalid port provided in -rpcconnect: %s", rpcconnect_str));
813 if (rpcconnect_port != 0) {
815 port = rpcconnect_port;
819 if (std::optional<std::string> rpcport_arg =
gArgs.
GetArg(
"-rpcport")) {
821 const uint16_t rpcport_int{ToIntegral<uint16_t>(rpcport_arg.value()).value_or(0)};
822 if (rpcport_int == 0) {
826 throw std::runtime_error(
strprintf(
"Invalid port provided in -rpcport: %s", rpcport_arg.value()));
834 if (rpcconnect_port != 0) {
835 tfm::format(std::cerr,
"Warning: Port specified in both -rpcconnect and -rpcport. Using -rpcport %u\n", port);
850 evhttp_connection_set_timeout(evcon.get(), timeout);
855 constexpr int YEAR_IN_SECONDS = 31556952;
856 evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
862 if (req ==
nullptr) {
863 throw std::runtime_error(
"create http request failed");
869 std::string strRPCUserColonPass;
870 bool failedToGetAuthCookie =
false;
874 failedToGetAuthCookie =
true;
880 struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
882 evhttp_add_header(output_headers,
"Host", host.c_str());
883 evhttp_add_header(output_headers,
"Connection",
"close");
884 evhttp_add_header(output_headers,
"Content-Type",
"application/json");
885 evhttp_add_header(output_headers,
"Authorization", (std::string(
"Basic ") +
EncodeBase64(strRPCUserColonPass)).c_str());
889 struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
891 evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
894 std::string endpoint =
"/";
896 char* encodedURI = evhttp_uriencode(rpcwallet->data(), rpcwallet->size(),
false);
898 endpoint =
"/wallet/" + std::string(encodedURI);
904 int r = evhttp_make_request(evcon.get(), req.release(), EVHTTP_REQ_POST, endpoint.c_str());
909 event_base_dispatch(base.get());
911 if (response.
status == 0) {
912 std::string responseErrorMessage;
913 if (response.
error != -1) {
917 "Make sure the bitcoind server is running and that you are connecting to the correct RPC port.\n"
918 "Use \"bitcoin-cli -help\" for more info.",
919 host, port, responseErrorMessage));
921 if (failedToGetAuthCookie) {
923 "Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
926 throw std::runtime_error(
"Authorization failed: Incorrect rpcuser or rpcpassword");
929 throw std::runtime_error(
strprintf(
"Server response: %s", response.
body));
931 throw std::runtime_error(
strprintf(
"server returned HTTP error %d", response.
status));
932 else if (response.
body.empty())
933 throw std::runtime_error(
"no response from server");
937 if (!valReply.read(response.
body))
938 throw std::runtime_error(
"couldn't parse reply from server");
941 throw std::runtime_error(
"expected reply to have result, error and id properties");
961 const auto deadline{std::chrono::steady_clock::now() + 1
s * timeout};
965 response =
CallRPC(rh, strMethod,
args, rpcwallet);
967 const UniValue& error = response.find_value(
"error");
974 if (fWait && (timeout <= 0 || std::chrono::steady_clock::now() < deadline)) {
987 if (result.
isNull())
return;
1000 if (err_msg.
isStr()) {
1004 strPrint +=
" Or for the CLI, specify the \"-rpcwallet=<walletname>\" option before the command";
1005 strPrint +=
" (run \"bitcoin-cli -h\" for help or \"bitcoin-cli listwallets\" to see which wallets are currently loaded).";
1010 nRet = abs(error[
"code"].getInt<int>());
1023 if (!
listwallets.find_value(
"error").isNull())
return;
1025 if (wallets.
size() <= 1)
return;
1029 const std::string& wallet_name =
wallet.get_str();
1032 balances.
pushKV(wallet_name, balance);
1034 result.
pushKV(
"balances", std::move(balances));
1045 if (progress < 0 || progress > 1)
return;
1047 static constexpr double INCREMENT{0.05};
1048 static const std::string COMPLETE_BAR{
"\u2592"};
1049 static const std::string INCOMPLETE_BAR{
"\u2591"};
1051 for (
int i = 0; i < progress / INCREMENT; ++i) {
1052 progress_bar += COMPLETE_BAR;
1055 for (
int i = 0; i < (1 - progress) / INCREMENT; ++i) {
1056 progress_bar += INCOMPLETE_BAR;
1069 std::string RESET, GREEN, BLUE, YELLOW, MAGENTA, CYAN;
1070 bool should_colorize =
false;
1073 if (isatty(fileno(stdout))) {
1075 should_colorize =
true;
1081 if (color ==
"always") {
1082 should_colorize =
true;
1083 }
else if (color ==
"never") {
1084 should_colorize =
false;
1085 }
else if (color !=
"auto") {
1086 throw std::runtime_error(
"Invalid value for -color option. Valid values: always, auto, never.");
1090 if (should_colorize) {
1094 YELLOW =
"\x1B[33m";
1095 MAGENTA =
"\x1B[35m";
1099 std::string result_string =
strprintf(
"%sChain: %s%s\n", BLUE, result[
"chain"].getValStr(), RESET);
1100 result_string +=
strprintf(
"Blocks: %s\n", result[
"blocks"].getValStr());
1101 result_string +=
strprintf(
"Headers: %s\n", result[
"headers"].getValStr());
1103 const double ibd_progress{result[
"verificationprogress"].
get_real()};
1104 std::string ibd_progress_bar;
1106 if (ibd_progress < 0.99) {
1109 ibd_progress_bar +=
" ";
1112 result_string +=
strprintf(
"Verification progress: %s%.4f%%\n", ibd_progress_bar, ibd_progress * 100);
1113 result_string +=
strprintf(
"Difficulty: %s\n\n", result[
"difficulty"].getValStr());
1116 "%sNetwork: in %s, out %s, total %s%s\n",
1118 result[
"connections"][
"in"].getValStr(),
1119 result[
"connections"][
"out"].getValStr(),
1120 result[
"connections"][
"total"].getValStr(),
1122 result_string +=
strprintf(
"Version: %s\n", result[
"version"].getValStr());
1123 result_string +=
strprintf(
"Time offset (s): %s\n", result[
"timeoffset"].getValStr());
1126 std::map<std::string, std::vector<std::string>> proxy_networks;
1127 std::vector<std::string> ordered_proxies;
1129 for (
const UniValue& network : result[
"networks"].getValues()) {
1130 const std::string proxy = network[
"proxy"].getValStr();
1131 if (proxy.empty())
continue;
1133 if (!proxy_networks.contains(proxy)) ordered_proxies.push_back(proxy);
1135 proxy_networks[proxy].push_back(network[
"name"].getValStr());
1138 std::vector<std::string> formatted_proxies;
1139 formatted_proxies.reserve(ordered_proxies.size());
1140 for (
const std::string& proxy : ordered_proxies) {
1141 formatted_proxies.emplace_back(
strprintf(
"%s (%s)", proxy,
Join(proxy_networks.find(proxy)->second,
", ")));
1143 result_string +=
strprintf(
"Proxies: %s\n", formatted_proxies.empty() ?
"n/a" :
Join(formatted_proxies,
", "));
1145 result_string +=
strprintf(
"Min tx relay fee rate (%s/kvB): %s\n\n",
CURRENCY_UNIT, result[
"relayfee"].getValStr());
1147 if (!result[
"has_wallet"].isNull()) {
1148 const std::string walletname = result[
"walletname"].
getValStr();
1149 result_string +=
strprintf(
"%sWallet: %s%s\n", MAGENTA, walletname.empty() ?
"\"\"" : walletname, RESET);
1151 result_string +=
strprintf(
"Keypool size: %s\n", result[
"keypoolsize"].getValStr());
1152 if (!result[
"unlocked_until"].isNull()) {
1153 result_string +=
strprintf(
"Unlocked until: %s\n", result[
"unlocked_until"].getValStr());
1155 result_string +=
strprintf(
"Transaction fee rate (-paytxfee) (%s/kvB): %s\n\n",
CURRENCY_UNIT, result[
"paytxfee"].getValStr());
1157 if (!result[
"balance"].isNull()) {
1158 result_string +=
strprintf(
"%sBalance:%s %s\n\n", CYAN, RESET, result[
"balance"].getValStr());
1161 if (!result[
"balances"].isNull()) {
1162 result_string +=
strprintf(
"%sBalances%s\n", CYAN, RESET);
1164 size_t max_balance_length{10};
1166 for (
const std::string&
wallet : result[
"balances"].getKeys()) {
1167 max_balance_length = std::max(result[
"balances"][
wallet].getValStr().length(), max_balance_length);
1170 for (
const std::string&
wallet : result[
"balances"].getKeys()) {
1173 result[
"balances"][
wallet].getValStr(),
1176 result_string +=
"\n";
1179 const std::string warnings{result[
"warnings"].
getValStr()};
1180 result_string +=
strprintf(
"%sWarnings:%s %s", YELLOW, RESET, warnings.empty() ?
"(none)" : warnings);
1182 result.
setStr(result_string);
1202 if (
args.size() > 2)
throw std::runtime_error(
"too many arguments (maximum 2 for nblocks and maxtries)");
1203 if (
args.size() == 0) {
1205 }
else if (
args.at(0) ==
"0") {
1206 throw std::runtime_error(
"the first argument (number of blocks to generate, default: " +
DEFAULT_NBLOCKS +
") must be an integer value greater than zero");
1208 args.emplace(
args.begin() + 1, address);
1221 std::string rpcPass;
1225 fputs(
"RPC password> ", stderr);
1228 if (!std::getline(std::cin, rpcPass)) {
1229 throw std::runtime_error(
"-stdinrpcpass specified but failed to read from standard input");
1232 fputc(
'\n', stdout);
1236 std::vector<std::string>
args = std::vector<std::string>(&argv[1], &argv[argc]);
1239 std::string walletPass;
1240 if (
args.size() < 1 || !
args[0].starts_with(
"walletpassphrase")) {
1241 throw std::runtime_error(
"-stdinwalletpassphrase is only applicable for walletpassphrase(change)");
1244 fputs(
"Wallet passphrase> ", stderr);
1247 if (!std::getline(std::cin, walletPass)) {
1248 throw std::runtime_error(
"-stdinwalletpassphrase specified but failed to read from standard input");
1251 fputc(
'\n', stdout);
1253 args.insert(
args.begin() + 1, walletPass);
1258 while (std::getline(std::cin, line)) {
1259 args.push_back(line);
1262 fputc(
'\n', stdout);
1266 std::unique_ptr<BaseRequestHandler> rh;
1271 if (!
args.empty() && (
args.at(0) ==
"h" ||
args.at(0) ==
"help")) {
1289 if (
args.size() < 1) {
1290 throw std::runtime_error(
"too few parameters (need at least command)");
1316 }
catch (
const std::exception& e) {
1317 strPrint = std::string(
"error: ") + e.what();
1318 nRet = EXIT_FAILURE;
1334 tfm::format(std::cerr,
"Error: Initializing networking failed\n");
1335 return EXIT_FAILURE;
1344 catch (
const std::exception& e) {
1346 return EXIT_FAILURE;
1349 return EXIT_FAILURE;
1356 catch (
const std::exception& e) {
bool HelpRequested(const ArgsManager &args)
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
bool CheckDataDirOption(const ArgsManager &args)
const char *const BITCOIN_CONF_FILENAME
bool IsSwitchChar(char c)
static const char DEFAULT_RPCCONNECT[]
static constexpr int8_t UNKNOWN_NETWORK
static constexpr int DEFAULT_WAIT_CLIENT_TIMEOUT
static const int CONTINUE_EXECUTION
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 constexpr std::array UNREACHABLE_NETWORK_IDS
static void http_error_cb(enum evhttp_request_error err, void *ctx)
static int CommandLineRPC(int argc, char *argv[])
static constexpr uint8_t NETINFO_MAX_LEVEL
static const int DEFAULT_HTTP_CLIENT_TIMEOUT
static void ParseGetInfoResult(UniValue &result)
ParseGetInfoResult takes in -getinfo result in UniValue object and parses it into a user friendly Uni...
static void http_request_done(struct evhttp_request *req, void *ctx)
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.
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 constexpr std::array NETWORKS
static void SetupCliArgs(ArgsManager &argsman)
static const std::string DEFAULT_COLOR_SETTING
Default -color setting.
std::optional< std::string > RpcWalletName(const ArgsManager &args)
const TranslateFn G_TRANSLATION_FUN
Translate string to current locale using Qt.
std::chrono::system_clock CliClock
static constexpr std::array NETWORK_SHORT_NAMES
static int8_t NetworkStringToId(const std::string &str)
static std::string http_errorstring(int code)
static const bool DEFAULT_NAMED
static void GetProgressBar(double progress, std::string &progress_bar)
GetProgressBar constructs a progress bar with 5% intervals.
static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args, const std::optional< std::string > &rpcwallet={})
event_set_log_callback & libevent_log_cb
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, 48334, 18445) have been chosen arbitra...
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.
bool IsArgNegated(const std::string &strArg) const
Return true if the argument was originally passed as a negated option, i.e.
@ ALLOW_ANY
disable validation
@ DISALLOW_NEGATION
disallow -nofoo syntax
ChainType GetChainType() const
Returns the appropriate chain type from the program arguments.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
bool ParseParameters(int argc, const char *const argv[], std::string &error)
void CheckMultipleCLIArgs() const
Check CLI command args.
std::string GetHelpMessage() const
Get the help string.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
fs::path GetConfigFilePath() const
Return config file path (read-only)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Process RPC generatetoaddress request.
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
UniValue ProcessReply(const UniValue &reply) override
Process netinfo requests.
bool m_outbound_only_selected
uint8_t m_block_relay_peers_count
bool DetailsRequested() const
std::vector< Peer > m_peers
UniValue ProcessReply(const UniValue &batch_in) override
static std::string ServicesList(const UniValue &services)
uint8_t m_details_level
Optional user-supplied arg to set dashboard details level.
size_t m_max_addr_rate_limited_length
size_t m_max_addr_processed_length
bool IsAddressSelected() const
std::string FormatServices(const UniValue &services)
std::string ConnectionTypeForNetinfo(const std::string &conn_type) const
bool IsVersionSelected() const
uint8_t m_manual_peers_count
const std::string m_help_doc
static constexpr int ID_PEERINFO
std::string ChainToString() const
size_t m_max_services_length
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
std::array< std::array< uint16_t, NETWORKS.size()+1 >, 3 > m_counts
Peer counts by (in/out/total, networks/total)
static constexpr int ID_NETWORKINFO
std::string PingTimeToString(double seconds) const
void push_back(UniValue val)
const std::string & get_str() const
const UniValue & find_value(std::string_view key) const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const std::string & getValStr() const
const UniValue & get_obj() const
const std::vector< UniValue > & getValues() const
void setStr(std::string str)
void pushKV(std::string key, UniValue val)
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert command lines arguments to params object when -named is disabled.
UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert command line arguments to params object when -named is enabled.
std::string FormatFullVersion()
std::string LicenseInfo()
Returns licensing information (for -version)
raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg)
raii_evhttp_connection obtain_evhttp_connection_base(struct event_base *base, std::string host, uint16_t port)
raii_event_base obtain_event_base()
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
const std::string CURRENCY_UNIT
std::string ToString(const T &t)
Locale-independent version of std::to_string.
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
static RPCHelpMan listwallets()
RPCHelpMan getnewaddress()
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in)
Parse JSON-RPC batch reply into a vector.
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue ¶ms, const UniValue &id)
JSON-RPC protocol.
UniValue JSONRPCReplyObj(UniValue result, UniValue error, std::optional< UniValue > id, JSONRPCVersion jsonrpc_version)
static const uint64_t DEFAULT_MAX_TRIES
Default max iterations to try in RPC generatetodescriptor, generatetoaddress, and generateblock.
@ HTTP_SERVICE_UNAVAILABLE
@ HTTP_INTERNAL_SERVER_ERROR
@ RPC_WALLET_NOT_SPECIFIED
No wallet specified (error when there are multiple wallets loaded)
@ RPC_IN_WARMUP
Client still warming up.
Process addrinfo requests.
UniValue ProcessReply(const UniValue &reply) override
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
Handle the conversion from a command-line to a JSON-RPC request, as well as converting back to a JSON...
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
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 getinfo requests.
const int ID_BLOCKCHAININFO
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.
Reply structure for request_done to fill in.
bool is_addr_relay_enabled
std::string transport_protocol_type
int64_t addr_rate_limited
bool operator<(const Peer &rhs) const
std::function< std::string(const char *)> TranslateFn
Translate a message to the native language of the user.
const UniValue NullUniValue
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.
std::string EncodeBase64(std::span< const unsigned char > input)
std::string ToLower(std::string_view str)
Returns the lowercase equivalent of the given string.
void UninterruptibleSleep(const std::chrono::microseconds &n)