2011-05-14 20:10:21 +02:00
|
|
|
// Copyright (c) 2010 Satoshi Nakamoto
|
2016-12-31 19:01:21 +01:00
|
|
|
// Copyright (c) 2009-2016 The Bitcoin Core developers
|
2014-10-30 03:14:08 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2012-05-18 16:02:28 +02:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2016-01-15 01:55:17 +01:00
|
|
|
#include "rpc/server.h"
|
2013-04-13 07:13:08 +02:00
|
|
|
|
|
|
|
#include "base58.h"
|
2011-06-18 18:46:01 +02:00
|
|
|
#include "init.h"
|
2014-10-19 10:46:17 +02:00
|
|
|
#include "random.h"
|
|
|
|
#include "sync.h"
|
2013-11-29 16:04:29 +01:00
|
|
|
#include "ui_interface.h"
|
2014-01-11 18:14:29 +01:00
|
|
|
#include "util.h"
|
2014-10-19 10:46:17 +02:00
|
|
|
#include "utilstrencodings.h"
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2015-09-04 16:11:34 +02:00
|
|
|
#include <univalue.h>
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
|
2011-08-10 13:53:13 +02:00
|
|
|
#include <boost/bind.hpp>
|
2011-07-13 11:56:38 +02:00
|
|
|
#include <boost/filesystem.hpp>
|
2011-08-10 15:07:46 +02:00
|
|
|
#include <boost/foreach.hpp>
|
2011-08-10 13:53:13 +02:00
|
|
|
#include <boost/shared_ptr.hpp>
|
2014-10-19 10:46:17 +02:00
|
|
|
#include <boost/signals2/signal.hpp>
|
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 <boost/thread.hpp>
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
#include <boost/algorithm/string/case_conv.hpp> // for to_upper()
|
2014-08-20 21:15:16 +02:00
|
|
|
|
2016-07-18 11:26:21 +02:00
|
|
|
#include <memory> // for unique_ptr
|
2016-09-25 20:42:49 +02:00
|
|
|
#include <unordered_map>
|
2016-07-18 11:26:21 +02:00
|
|
|
|
2012-05-13 06:43:24 +02:00
|
|
|
static bool fRPCRunning = false;
|
2014-10-29 18:08:31 +01:00
|
|
|
static bool fRPCInWarmup = true;
|
|
|
|
static std::string rpcWarmupStatus("RPC server started");
|
|
|
|
static CCriticalSection cs_rpcWarmup;
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
/* Timer-creating functions */
|
2016-01-08 11:03:52 +01:00
|
|
|
static RPCTimerInterface* timerInterface = NULL;
|
2016-07-18 11:26:21 +02:00
|
|
|
/* Map of name to timer. */
|
|
|
|
static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers;
|
2012-04-15 02:35:58 +02:00
|
|
|
|
2014-10-19 10:46:17 +02:00
|
|
|
static struct CRPCSignals
|
|
|
|
{
|
|
|
|
boost::signals2::signal<void ()> Started;
|
|
|
|
boost::signals2::signal<void ()> Stopped;
|
|
|
|
boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
|
|
|
|
} g_rpcSignals;
|
|
|
|
|
|
|
|
void RPCServer::OnStarted(boost::function<void ()> slot)
|
|
|
|
{
|
|
|
|
g_rpcSignals.Started.connect(slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RPCServer::OnStopped(boost::function<void ()> slot)
|
|
|
|
{
|
|
|
|
g_rpcSignals.Stopped.connect(slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RPCServer::OnPreCommand(boost::function<void (const CRPCCommand&)> slot)
|
|
|
|
{
|
|
|
|
g_rpcSignals.PreCommand.connect(boost::bind(slot, _1));
|
|
|
|
}
|
|
|
|
|
2015-05-18 14:02:18 +02:00
|
|
|
void RPCTypeCheck(const UniValue& params,
|
2017-01-04 05:22:19 +01:00
|
|
|
const std::list<UniValue::VType>& typesExpected,
|
2012-08-20 22:18:17 +02:00
|
|
|
bool fAllowNull)
|
2012-06-23 00:36:42 +02:00
|
|
|
{
|
2012-07-05 19:25:52 +02:00
|
|
|
unsigned int i = 0;
|
2015-05-18 14:02:18 +02:00
|
|
|
BOOST_FOREACH(UniValue::VType t, typesExpected)
|
2012-06-23 00:36:42 +02:00
|
|
|
{
|
|
|
|
if (params.size() <= i)
|
|
|
|
break;
|
|
|
|
|
2015-05-18 14:02:18 +02:00
|
|
|
const UniValue& v = params[i];
|
2017-01-17 16:40:41 +01:00
|
|
|
if (!(fAllowNull && v.isNull())) {
|
|
|
|
RPCTypeCheckArgument(v, t);
|
2012-06-23 00:36:42 +02:00
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-17 16:40:41 +01:00
|
|
|
void RPCTypeCheckArgument(const UniValue& value, UniValue::VType typeExpected)
|
|
|
|
{
|
|
|
|
if (value.type() != typeExpected) {
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected), uvTypeName(value.type())));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-20 21:15:16 +02:00
|
|
|
void RPCTypeCheckObj(const UniValue& o,
|
2017-01-04 05:22:19 +01:00
|
|
|
const std::map<std::string, UniValueType>& typesExpected,
|
2016-06-06 17:50:50 +02:00
|
|
|
bool fAllowNull,
|
|
|
|
bool fStrict)
|
2012-06-23 00:36:42 +02:00
|
|
|
{
|
2016-06-06 17:50:50 +02:00
|
|
|
for (const auto& t : typesExpected) {
|
2015-05-18 14:02:18 +02:00
|
|
|
const UniValue& v = find_value(o, t.first);
|
2014-08-20 21:15:16 +02:00
|
|
|
if (!fAllowNull && v.isNull())
|
2014-01-16 16:15:27 +01:00
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
|
2012-08-20 22:18:17 +02:00
|
|
|
|
2016-06-06 17:50:50 +02:00
|
|
|
if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) {
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string err = strprintf("Expected type %s for %s, got %s",
|
2016-06-06 17:50:50 +02:00
|
|
|
uvTypeName(t.second.type), t.first, uvTypeName(v.type()));
|
2012-10-04 09:34:44 +02:00
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
2012-06-23 00:36:42 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-30 01:59:29 +02:00
|
|
|
|
|
|
|
if (fStrict)
|
|
|
|
{
|
2017-01-04 05:22:19 +01:00
|
|
|
BOOST_FOREACH(const std::string& k, o.getKeys())
|
2016-03-30 01:59:29 +02:00
|
|
|
{
|
|
|
|
if (typesExpected.count(k) == 0)
|
|
|
|
{
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string err = strprintf("Unexpected key %s", k);
|
2016-03-30 01:59:29 +02:00
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-06-23 00:36:42 +02:00
|
|
|
}
|
|
|
|
|
2015-05-18 14:02:18 +02:00
|
|
|
CAmount AmountFromValue(const UniValue& value)
|
2011-05-14 20:10:21 +02:00
|
|
|
{
|
2015-07-06 11:43:56 +02:00
|
|
|
if (!value.isNum() && !value.isStr())
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
|
2015-06-04 14:22:26 +02:00
|
|
|
CAmount amount;
|
2015-07-06 10:49:24 +02:00
|
|
|
if (!ParseFixedPoint(value.getValStr(), 8, &amount))
|
2012-10-04 09:34:44 +02:00
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
2015-06-04 14:22:26 +02:00
|
|
|
if (!MoneyRange(amount))
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
|
|
|
|
return amount;
|
2011-05-14 20:10:21 +02:00
|
|
|
}
|
|
|
|
|
2015-05-13 21:29:19 +02:00
|
|
|
UniValue ValueFromAmount(const CAmount& amount)
|
2011-05-14 20:10:21 +02:00
|
|
|
{
|
2015-07-18 07:42:23 +02:00
|
|
|
bool sign = amount < 0;
|
|
|
|
int64_t n_abs = (sign ? -amount : amount);
|
|
|
|
int64_t quotient = n_abs / COIN;
|
|
|
|
int64_t remainder = n_abs % COIN;
|
|
|
|
return UniValue(UniValue::VNUM,
|
|
|
|
strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder));
|
2011-05-14 20:10:21 +02:00
|
|
|
}
|
|
|
|
|
2017-01-04 05:22:19 +01:00
|
|
|
uint256 ParseHashV(const UniValue& v, std::string strName)
|
2013-07-15 08:24:33 +02:00
|
|
|
{
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string strHex;
|
2014-08-20 21:15:16 +02:00
|
|
|
if (v.isStr())
|
2013-07-15 08:24:33 +02:00
|
|
|
strHex = v.get_str();
|
|
|
|
if (!IsHex(strHex)) // Note: IsHex("") is false
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
2016-10-30 16:58:13 +01:00
|
|
|
if (64 != strHex.length())
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d)", strName, 64, strHex.length()));
|
2013-07-15 08:24:33 +02:00
|
|
|
uint256 result;
|
|
|
|
result.SetHex(strHex);
|
|
|
|
return result;
|
|
|
|
}
|
2017-01-04 05:22:19 +01:00
|
|
|
uint256 ParseHashO(const UniValue& o, std::string strKey)
|
2013-07-15 08:24:33 +02:00
|
|
|
{
|
|
|
|
return ParseHashV(find_value(o, strKey), strKey);
|
|
|
|
}
|
2017-01-04 05:22:19 +01:00
|
|
|
std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
|
2013-07-15 08:24:33 +02:00
|
|
|
{
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string strHex;
|
2014-08-20 21:15:16 +02:00
|
|
|
if (v.isStr())
|
2013-07-15 08:24:33 +02:00
|
|
|
strHex = v.get_str();
|
|
|
|
if (!IsHex(strHex))
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
|
|
|
return ParseHex(strHex);
|
|
|
|
}
|
2017-01-04 05:22:19 +01:00
|
|
|
std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
|
2013-07-15 08:24:33 +02:00
|
|
|
{
|
|
|
|
return ParseHexV(find_value(o, strKey), strKey);
|
|
|
|
}
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2014-10-30 03:14:08 +01:00
|
|
|
/**
|
|
|
|
* Note: This interface may still be subject to change.
|
|
|
|
*/
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2016-12-29 14:05:51 +01:00
|
|
|
std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const
|
2011-05-14 20:10:21 +02:00
|
|
|
{
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string strRet;
|
|
|
|
std::string category;
|
|
|
|
std::set<rpcfn_type> setDone;
|
|
|
|
std::vector<std::pair<std::string, const CRPCCommand*> > vCommands;
|
2014-07-15 21:38:52 +02:00
|
|
|
|
2017-01-04 05:22:19 +01:00
|
|
|
for (std::map<std::string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
|
2014-07-15 21:38:52 +02:00
|
|
|
vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second));
|
|
|
|
sort(vCommands.begin(), vCommands.end());
|
|
|
|
|
2016-12-29 14:05:51 +01:00
|
|
|
JSONRPCRequest jreq(helpreq);
|
|
|
|
jreq.fHelp = true;
|
|
|
|
jreq.params = UniValue();
|
|
|
|
|
2017-01-04 05:22:19 +01:00
|
|
|
BOOST_FOREACH(const PAIRTYPE(std::string, const CRPCCommand*)& command, vCommands)
|
2011-05-14 20:10:21 +02:00
|
|
|
{
|
2014-07-15 21:38:52 +02:00
|
|
|
const CRPCCommand *pcmd = command.second;
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string strMethod = pcmd->name;
|
2014-11-26 16:33:18 +01:00
|
|
|
if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand)
|
2011-05-14 20:10:21 +02:00
|
|
|
continue;
|
2016-12-29 14:05:51 +01:00
|
|
|
jreq.strMethod = strMethod;
|
2011-05-14 20:10:21 +02:00
|
|
|
try
|
|
|
|
{
|
2012-04-15 05:55:05 +02:00
|
|
|
rpcfn_type pfn = pcmd->actor;
|
2011-05-14 20:10:21 +02:00
|
|
|
if (setDone.insert(pfn).second)
|
2016-09-22 09:46:41 +02:00
|
|
|
(*pfn)(jreq);
|
2011-05-14 20:10:21 +02:00
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception& e)
|
2011-05-14 20:10:21 +02:00
|
|
|
{
|
|
|
|
// Help text is returned in an exception
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string strHelp = std::string(e.what());
|
2011-05-14 20:10:21 +02:00
|
|
|
if (strCommand == "")
|
2014-07-15 21:38:52 +02:00
|
|
|
{
|
2017-01-04 05:22:19 +01:00
|
|
|
if (strHelp.find('\n') != std::string::npos)
|
2011-05-14 20:10:21 +02:00
|
|
|
strHelp = strHelp.substr(0, strHelp.find('\n'));
|
2014-07-15 21:38:52 +02:00
|
|
|
|
|
|
|
if (category != pcmd->category)
|
|
|
|
{
|
|
|
|
if (!category.empty())
|
|
|
|
strRet += "\n";
|
|
|
|
category = pcmd->category;
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string firstLetter = category.substr(0,1);
|
2014-07-15 21:38:52 +02:00
|
|
|
boost::to_upper(firstLetter);
|
|
|
|
strRet += "== " + firstLetter + category.substr(1) + " ==\n";
|
|
|
|
}
|
|
|
|
}
|
2011-05-14 20:10:21 +02:00
|
|
|
strRet += strHelp + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (strRet == "")
|
2014-01-16 16:15:27 +01:00
|
|
|
strRet = strprintf("help: unknown command: %s\n", strCommand);
|
2011-05-14 20:10:21 +02:00
|
|
|
strRet = strRet.substr(0,strRet.size()-1);
|
|
|
|
return strRet;
|
|
|
|
}
|
|
|
|
|
2016-09-22 09:46:41 +02:00
|
|
|
UniValue help(const JSONRPCRequest& jsonRequest)
|
2012-04-18 22:42:17 +02:00
|
|
|
{
|
2016-09-22 09:46:41 +02:00
|
|
|
if (jsonRequest.fHelp || jsonRequest.params.size() > 1)
|
2017-01-04 05:22:19 +01:00
|
|
|
throw std::runtime_error(
|
2013-10-29 12:29:44 +01:00
|
|
|
"help ( \"command\" )\n"
|
|
|
|
"\nList all commands, or get help for a specified command.\n"
|
|
|
|
"\nArguments:\n"
|
|
|
|
"1. \"command\" (string, optional) The command to get help on\n"
|
|
|
|
"\nResult:\n"
|
|
|
|
"\"text\" (string) The help text\n"
|
|
|
|
);
|
2012-04-18 22:42:17 +02:00
|
|
|
|
2017-01-04 05:22:19 +01:00
|
|
|
std::string strCommand;
|
2016-09-22 09:46:41 +02:00
|
|
|
if (jsonRequest.params.size() > 0)
|
|
|
|
strCommand = jsonRequest.params[0].get_str();
|
2012-04-18 22:42:17 +02:00
|
|
|
|
2016-12-29 14:05:51 +01:00
|
|
|
return tableRPC.help(strCommand, jsonRequest);
|
2012-04-18 22:42:17 +02:00
|
|
|
}
|
|
|
|
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2016-09-22 09:46:41 +02:00
|
|
|
UniValue stop(const JSONRPCRequest& jsonRequest)
|
2011-05-14 20:10:21 +02:00
|
|
|
{
|
2013-01-20 18:50:30 +01:00
|
|
|
// Accept the deprecated and ignored 'detach' boolean argument
|
2016-09-22 09:46:41 +02:00
|
|
|
if (jsonRequest.fHelp || jsonRequest.params.size() > 1)
|
2017-01-04 05:22:19 +01:00
|
|
|
throw std::runtime_error(
|
2012-11-04 12:48:45 +01:00
|
|
|
"stop\n"
|
2013-10-29 12:29:44 +01:00
|
|
|
"\nStop Bitcoin server.");
|
2015-09-24 17:29:22 +02:00
|
|
|
// Event loop will exit after current HTTP requests have been handled, so
|
|
|
|
// this reply will get back to the client.
|
2012-06-11 07:40:14 +02:00
|
|
|
StartShutdown();
|
2012-05-13 16:09:14 +02:00
|
|
|
return "Bitcoin server stopping";
|
2011-05-14 20:10:21 +02:00
|
|
|
}
|
|
|
|
|
2014-10-30 03:14:08 +01:00
|
|
|
/**
|
|
|
|
* Call Table
|
|
|
|
*/
|
2012-04-21 01:37:34 +02:00
|
|
|
static const CRPCCommand vRPCCommands[] =
|
2016-09-25 20:42:49 +02:00
|
|
|
{ // category name actor (function) okSafe argNames
|
|
|
|
// --------------------- ------------------------ ----------------------- ------ ----------
|
2014-03-26 12:26:43 +01:00
|
|
|
/* Overall control/query calls */
|
2016-09-25 20:42:49 +02:00
|
|
|
{ "control", "help", &help, true, {"command"} },
|
|
|
|
{ "control", "stop", &stop, true, {} },
|
2011-05-14 20:10:21 +02:00
|
|
|
};
|
|
|
|
|
2012-04-18 22:42:17 +02:00
|
|
|
CRPCTable::CRPCTable()
|
2012-04-15 05:55:05 +02:00
|
|
|
{
|
|
|
|
unsigned int vcidx;
|
|
|
|
for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
|
|
|
|
{
|
2012-04-21 01:37:34 +02:00
|
|
|
const CRPCCommand *pcmd;
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2012-04-15 05:55:05 +02:00
|
|
|
pcmd = &vRPCCommands[vcidx];
|
|
|
|
mapCommands[pcmd->name] = pcmd;
|
|
|
|
}
|
|
|
|
}
|
2011-05-14 20:10:21 +02:00
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
const CRPCCommand *CRPCTable::operator[](const std::string &name) const
|
2012-04-18 22:42:17 +02:00
|
|
|
{
|
2017-01-04 05:22:19 +01:00
|
|
|
std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
|
2012-04-18 22:42:17 +02:00
|
|
|
if (it == mapCommands.end())
|
|
|
|
return NULL;
|
|
|
|
return (*it).second;
|
|
|
|
}
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2016-01-07 08:33:49 +01:00
|
|
|
bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd)
|
|
|
|
{
|
|
|
|
if (IsRPCRunning())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// don't allow overwriting for now
|
2017-01-04 05:22:19 +01:00
|
|
|
std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
|
2016-01-07 08:33:49 +01:00
|
|
|
if (it != mapCommands.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mapCommands[name] = pcmd;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
bool StartRPC()
|
2011-08-10 13:53:13 +02:00
|
|
|
{
|
2016-12-25 21:19:40 +01:00
|
|
|
LogPrint(BCLog::RPC, "Starting RPC\n");
|
2012-05-13 06:43:24 +02:00
|
|
|
fRPCRunning = true;
|
2014-10-19 10:46:17 +02:00
|
|
|
g_rpcSignals.Started();
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
return true;
|
2013-03-07 04:31:26 +01:00
|
|
|
}
|
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
void InterruptRPC()
|
2014-01-17 16:32:35 +01:00
|
|
|
{
|
2016-12-25 21:19:40 +01:00
|
|
|
LogPrint(BCLog::RPC, "Interrupting RPC\n");
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
// Interrupt e.g. running longpolls
|
|
|
|
fRPCRunning = false;
|
2014-01-17 16:32:35 +01:00
|
|
|
}
|
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
void StopRPC()
|
2013-03-07 04:31:26 +01:00
|
|
|
{
|
2016-12-25 21:19:40 +01:00
|
|
|
LogPrint(BCLog::RPC, "Stopping RPC\n");
|
2013-05-07 16:47:00 +02:00
|
|
|
deadlineTimers.clear();
|
2017-03-28 08:20:08 +02:00
|
|
|
DeleteAuthCookie();
|
2014-10-19 10:46:17 +02:00
|
|
|
g_rpcSignals.Stopped();
|
2012-04-15 02:35:58 +02:00
|
|
|
}
|
|
|
|
|
2012-05-13 06:43:24 +02:00
|
|
|
bool IsRPCRunning()
|
|
|
|
{
|
|
|
|
return fRPCRunning;
|
|
|
|
}
|
|
|
|
|
2014-10-29 18:08:31 +01:00
|
|
|
void SetRPCWarmupStatus(const std::string& newStatus)
|
|
|
|
{
|
|
|
|
LOCK(cs_rpcWarmup);
|
|
|
|
rpcWarmupStatus = newStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetRPCWarmupFinished()
|
|
|
|
{
|
|
|
|
LOCK(cs_rpcWarmup);
|
|
|
|
assert(fRPCInWarmup);
|
|
|
|
fRPCInWarmup = false;
|
|
|
|
}
|
|
|
|
|
2014-11-26 13:51:02 +01:00
|
|
|
bool RPCIsInWarmup(std::string *outStatus)
|
|
|
|
{
|
|
|
|
LOCK(cs_rpcWarmup);
|
|
|
|
if (outStatus)
|
|
|
|
*outStatus = rpcWarmupStatus;
|
|
|
|
return fRPCInWarmup;
|
|
|
|
}
|
|
|
|
|
2016-09-22 09:46:41 +02:00
|
|
|
void JSONRPCRequest::parse(const UniValue& valRequest)
|
2012-06-27 19:47:02 +02:00
|
|
|
{
|
|
|
|
// Parse request
|
2014-08-20 21:15:16 +02:00
|
|
|
if (!valRequest.isObject())
|
2012-10-04 09:34:44 +02:00
|
|
|
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
|
2015-05-18 14:02:18 +02:00
|
|
|
const UniValue& request = valRequest.get_obj();
|
2012-06-27 19:47:02 +02:00
|
|
|
|
|
|
|
// Parse id now so errors from here on will have the id
|
|
|
|
id = find_value(request, "id");
|
|
|
|
|
|
|
|
// Parse method
|
2015-05-13 21:29:19 +02:00
|
|
|
UniValue valMethod = find_value(request, "method");
|
2014-08-20 21:15:16 +02:00
|
|
|
if (valMethod.isNull())
|
2012-10-04 09:34:44 +02:00
|
|
|
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
|
2014-08-20 21:15:16 +02:00
|
|
|
if (!valMethod.isStr())
|
2012-10-04 09:34:44 +02:00
|
|
|
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
|
2012-06-27 19:47:02 +02:00
|
|
|
strMethod = valMethod.get_str();
|
2017-04-06 16:37:30 +02:00
|
|
|
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
|
2012-06-27 19:47:02 +02:00
|
|
|
|
|
|
|
// Parse params
|
2015-05-13 21:29:19 +02:00
|
|
|
UniValue valParams = find_value(request, "params");
|
2016-09-25 20:42:49 +02:00
|
|
|
if (valParams.isArray() || valParams.isObject())
|
|
|
|
params = valParams;
|
2014-08-20 21:15:16 +02:00
|
|
|
else if (valParams.isNull())
|
2015-05-18 14:02:18 +02:00
|
|
|
params = UniValue(UniValue::VARR);
|
2012-06-27 19:47:02 +02:00
|
|
|
else
|
2016-09-25 20:42:49 +02:00
|
|
|
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
|
2012-06-27 19:47:02 +02:00
|
|
|
}
|
|
|
|
|
2015-05-18 14:02:18 +02:00
|
|
|
static UniValue JSONRPCExecOne(const UniValue& req)
|
2012-06-24 08:01:28 +02:00
|
|
|
{
|
2015-05-10 14:48:35 +02:00
|
|
|
UniValue rpc_result(UniValue::VOBJ);
|
2012-06-24 08:01:28 +02:00
|
|
|
|
2016-09-22 09:46:41 +02:00
|
|
|
JSONRPCRequest jreq;
|
2012-06-24 08:01:28 +02:00
|
|
|
try {
|
|
|
|
jreq.parse(req);
|
|
|
|
|
2016-09-22 09:46:41 +02:00
|
|
|
UniValue result = tableRPC.execute(jreq);
|
2014-08-20 21:15:16 +02:00
|
|
|
rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
|
2012-06-24 08:01:28 +02:00
|
|
|
}
|
2015-05-18 14:02:18 +02:00
|
|
|
catch (const UniValue& objError)
|
2012-06-24 08:01:28 +02:00
|
|
|
{
|
2014-08-20 21:15:16 +02:00
|
|
|
rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
|
2012-06-24 08:01:28 +02:00
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception& e)
|
2012-06-24 08:01:28 +02:00
|
|
|
{
|
2014-08-20 21:15:16 +02:00
|
|
|
rpc_result = JSONRPCReplyObj(NullUniValue,
|
2012-10-04 09:34:44 +02:00
|
|
|
JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
|
2012-06-24 08:01:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return rpc_result;
|
|
|
|
}
|
|
|
|
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
std::string JSONRPCExecBatch(const UniValue& vReq)
|
2012-06-24 08:01:28 +02:00
|
|
|
{
|
2015-06-02 11:41:00 +02:00
|
|
|
UniValue ret(UniValue::VARR);
|
2012-06-24 08:01:28 +02:00
|
|
|
for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
|
|
|
|
ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
|
|
|
|
|
2014-08-20 21:15:16 +02:00
|
|
|
return ret.write() + "\n";
|
2012-06-24 08:01:28 +02:00
|
|
|
}
|
|
|
|
|
2016-09-25 20:42:49 +02:00
|
|
|
/**
|
|
|
|
* Process named arguments into a vector of positional arguments, based on the
|
|
|
|
* passed-in specification for the RPC call's arguments.
|
|
|
|
*/
|
|
|
|
static inline JSONRPCRequest transformNamedArguments(const JSONRPCRequest& in, const std::vector<std::string>& argNames)
|
|
|
|
{
|
|
|
|
JSONRPCRequest out = in;
|
|
|
|
out.params = UniValue(UniValue::VARR);
|
|
|
|
// Build a map of parameters, and remove ones that have been processed, so that we can throw a focused error if
|
|
|
|
// there is an unknown one.
|
|
|
|
const std::vector<std::string>& keys = in.params.getKeys();
|
|
|
|
const std::vector<UniValue>& values = in.params.getValues();
|
|
|
|
std::unordered_map<std::string, const UniValue*> argsIn;
|
|
|
|
for (size_t i=0; i<keys.size(); ++i) {
|
|
|
|
argsIn[keys[i]] = &values[i];
|
|
|
|
}
|
|
|
|
// Process expected parameters.
|
|
|
|
int hole = 0;
|
|
|
|
for (const std::string &argName: argNames) {
|
|
|
|
auto fr = argsIn.find(argName);
|
|
|
|
if (fr != argsIn.end()) {
|
|
|
|
for (int i = 0; i < hole; ++i) {
|
|
|
|
// Fill hole between specified parameters with JSON nulls,
|
|
|
|
// but not at the end (for backwards compatibility with calls
|
|
|
|
// that act based on number of specified parameters).
|
|
|
|
out.params.push_back(UniValue());
|
|
|
|
}
|
|
|
|
hole = 0;
|
|
|
|
out.params.push_back(*fr->second);
|
|
|
|
argsIn.erase(fr);
|
|
|
|
} else {
|
|
|
|
hole += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If there are still arguments in the argsIn map, this is an error.
|
|
|
|
if (!argsIn.empty()) {
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown named parameter " + argsIn.begin()->first);
|
|
|
|
}
|
|
|
|
// Return request with named arguments transformed to positional arguments
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2016-09-22 09:46:41 +02:00
|
|
|
UniValue CRPCTable::execute(const JSONRPCRequest &request) const
|
2012-04-09 21:07:25 +02:00
|
|
|
{
|
2015-07-02 03:34:31 +02:00
|
|
|
// Return immediately if in warmup
|
|
|
|
{
|
|
|
|
LOCK(cs_rpcWarmup);
|
|
|
|
if (fRPCInWarmup)
|
|
|
|
throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
|
|
|
|
}
|
|
|
|
|
2012-04-09 21:07:25 +02:00
|
|
|
// Find method
|
2016-09-22 09:46:41 +02:00
|
|
|
const CRPCCommand *pcmd = tableRPC[request.strMethod];
|
2012-04-09 21:07:25 +02:00
|
|
|
if (!pcmd)
|
2012-10-04 09:34:44 +02:00
|
|
|
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2014-10-19 10:46:17 +02:00
|
|
|
g_rpcSignals.PreCommand(*pcmd);
|
2012-04-09 21:07:25 +02:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2016-09-25 20:42:49 +02:00
|
|
|
// Execute, convert arguments to array if necessary
|
|
|
|
if (request.params.isObject()) {
|
|
|
|
return pcmd->actor(transformNamedArguments(request, pcmd->argNames));
|
|
|
|
} else {
|
|
|
|
return pcmd->actor(request);
|
|
|
|
}
|
2012-04-09 21:07:25 +02:00
|
|
|
}
|
2014-12-07 13:29:06 +01:00
|
|
|
catch (const std::exception& e)
|
2012-04-09 21:07:25 +02:00
|
|
|
{
|
2012-10-04 09:34:44 +02:00
|
|
|
throw JSONRPCError(RPC_MISC_ERROR, e.what());
|
2012-04-09 21:07:25 +02:00
|
|
|
}
|
|
|
|
}
|
2011-05-14 20:10:21 +02:00
|
|
|
|
2016-02-27 04:57:12 +01:00
|
|
|
std::vector<std::string> CRPCTable::listCommands() const
|
|
|
|
{
|
|
|
|
std::vector<std::string> commandList;
|
|
|
|
typedef std::map<std::string, const CRPCCommand*> commandMap;
|
|
|
|
|
|
|
|
std::transform( mapCommands.begin(), mapCommands.end(),
|
|
|
|
std::back_inserter(commandList),
|
|
|
|
boost::bind(&commandMap::value_type::first,_1) );
|
|
|
|
return commandList;
|
|
|
|
}
|
|
|
|
|
2015-05-31 15:36:44 +02:00
|
|
|
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
|
|
|
|
{
|
2013-11-29 15:48:07 +01:00
|
|
|
return "> bitcoin-cli " + methodname + " " + args + "\n";
|
|
|
|
}
|
|
|
|
|
2015-05-31 15:36:44 +02:00
|
|
|
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
|
|
|
|
{
|
2013-11-29 15:48:07 +01:00
|
|
|
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
|
|
|
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
|
|
|
|
}
|
|
|
|
|
2016-01-08 11:03:52 +01:00
|
|
|
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
{
|
2016-01-08 11:03:52 +01:00
|
|
|
if (!timerInterface)
|
|
|
|
timerInterface = iface;
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-08 11:03:52 +01:00
|
|
|
void RPCSetTimerInterface(RPCTimerInterface *iface)
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
{
|
2016-01-08 11:03:52 +01:00
|
|
|
timerInterface = iface;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
|
|
|
|
{
|
|
|
|
if (timerInterface == iface)
|
|
|
|
timerInterface = NULL;
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds)
|
|
|
|
{
|
2016-01-08 11:03:52 +01:00
|
|
|
if (!timerInterface)
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
|
|
|
|
deadlineTimers.erase(name);
|
2016-12-25 21:19:40 +01:00
|
|
|
LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
|
2016-07-19 01:15:59 +02:00
|
|
|
deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
|
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
|
|
|
}
|
|
|
|
|
2016-11-20 15:54:51 +01:00
|
|
|
int RPCSerializationFlags()
|
|
|
|
{
|
|
|
|
int flag = 0;
|
|
|
|
if (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0)
|
|
|
|
flag |= SERIALIZE_TRANSACTION_NO_WITNESS;
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
2016-01-07 08:33:49 +01:00
|
|
|
CRPCTable tableRPC;
|