mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
210 lines
7.5 KiB
C++
210 lines
7.5 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include "callrpc.h"
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include "config/bitcoin-config.h"
|
|
#endif
|
|
|
|
#include "chainparamsbase.h"
|
|
#include "clientversion.h"
|
|
#include "rpc/client.h"
|
|
#include "rpc/protocol.h"
|
|
#include "util.h"
|
|
#include "utilstrencodings.h"
|
|
|
|
#include <boost/filesystem/operations.hpp>
|
|
#include <stdio.h>
|
|
#include <univalue.h>
|
|
|
|
using namespace std;
|
|
|
|
std::string HelpMessageCli()
|
|
{
|
|
const boost::scoped_ptr<CBaseChainParams> defaultBaseParams(CBaseChainParams::Factory(CBaseChainParams::MAIN));
|
|
string strUsage;
|
|
strUsage += HelpMessageGroup(_("Options:"));
|
|
strUsage += HelpMessageOpt("-?", _("This help message"));
|
|
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
|
|
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
|
|
AppendParamsHelpMessages(strUsage);
|
|
strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCHOST));
|
|
strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u)"), defaultBaseParams->RPCPort()));
|
|
strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
|
|
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
|
|
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
|
|
strUsage += HelpMessageOpt("-rpcclienttimeout=<n>", strprintf(_("Timeout during HTTP requests (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT));
|
|
strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)"));
|
|
|
|
return strUsage;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Start
|
|
//
|
|
|
|
static bool AppInitRPC(int argc, char* argv[])
|
|
{
|
|
//
|
|
// Parameters
|
|
//
|
|
ParseParameters(argc, argv);
|
|
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
|
|
std::string strUsage = strprintf(_("%s RPC client version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n";
|
|
if (!mapArgs.count("-version")) {
|
|
strUsage += "\n" + _("Usage:") + "\n" +
|
|
" bitcoin-cli [options] <command> [params] " + strprintf(_("Send command to %s"), _(PACKAGE_NAME)) + "\n" +
|
|
" bitcoin-cli [options] help " + _("List commands") + "\n" +
|
|
" bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
|
|
|
|
strUsage += "\n" + HelpMessageCli();
|
|
}
|
|
|
|
fprintf(stdout, "%s", strUsage.c_str());
|
|
return false;
|
|
}
|
|
if (!boost::filesystem::is_directory(GetDataDir(false))) {
|
|
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
|
|
return false;
|
|
}
|
|
try {
|
|
ReadConfigFile(mapArgs, mapMultiArgs);
|
|
} catch (const std::exception& e) {
|
|
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
|
return false;
|
|
}
|
|
// Check for -chain, -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
|
|
try {
|
|
SelectBaseParams(ChainNameFromCommandLine());
|
|
} catch (const std::exception& e) {
|
|
fprintf(stderr, "Error: %s\n", e.what());
|
|
return false;
|
|
}
|
|
if (GetBoolArg("-rpcssl", false))
|
|
{
|
|
fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int CommandLineRPC(int argc, char *argv[])
|
|
{
|
|
string strPrint;
|
|
int nRet = 0;
|
|
try {
|
|
// Skip switches
|
|
while (argc > 1 && IsSwitchChar(argv[1][0])) {
|
|
argc--;
|
|
argv++;
|
|
}
|
|
std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
|
|
if (GetBoolArg("-stdin", false)) {
|
|
// Read one arg per line from stdin and append
|
|
std::string line;
|
|
while (std::getline(std::cin,line))
|
|
args.push_back(line);
|
|
}
|
|
if (args.size() < 1)
|
|
throw runtime_error("too few parameters (need at least command)");
|
|
std::string strMethod = args[0];
|
|
UniValue params = RPCConvertValues(strMethod, std::vector<std::string>(args.begin()+1, args.end()));
|
|
|
|
// Execute and handle connection failures with -rpcwait
|
|
const bool fWait = GetBoolArg("-rpcwait", false);
|
|
do {
|
|
try {
|
|
const UniValue reply = CallRPC(strMethod, params);
|
|
|
|
// Parse reply
|
|
const UniValue& result = find_value(reply, "result");
|
|
const UniValue& error = find_value(reply, "error");
|
|
|
|
if (!error.isNull()) {
|
|
// Error
|
|
int code = error["code"].get_int();
|
|
if (fWait && code == RPC_IN_WARMUP)
|
|
throw CConnectionFailed("server in warmup");
|
|
strPrint = "error: " + error.write();
|
|
nRet = abs(code);
|
|
if (error.isObject())
|
|
{
|
|
UniValue errCode = find_value(error, "code");
|
|
UniValue errMsg = find_value(error, "message");
|
|
strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n";
|
|
|
|
if (errMsg.isStr())
|
|
strPrint += "error message:\n"+errMsg.get_str();
|
|
}
|
|
} else {
|
|
// Result
|
|
if (result.isNull())
|
|
strPrint = "";
|
|
else if (result.isStr())
|
|
strPrint = result.get_str();
|
|
else
|
|
strPrint = result.write(2);
|
|
}
|
|
// Connection succeeded, no need to retry.
|
|
break;
|
|
}
|
|
catch (const CConnectionFailed&) {
|
|
if (fWait)
|
|
MilliSleep(1000);
|
|
else
|
|
throw;
|
|
}
|
|
} while (fWait);
|
|
}
|
|
catch (const boost::thread_interrupted&) {
|
|
throw;
|
|
}
|
|
catch (const std::exception& e) {
|
|
strPrint = string("error: ") + e.what();
|
|
nRet = EXIT_FAILURE;
|
|
}
|
|
catch (...) {
|
|
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
|
throw;
|
|
}
|
|
|
|
if (strPrint != "") {
|
|
fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
SetupEnvironment();
|
|
if (!SetupNetworking()) {
|
|
fprintf(stderr, "Error: Initializing networking failed\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
try {
|
|
if(!AppInitRPC(argc, argv))
|
|
return EXIT_FAILURE;
|
|
}
|
|
catch (const std::exception& e) {
|
|
PrintExceptionContinue(&e, "AppInitRPC()");
|
|
return EXIT_FAILURE;
|
|
} catch (...) {
|
|
PrintExceptionContinue(NULL, "AppInitRPC()");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
int ret = EXIT_FAILURE;
|
|
try {
|
|
ret = CommandLineRPC(argc, argv);
|
|
}
|
|
catch (const std::exception& e) {
|
|
PrintExceptionContinue(&e, "CommandLineRPC()");
|
|
} catch (...) {
|
|
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
|
}
|
|
return ret;
|
|
}
|