2013-10-11 23:09:59 +02:00
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
|
|
|
// Copyright (c) 2009-2013 The Bitcoin developers
|
|
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
2014-12-06 14:37:48 -08:00
|
|
|
#include "callrpc.h"
|
2014-09-14 12:43:56 +02:00
|
|
|
#include "chainparamsbase.h"
|
2014-10-28 21:33:23 -04:00
|
|
|
#include "clientversion.h"
|
2014-09-14 12:43:56 +02:00
|
|
|
#include "util.h"
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
#include "utilstrencodings.h"
|
2013-10-11 23:09:59 +02:00
|
|
|
|
2013-04-13 00:13:08 -05:00
|
|
|
#include <boost/filesystem/operations.hpp>
|
|
|
|
|
|
2014-07-03 07:45:16 +02:00
|
|
|
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
|
|
|
|
|
|
2014-06-16 16:30:38 +02:00
|
|
|
using namespace std;
|
2014-05-26 11:38:44 +02:00
|
|
|
using namespace boost;
|
|
|
|
|
using namespace boost::asio;
|
|
|
|
|
using namespace json_spirit;
|
|
|
|
|
|
|
|
|
|
std::string HelpMessageCli()
|
|
|
|
|
{
|
|
|
|
|
string strUsage;
|
|
|
|
|
strUsage += _("Options:") + "\n";
|
|
|
|
|
strUsage += " -? " + _("This help message") + "\n";
|
2014-10-10 21:59:04 +00:00
|
|
|
strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n";
|
2014-05-26 11:38:44 +02:00
|
|
|
strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
|
|
|
|
|
strUsage += " -testnet " + _("Use the test network") + "\n";
|
|
|
|
|
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
|
|
|
|
|
"solved instantly. This is intended for regression testing tools and app development.") + "\n";
|
2014-10-10 21:59:04 +00:00
|
|
|
strUsage += " -rpcconnect=<ip> " + strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1") + "\n";
|
|
|
|
|
strUsage += " -rpcport=<port> " + strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n";
|
2014-05-26 11:38:44 +02:00
|
|
|
strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n";
|
|
|
|
|
strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
|
|
|
|
|
strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
|
|
|
|
|
|
|
|
|
|
strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
|
|
|
|
|
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
|
|
|
|
|
|
|
|
|
|
return strUsage;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-11 23:09:59 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// Start
|
|
|
|
|
//
|
2014-10-29 18:08:31 +01:00
|
|
|
|
2013-10-11 23:09:59 +02:00
|
|
|
static bool AppInitRPC(int argc, char* argv[])
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// Parameters
|
|
|
|
|
//
|
|
|
|
|
ParseParameters(argc, argv);
|
2014-11-22 19:56:25 +01:00
|
|
|
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) {
|
|
|
|
|
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
|
|
|
|
|
if (!mapArgs.count("-version")) {
|
|
|
|
|
strUsage += "\n" + _("Usage:") + "\n" +
|
|
|
|
|
" bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\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;
|
|
|
|
|
}
|
2014-06-25 21:09:36 -04:00
|
|
|
if (!boost::filesystem::is_directory(GetDataDir(false))) {
|
2013-10-11 23:09:59 +02:00
|
|
|
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-04-07 10:10:01 +02:00
|
|
|
try {
|
|
|
|
|
ReadConfigFile(mapArgs, mapMultiArgs);
|
|
|
|
|
} catch(std::exception &e) {
|
|
|
|
|
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-06-19 15:10:04 +02:00
|
|
|
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
|
|
|
|
|
if (!SelectBaseParamsFromCommandLine()) {
|
2013-11-28 17:28:27 +01:00
|
|
|
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2013-10-11 23:09:59 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-26 11:38:44 +02:00
|
|
|
int CommandLineRPC(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
string strPrint;
|
|
|
|
|
int nRet = 0;
|
2014-06-25 21:09:36 -04:00
|
|
|
try {
|
2014-05-26 11:38:44 +02:00
|
|
|
// Skip switches
|
2014-06-25 21:09:36 -04:00
|
|
|
while (argc > 1 && IsSwitchChar(argv[1][0])) {
|
2014-05-26 11:38:44 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Method
|
|
|
|
|
if (argc < 2)
|
|
|
|
|
throw runtime_error("too few parameters");
|
|
|
|
|
string strMethod = argv[1];
|
|
|
|
|
|
|
|
|
|
// Parameters default to strings
|
|
|
|
|
std::vector<std::string> strParams(&argv[2], &argv[argc]);
|
|
|
|
|
Array params = RPCConvertValues(strMethod, strParams);
|
|
|
|
|
|
2014-10-29 18:08:31 +01:00
|
|
|
// Execute and handle connection failures with -rpcwait
|
|
|
|
|
const bool fWait = GetBoolArg("-rpcwait", false);
|
|
|
|
|
do {
|
|
|
|
|
try {
|
|
|
|
|
const Object reply = CallRPC(strMethod, params);
|
|
|
|
|
|
|
|
|
|
// Parse reply
|
|
|
|
|
const Value& result = find_value(reply, "result");
|
|
|
|
|
const Value& error = find_value(reply, "error");
|
|
|
|
|
|
|
|
|
|
if (error.type() != null_type) {
|
|
|
|
|
// Error
|
|
|
|
|
const int code = find_value(error.get_obj(), "code").get_int();
|
|
|
|
|
if (fWait && code == RPC_IN_WARMUP)
|
|
|
|
|
throw CConnectionFailed("server in warmup");
|
|
|
|
|
strPrint = "error: " + write_string(error, false);
|
|
|
|
|
nRet = abs(code);
|
|
|
|
|
} else {
|
|
|
|
|
// Result
|
|
|
|
|
if (result.type() == null_type)
|
|
|
|
|
strPrint = "";
|
|
|
|
|
else if (result.type() == str_type)
|
|
|
|
|
strPrint = result.get_str();
|
|
|
|
|
else
|
|
|
|
|
strPrint = write_string(result, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Connection succeeded, no need to retry.
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
catch (const CConnectionFailed& e) {
|
|
|
|
|
if (fWait)
|
|
|
|
|
MilliSleep(1000);
|
|
|
|
|
else
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
} while (fWait);
|
2014-05-26 11:38:44 +02:00
|
|
|
}
|
|
|
|
|
catch (boost::thread_interrupted) {
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
catch (std::exception& e) {
|
|
|
|
|
strPrint = string("error: ") + e.what();
|
|
|
|
|
nRet = EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
catch (...) {
|
|
|
|
|
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-25 21:09:36 -04:00
|
|
|
if (strPrint != "") {
|
2014-05-26 11:38:44 +02:00
|
|
|
fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
|
|
|
|
|
}
|
|
|
|
|
return nRet;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-11 23:09:59 +02:00
|
|
|
int main(int argc, char* argv[])
|
|
|
|
|
{
|
2014-05-13 10:15:00 +00:00
|
|
|
SetupEnvironment();
|
|
|
|
|
|
2014-06-25 21:09:36 -04:00
|
|
|
try {
|
2013-10-11 23:09:59 +02:00
|
|
|
if(!AppInitRPC(argc, argv))
|
2014-06-12 22:26:46 -04:00
|
|
|
return EXIT_FAILURE;
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|
|
|
|
|
catch (std::exception& e) {
|
|
|
|
|
PrintExceptionContinue(&e, "AppInitRPC()");
|
2014-06-12 22:26:46 -04:00
|
|
|
return EXIT_FAILURE;
|
2013-10-11 23:09:59 +02:00
|
|
|
} catch (...) {
|
|
|
|
|
PrintExceptionContinue(NULL, "AppInitRPC()");
|
2014-06-12 22:26:46 -04:00
|
|
|
return EXIT_FAILURE;
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|
|
|
|
|
|
2014-06-12 22:26:46 -04:00
|
|
|
int ret = EXIT_FAILURE;
|
2014-06-25 21:09:36 -04:00
|
|
|
try {
|
2014-02-24 14:08:56 +01:00
|
|
|
ret = CommandLineRPC(argc, argv);
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|
|
|
|
|
catch (std::exception& e) {
|
|
|
|
|
PrintExceptionContinue(&e, "CommandLineRPC()");
|
|
|
|
|
} catch (...) {
|
|
|
|
|
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
|
|
|
|
}
|
2014-02-24 14:08:56 +01:00
|
|
|
return ret;
|
2013-10-11 23:09:59 +02:00
|
|
|
}
|