6 #if defined(HAVE_CONFIG_H)
30 #include <event2/buffer.h>
31 #include <event2/keyvalq_struct.h>
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);
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);
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);
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
87 throw std::runtime_error(
strprintf(
"libevent error: %s", msg));
100 std::runtime_error(msg)
114 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n", error);
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";
130 tfm::format(std::cerr,
"Error: too few parameters\n");
136 tfm::format(std::cerr,
"Error: Specified data directory \"%s\" does not exist.\n",
gArgs.
GetArg(
"-datadir",
""));
140 tfm::format(std::cerr,
"Error reading configuration file: %s\n", error);
146 }
catch (
const std::exception& e) {
167 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
168 case EVREQ_HTTP_TIMEOUT:
169 return "timeout reached";
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";
190 if (req ==
nullptr) {
198 reply->
status = evhttp_request_get_response_code(req);
200 struct evbuffer *buf = evhttp_request_get_input_buffer(req);
203 size_t size = evbuffer_get_length(buf);
204 const char *data = (
const char*)evbuffer_pullup(buf, size);
206 reply->
body = std::string(data, size);
207 evbuffer_drain(buf, size);
211 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
212 static void http_error_cb(
enum evhttp_request_error err,
void *
ctx)
243 throw std::runtime_error(
"-getinfo takes no arguments");
260 if (!batch[ID_NETWORKINFO][
"error"].isNull()) {
263 if (!batch[ID_BLOCKCHAININFO][
"error"].isNull()) {
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"]);
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);
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"]);
286 result.
pushKV(
"paytxfee", batch[ID_WALLETINFO][
"result"][
"paytxfee"]);
288 if (!batch[ID_BALANCES][
"result"].isNull()) {
289 result.
pushKV(
"balance", batch[ID_BALANCES][
"result"][
"mine"][
"trusted"]);
291 result.
pushKV(
"relayfee", batch[ID_NETWORKINFO][
"result"][
"relayfee"]);
292 result.
pushKV(
"warnings", batch[ID_NETWORKINFO][
"result"][
"warnings"]);
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{{{}}};
348 if (seconds < 0)
return "";
349 const double milliseconds{round(1000 * seconds)};
350 return milliseconds > 999999 ?
"-" :
ToString(milliseconds);
375 if (!batch[ID_PEERINFO][
"error"].isNull())
return batch[
ID_PEERINFO];
376 if (!batch[ID_NETWORKINFO][
"error"].isNull())
return batch[
ID_NETWORKINFO];
379 if (networkinfo[
"version"].get_int() < 209900) {
380 throw std::runtime_error(
"-netinfo requires bitcoind server to be running v0.21.0 and up");
384 for (
const UniValue& peer : batch[ID_PEERINFO][
"result"].getValues()) {
385 const std::string network{peer[
"network"].get_str()};
388 const bool is_outbound{!peer[
"inbound"].get_bool()};
389 const bool is_block_relay{!peer[
"relaytxes"].get_bool()};
390 ++
m_counts.at(is_outbound).at(network_id);
394 if (is_block_relay) {
400 const int peer_id{peer[
"id"].get_int()};
401 const int mapped_as{peer[
"mapped_as"].isNull() ? 0 : peer[
"mapped_as"].get_int()};
402 const int version{peer[
"version"].get_int()};
403 const int64_t conn_time{peer[
"conntime"].get_int64()};
404 const int64_t last_blck{peer[
"last_block"].get_int64()};
405 const int64_t last_recv{peer[
"lastrecv"].get_int64()};
406 const int64_t last_send{peer[
"lastsend"].get_int64()};
407 const int64_t last_trxn{peer[
"last_transaction"].get_int64()};
408 const double min_ping{peer[
"minping"].isNull() ? -1 : peer[
"minping"].get_real()};
409 const double ping{peer[
"pingtime"].isNull() ? -1 : peer[
"pingtime"].get_real()};
410 const std::string addr{peer[
"addr"].get_str()};
412 const std::string sub_version{peer[
"subver"].get_str()};
413 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});
426 std::sort(m_peers.begin(), m_peers.end());
427 result +=
strprintf(
"Peer connections sorted by direction and min ping\n<-> relay net mping ping send recv txn blk %*s ",
m_max_age_length,
"age");
430 for (
const Peer& peer : m_peers) {
431 std::string version{
ToString(peer.version) + peer.sub_version};
433 "%3s %5s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s\n",
434 peer.is_outbound ?
"out" :
"in",
435 peer.is_block_relay ?
"block" :
"full",
457 result +=
" ipv4 ipv6 onion total block-relay\n";
458 const std::array<std::string, 3> rows{{
"in",
"out",
"total"}};
464 result +=
"\nLocal addresses";
465 const std::vector<UniValue>& local_addrs{networkinfo[
"localaddresses"].getValues()};
466 if (local_addrs.empty()) {
469 size_t max_addr_size{0};
470 for (
const UniValue& addr : local_addrs) {
471 max_addr_size = std::max(addr[
"address"].get_str().length() + 1, max_addr_size);
473 for (
const UniValue& addr : local_addrs) {
474 result +=
strprintf(
"\n%-*s port %6i score %6i", max_addr_size, addr[
"address"].get_str(), addr[
"port"].get_int(), addr[
"score"].get_int());
545 evhttp_connection_set_timeout(evcon.get(), timeout);
550 constexpr
int YEAR_IN_SECONDS = 31556952;
551 evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
558 throw std::runtime_error(
"create http request failed");
559 #if LIBEVENT_VERSION_NUMBER >= 0x02010300
560 evhttp_request_set_error_cb(req.get(), http_error_cb);
565 bool failedToGetAuthCookie =
false;
569 failedToGetAuthCookie =
true;
575 struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get());
576 assert(output_headers);
577 evhttp_add_header(output_headers,
"Host", host.c_str());
578 evhttp_add_header(output_headers,
"Connection",
"close");
579 evhttp_add_header(output_headers,
"Content-Type",
"application/json");
580 evhttp_add_header(output_headers,
"Authorization", (std::string(
"Basic ") +
EncodeBase64(strRPCUserColonPass)).c_str());
584 struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get());
585 assert(output_buffer);
586 evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
589 std::string endpoint =
"/";
591 char* encodedURI = evhttp_uriencode(rpcwallet->data(), rpcwallet->size(),
false);
593 endpoint =
"/wallet/" + std::string(encodedURI);
599 int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, endpoint.c_str());
605 event_base_dispatch(base.get());
607 if (response.
status == 0) {
608 std::string responseErrorMessage;
609 if (response.
error != -1) {
612 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));
614 if (failedToGetAuthCookie) {
616 "Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
619 throw std::runtime_error(
"Authorization failed: Incorrect rpcuser or rpcpassword");
622 throw std::runtime_error(
strprintf(
"server returned HTTP error %d", response.
status));
623 else if (response.
body.empty())
624 throw std::runtime_error(
"no response from server");
628 if (!valReply.read(response.
body))
629 throw std::runtime_error(
"couldn't parse reply from server");
632 throw std::runtime_error(
"expected reply to have result, error and id properties");
653 response =
CallRPC(rh, strMethod, args, rpcwallet);
675 if (result.
isNull())
return;
686 strPrint =
"error code: " + err_code.
getValStr() +
"\n";
688 if (err_msg.
isStr()) {
689 strPrint += (
"error message:\n" + err_msg.
get_str());
692 strPrint +=
"\nTry adding \"-rpcwallet=<filename>\" option to bitcoin-cli command line.";
695 strPrint =
"error: " + error.
write();
697 nRet = abs(error[
"code"].get_int());
710 if (!
find_value(listwallets,
"error").isNull())
return;
712 if (wallets.
size() <= 1)
return;
716 const std::string wallet_name = wallet.get_str();
719 balances.
pushKV(wallet_name, balance);
721 result.
pushKV(
"balances", balances);
743 if (args.size() > 2)
throw std::runtime_error(
"too many arguments (maximum 2 for nblocks and maxtries)");
744 if (args.size() == 0) {
746 }
else if (args.at(0) ==
"0") {
747 throw std::runtime_error(
"the first argument (number of blocks to generate, default: " +
DEFAULT_NBLOCKS +
") must be an integer value greater than zero");
749 args.emplace(args.begin() + 1, address);
754 std::string strPrint;
766 fputs(
"RPC password> ", stderr);
769 if (!std::getline(std::cin, rpcPass)) {
770 throw std::runtime_error(
"-stdinrpcpass specified but failed to read from standard input");
777 std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
780 std::string walletPass;
781 if (args.size() < 1 || args[0].substr(0, 16) !=
"walletpassphrase") {
782 throw std::runtime_error(
"-stdinwalletpassphrase is only applicable for walletpassphrase(change)");
785 fputs(
"Wallet passphrase> ", stderr);
788 if (!std::getline(std::cin, walletPass)) {
789 throw std::runtime_error(
"-stdinwalletpassphrase specified but failed to read from standard input");
794 args.insert(args.begin() + 1, walletPass);
799 while (std::getline(std::cin, line)) {
800 args.push_back(line);
806 std::unique_ptr<BaseRequestHandler> rh;
823 if (args.size() < 1) {
824 throw std::runtime_error(
"too few parameters (need at least command)");
827 args.erase(args.begin());
847 }
catch (
const std::exception& e) {
848 strPrint = std::string(
"error: ") + e.what();
855 if (strPrint !=
"") {
856 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
867 __declspec(dllexport) int
main(
int argc,
char* argv[])
869 util::WinCmdLineArgs winArgs;
870 std::tie(argc, argv) = winArgs.get();
872 int main(
int argc,
char* argv[])
877 tfm::format(std::cerr,
"Error: Initializing networking failed\n");
887 catch (
const std::exception& e) {
895 int ret = EXIT_FAILURE;
899 catch (
const std::exception& e) {
NODISCARD bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
No wallet specified (error when there are multiple wallets loaded)
static const std::string DEFAULT_NBLOCKS
Default number of blocks to generate for RPC generatetoaddress.
const std::string & get_str() const
std::unique_ptr< CBaseChainParams > CreateBaseChainParams(const std::string &chain)
Port numbers for incoming Tor connections (8334, 18334, 38334, 18445) have been chosen arbitrarily to...
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()
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
static int AppInitRPC(int argc, char *argv[])
std::string PingTimeToString(double seconds) const
static void libevent_log_cb(int severity, const char *msg)
libevent event log callback
static const std::string REGTEST
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
static std::string strRPCUserColonPass
static constexpr int ID_NETWORKINFO
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={})
const std::vector< UniValue > & getValues() const
virtual ~BaseRequestHandler()
static const int DEFAULT_HTTP_CLIENT_TIMEOUT
static constexpr int ID_PEERINFO
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
static RPCHelpMan listwallets()
raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg)
NODISCARD bool ParseParameters(int argc, const char *const argv[], std::string &error)
std::vector< Peer > m_peers
static std::string http_errorstring(int code)
uint8_t m_details_level
Optional user-supplied arg to set dashboard details level.
const int ID_BLOCKCHAININFO
void ForceSetArg(const std::string &strArg, const std::string &strValue)
bool IsVersionSelected() const
const char *const BITCOIN_CONF_FILENAME
int64_t GetSystemTimeInSeconds()
Returns the system time (not mockable)
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)
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.
bool CheckDataDirOption()
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in)
Parse JSON-RPC batch reply into a vector.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
std::string EncodeBase64(Span< const unsigned char > input)
bool error(const char *fmt, const Args &...args)
static const char DEFAULT_RPCCONNECT[]
bool push_back(const UniValue &val)
std::array< std::array< uint16_t, m_networks_size+2 >, 3 > m_counts
Peer counts by (in/out/total, networks/total/block-relay)
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
Process netinfo requests.
static RPCHelpMan getbalances()
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
bool HelpRequested(const ArgsManager &args)
static const uint64_t DEFAULT_MAX_TRIES
Default max iterations to try in RPC generatetodescriptor, generatetoaddress, and generateblock...
static const int CONTINUE_EXECUTION
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)
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)
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
int main(int argc, char *argv[])
bool DetailsRequested() const
UniValue ProcessReply(const UniValue &batch_in) override
Collect values from the batch and form a simulated getinfo reply.
Class that handles the conversion from a command-line to a JSON-RPC request, as well as converting ba...
std::string FormatFullVersion()
static constexpr int8_t UNKNOWN_NETWORK
static void SetupCliArgs(ArgsManager &argsman)
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)
bool IsAddressSelected() const
const std::string & getValStr() const
void UninterruptibleSleep(const std::chrono::microseconds &n)
fs::path GetConfigFile(const std::string &confPath)
const std::array< std::string, m_networks_size > m_networks
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Process RPC generatetoaddress request.
std::string GetHelpMessage() const
Get the help string.
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Process default single requests.
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue ¶ms, const UniValue &id)
JSON-RPC protocol.
void SetupHelpOptions(ArgsManager &args)
Add help options to the args manager.
static RPCHelpMan getnewaddress()
const UniValue NullUniValue
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
bool operator<(const Peer &rhs) const
UrlDecodeFn *const URL_DECODE
int8_t NetworkStringToId(const std::string &str) const
std::string ChainToString() const
UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert named arguments to command-specific RPC representation.
static const std::string TESTNET
static const bool DEFAULT_NAMED
static UniValue GetNewAddress()
Call RPC getnewaddress.
std::string GetChainName() const
Returns the appropriate chain name from the program arguments.
bool IsSwitchChar(char c)
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.
boost::optional< T > Optional
Substitute for C++17 std::optional.
static constexpr uint8_t m_networks_size
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.
const UniValue & get_obj() const
Process getinfo requests.
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
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.
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
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)