6 #if defined(HAVE_CONFIG_H) 7 #include <config/bitcoin-config.h> 20 #include <event2/buffer.h> 21 #include <event2/keyvalq_struct.h> 41 const auto defaultBaseParams =
43 const auto testnetBaseParams =
45 const auto regtestBaseParams =
52 strprintf(
"Specify configuration file. Relative paths will be " 53 "prefixed by datadir location. (default: %s)",
56 argsman.
AddArg(
"-datadir=<dir>",
"Specify data directory",
60 "Get general information from the remote server. Note that unlike " 61 "server-side RPC calls, the results of -getinfo is the result of " 62 "multiple non-atomic requests. Some entries in the result may " 63 "represent results from different states (e.g. wallet balance may be " 64 "as of a different block from the chain state reported)",
69 strprintf(
"Pass named instead of positional arguments (default: %s)",
74 strprintf(
"Send commands to node running on <ip> (default: %s)",
78 "-rpccookiefile=<loc>",
79 "Location of the auth cookie. Relative paths will be prefixed " 80 "by a net-specific datadir location. (default: data dir)",
82 argsman.
AddArg(
"-rpcport=<port>",
83 strprintf(
"Connect to JSON-RPC on <port> (default: %u, " 84 "testnet: %u, regtest: %u)",
85 defaultBaseParams->RPCPort(),
86 testnetBaseParams->RPCPort(),
87 regtestBaseParams->RPCPort()),
90 argsman.
AddArg(
"-rpcwait",
"Wait for RPC server to start",
92 argsman.
AddArg(
"-rpcuser=<user>",
"Username for JSON-RPC connections",
94 argsman.
AddArg(
"-rpcpassword=<pw>",
"Password for JSON-RPC connections",
97 "-rpcclienttimeout=<n>",
98 strprintf(
"Timeout in seconds during HTTP requests, or 0 for " 99 "no timeout. (default: %d)",
103 argsman.
AddArg(
"-stdinrpcpass",
104 "Read RPC password from standard input as a single " 105 "line. When combined with -stdin, the first line " 106 "from standard input is used for the RPC password. When " 107 "combined with -stdinwalletpassphrase, -stdinrpcpass " 108 "consumes the first line, and -stdinwalletpassphrase " 109 "consumes the second.",
111 argsman.
AddArg(
"-stdinwalletpassphrase",
112 "Read wallet passphrase from standard input as a single " 113 "line. When combined with -stdin, the first line " 114 "from standard input is used for the wallet passphrase.",
118 "Read extra arguments from standard input, one per line until " 119 "EOF/Ctrl-D (recommended for sensitive information such as " 120 "passphrases). When combined with -stdinrpcpass, the first " 121 "line from standard input is used for the RPC password.",
124 "-rpcwallet=<walletname>",
125 "Send RPC for non-default wallet on RPC server (needs to exactly match " 126 "corresponding -wallet option passed to bitcoind). This changes the " 127 "RPC endpoint used, e.g. http://127.0.0.1:8332/wallet/<walletname>",
133 #ifndef EVENT_LOG_ERR 135 #define EVENT_LOG_ERR _EVENT_LOG_ERR 139 throw std::runtime_error(
strprintf(
"libevent error: %s", msg));
155 :
std::runtime_error(msg) {}
169 tfm::format(std::cerr,
"Error parsing command line arguments: %s\n",
174 std::string strUsage =
178 "Usage: bitcoin-cli [options] <command> [params] " 179 "Send command to " PACKAGE_NAME
"\n" 180 "or: bitcoin-cli [options] -named <command> " 181 "[name=value]... Send command to " PACKAGE_NAME
182 " (with named arguments)\n" 183 "or: bitcoin-cli [options] help " 185 "or: bitcoin-cli [options] help <command> Get " 186 "help for a command\n";
193 tfm::format(std::cerr,
"Error: too few parameters\n");
200 "Error: Specified data directory \"%s\" does not exist.\n",
205 tfm::format(std::cerr,
"Error reading configuration file: %s\n", error);
212 }
catch (
const std::exception &e) {
230 #if LIBEVENT_VERSION_NUMBER >= 0x02010300 231 case EVREQ_HTTP_TIMEOUT:
232 return "timeout reached";
234 return "EOF reached";
235 case EVREQ_HTTP_INVALID_HEADER:
236 return "error while reading header, or invalid header";
237 case EVREQ_HTTP_BUFFER_ERROR:
238 return "error encountered while reading or writing";
239 case EVREQ_HTTP_REQUEST_CANCEL:
240 return "request was canceled";
241 case EVREQ_HTTP_DATA_TOO_LONG:
242 return "response body is larger than allowed";
252 if (req ==
nullptr) {
261 reply->
status = evhttp_request_get_response_code(req);
263 struct evbuffer *buf = evhttp_request_get_input_buffer(req);
265 size_t size = evbuffer_get_length(buf);
266 const char *data = (
const char *)evbuffer_pullup(buf, size);
268 reply->
body = std::string(data, size);
270 evbuffer_drain(buf, size);
274 #if LIBEVENT_VERSION_NUMBER >= 0x02010300 275 static void http_error_cb(
enum evhttp_request_error err,
void *
ctx) {
288 virtual UniValue PrepareRequest(
const std::string &method,
289 const std::vector<std::string> &args) = 0;
296 const int ID_NETWORKINFO = 0;
297 const int ID_BLOCKCHAININFO = 1;
298 const int ID_WALLETINFO = 2;
299 const int ID_BALANCES = 3;
303 const std::vector<std::string> &args)
override {
305 throw std::runtime_error(
"-getinfo takes no arguments");
322 std::vector<UniValue> batch =
327 if (!batch[ID_NETWORKINFO][
"error"].isNull()) {
328 return batch[ID_NETWORKINFO];
330 if (!batch[ID_BLOCKCHAININFO][
"error"].isNull()) {
331 return batch[ID_BLOCKCHAININFO];
333 result.
pushKV(
"version", batch[ID_NETWORKINFO][
"result"][
"version"]);
334 result.
pushKV(
"blocks", batch[ID_BLOCKCHAININFO][
"result"][
"blocks"]);
335 result.
pushKV(
"headers", batch[ID_BLOCKCHAININFO][
"result"][
"headers"]);
337 "verificationprogress",
338 batch[ID_BLOCKCHAININFO][
"result"][
"verificationprogress"]);
339 result.
pushKV(
"timeoffset",
340 batch[ID_NETWORKINFO][
"result"][
"timeoffset"]);
341 result.
pushKV(
"connections",
342 batch[ID_NETWORKINFO][
"result"][
"connections"]);
344 batch[ID_NETWORKINFO][
"result"][
"networks"][0][
"proxy"]);
345 result.
pushKV(
"difficulty",
346 batch[ID_BLOCKCHAININFO][
"result"][
"difficulty"]);
348 UniValue(batch[ID_BLOCKCHAININFO][
"result"][
"chain"]));
349 if (!batch[ID_WALLETINFO][
"result"].isNull()) {
350 result.
pushKV(
"keypoolsize",
351 batch[ID_WALLETINFO][
"result"][
"keypoolsize"]);
352 if (!batch[ID_WALLETINFO][
"result"][
"unlocked_until"].isNull()) {
353 result.
pushKV(
"unlocked_until",
354 batch[ID_WALLETINFO][
"result"][
"unlocked_until"]);
357 batch[ID_WALLETINFO][
"result"][
"paytxfee"]);
359 if (!batch[ID_BALANCES][
"result"].isNull()) {
361 batch[ID_BALANCES][
"result"][
"mine"][
"trusted"]);
363 result.
pushKV(
"relayfee", batch[ID_NETWORKINFO][
"result"][
"relayfee"]);
364 result.
pushKV(
"warnings", batch[ID_NETWORKINFO][
"result"][
"warnings"]);
373 const std::vector<std::string> &args)
override {
389 const std::vector<std::string> &args) {
403 raii_evhttp_connection evcon =
411 evhttp_connection_set_timeout(evcon.get(), timeout);
417 constexpr
int YEAR_IN_SECONDS = 31556952;
418 evhttp_connection_set_timeout(evcon.get(), 5 * YEAR_IN_SECONDS);
423 raii_evhttp_request req =
425 if (req ==
nullptr) {
426 throw std::runtime_error(
"create http request failed");
428 #if LIBEVENT_VERSION_NUMBER >= 0x02010300 429 evhttp_request_set_error_cb(req.get(), http_error_cb);
434 bool failedToGetAuthCookie =
false;
439 failedToGetAuthCookie =
true;
442 strRPCUserColonPass =
gArgs.
GetArg(
"-rpcuser",
"") +
":" +
446 struct evkeyvalq *output_headers =
447 evhttp_request_get_output_headers(req.get());
448 assert(output_headers);
449 evhttp_add_header(output_headers,
"Host", host.c_str());
450 evhttp_add_header(output_headers,
"Connection",
"close");
452 output_headers,
"Authorization",
453 (std::string(
"Basic ") +
EncodeBase64(strRPCUserColonPass)).c_str());
457 struct evbuffer *output_buffer =
458 evhttp_request_get_output_buffer(req.get());
459 assert(output_buffer);
460 evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
463 std::string endpoint =
"/";
465 std::string walletName =
gArgs.
GetArg(
"-rpcwallet",
"");
467 evhttp_uriencode(walletName.data(), walletName.size(),
false);
469 endpoint =
"/wallet/" + std::string(encodedURI);
475 int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST,
483 event_base_dispatch(base.get());
485 if (response.status == 0) {
486 std::string responseErrorMessage;
487 if (response.error != -1) {
488 responseErrorMessage =
489 strprintf(
" (error code %d - \"%s\")", response.error,
493 strprintf(
"Could not connect to the server %s:%d%s\n\nMake sure " 494 "the bitcoind server is running and that you are " 495 "connecting to the correct RPC port.",
496 host, port, responseErrorMessage));
498 if (failedToGetAuthCookie) {
500 "Could not locate RPC credentials. No authentication cookie " 501 "could be found, and RPC password is not set. See " 502 "-rpcpassword and -stdinrpcpass. Configuration file: (%s)",
506 throw std::runtime_error(
507 "Authorization failed: Incorrect rpcuser or rpcpassword");
512 throw std::runtime_error(
513 strprintf(
"server returned HTTP error %d", response.status));
514 }
else if (response.body.empty()) {
515 throw std::runtime_error(
"no response from server");
520 if (!valReply.
read(response.body)) {
521 throw std::runtime_error(
"couldn't parse reply from server");
525 throw std::runtime_error(
526 "expected reply to have result, error and id properties");
533 std::string strPrint;
545 fputs(
"RPC password> ", stderr);
548 if (!std::getline(std::cin, rpcPass)) {
549 throw std::runtime_error(
"-stdinrpcpass specified but failed " 550 "to read from standard input");
557 std::vector<std::string> args =
558 std::vector<std::string>(&argv[1], &argv[argc]);
561 std::string walletPass;
562 if (args.size() < 1 ||
563 args[0].substr(0, 16) !=
"walletpassphrase") {
564 throw std::runtime_error(
565 "-stdinwalletpassphrase is only applicable for " 566 "walletpassphrase(change)");
569 fputs(
"Wallet passphrase> ", stderr);
572 if (!std::getline(std::cin, walletPass)) {
573 throw std::runtime_error(
"-stdinwalletpassphrase specified but " 574 "failed to read from standard input");
579 args.insert(args.begin() + 1, walletPass);
584 while (std::getline(std::cin, line)) {
585 args.push_back(line);
591 std::unique_ptr<BaseRequestHandler> rh;
598 if (args.size() < 1) {
599 throw std::runtime_error(
600 "too few parameters (need at least command)");
604 args.erase(args.begin());
619 int code = error[
"code"].
get_int();
623 strPrint =
"error: " + error.
write();
631 :
"error code: " + errCode.
getValStr() +
"\n";
633 if (errMsg.
isStr()) {
634 strPrint +=
"error message:\n" + errMsg.
get_str();
637 if (errCode.
isNum() &&
639 strPrint +=
"\nTry adding " 640 "\"-rpcwallet=<filename>\" option to " 641 "bitcoin-cli command line.";
646 if (result.isNull()) {
648 }
else if (result.isStr()) {
649 strPrint = result.get_str();
651 strPrint = result.write(2);
664 }
catch (
const std::exception &e) {
665 strPrint = std::string(
"error: ") + e.what();
672 if (strPrint !=
"") {
673 tfm::format(nRet == 0 ? std::cout : std::cerr,
"%s\n", strPrint);
678 int main(
int argc,
char *argv[]) {
680 util::WinCmdLineArgs winArgs;
681 std::tie(argc, argv) = winArgs.get();
685 tfm::format(std::cerr,
"Error: Initializing networking failed\n");
695 }
catch (
const std::exception &e) {
703 int ret = EXIT_FAILURE;
706 }
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)
std::unique_ptr< CBaseChainParams > CreateBaseChainParams(const std::string &chain)
Creates and returns a std::unique_ptr<CBaseChainParams> of the chosen chain.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
static int CommandLineRPC(int argc, char *argv[])
raii_event_base obtain_event_base()
void SetupChainParamsBaseOptions(ArgsManager &argsman)
Set the arguments for chainparams.
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in, size_t num)
Parse JSON-RPC batch reply into a vector.
static int AppInitRPC(int argc, char *argv[])
static void libevent_log_cb(int severity, const char *msg)
libevent event log callback
static const std::string REGTEST
bool read(const char *raw, size_t len)
static std::string strRPCUserColonPass
UniValue ProcessReply(const UniValue &reply) override
virtual ~BaseRequestHandler()
static const int DEFAULT_HTTP_CLIENT_TIMEOUT
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
std::string EncodeBase64(const uint8_t *pch, size_t len)
const std::string & get_str() const
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)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
const char *const BITCOIN_CONF_FILENAME
const std::string & getValStr() const
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)
std::string GetHelpMessage() const
Get the help string.
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
bool CheckDataDirOption()
static const char DEFAULT_RPCCONNECT[]
bool push_back(const UniValue &val)
static const char * http_errorstring(int code)
static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args)
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
bool HelpRequested(const ArgsManager &args)
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)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool pushKV(const std::string &key, const UniValue &val)
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
int main(int argc, char *argv[])
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 void SetupCliArgs(ArgsManager &argsman)
CConnectionFailed(const std::string &msg)
void UninterruptibleSleep(const std::chrono::microseconds &n)
fs::path GetConfigFile(const std::string &confPath)
const UniValue & get_obj() const
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
const std::function< std::string(const char *)> G_TRANSLATION_FUN
Translate string to current locale using Qt.
Process default single requests.
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.
const UniValue NullUniValue
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
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
bool IsSwitchChar(char c)
UniValue PrepareRequest(const std::string &method, const std::vector< std::string > &args) override
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
void SelectBaseParams(const std::string &chain)
Sets the params returned by Params() to those for the given network.
Process getinfo requests.
bool error(const char *fmt, const Args &... args)
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
static void http_request_done(struct evhttp_request *req, void *ctx)
Reply structure for request_done to fill in.
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)