21 #include <boost/bind.hpp> 22 #include <boost/signals2/signal.hpp> 23 #include <boost/algorithm/string/case_conv.hpp> 24 #include <boost/algorithm/string/classification.hpp> 25 #include <boost/algorithm/string/split.hpp> 28 #include <unordered_map> 32 static bool fRPCRunning =
false;
33 static bool fRPCInWarmup =
true;
34 static std::string rpcWarmupStatus(
"RPC server started");
39 static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers;
41 static struct CRPCSignals
43 boost::signals2::signal<void ()> Started;
44 boost::signals2::signal<void ()> Stopped;
45 boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
50 g_rpcSignals.Started.connect(slot);
55 g_rpcSignals.Stopped.connect(slot);
59 const std::list<UniValue::VType>& typesExpected,
65 if (params.
size() <= i)
69 if (!(fAllowNull && v.
isNull())) {
78 if (value.
type() != typeExpected) {
84 const std::map<std::string, UniValueType>& typesExpected,
88 for (
const auto& t : typesExpected) {
90 if (!fAllowNull && v.
isNull())
93 if (!(t.second.typeAny || v.
type() == t.second.type || (fAllowNull && v.
isNull()))) {
94 std::string err =
strprintf(
"Expected type %s for %s, got %s",
102 for (
const std::string& k : o.
getKeys())
104 if (typesExpected.count(k) == 0)
106 std::string err =
strprintf(
"Unexpected key %s", k);
132 if (64 != strHex.length())
163 std::string category;
164 std::set<rpcfn_type> setDone;
165 std::vector<std::pair<std::string, const CRPCCommand*> > vCommands;
167 for (std::map<std::string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
168 vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second));
169 sort(vCommands.begin(), vCommands.end());
175 for (
const std::pair<std::string, const CRPCCommand*>& command : vCommands)
178 std::string strMethod = pcmd->
name;
179 if ((strCommand !=
"" || pcmd->
category ==
"hidden") && strMethod != strCommand)
181 jreq.strMethod = strMethod;
185 if (setDone.insert(pfn).second)
188 catch (
const std::exception& e)
191 std::string strHelp = std::string(e.what());
192 if (strCommand ==
"")
194 if (strHelp.find(
'\n') != std::string::npos)
195 strHelp = strHelp.substr(0, strHelp.find(
'\n'));
199 if (!category.empty())
202 std::string firstLetter = category.substr(0,1);
203 boost::to_upper(firstLetter);
204 strRet +=
"== " + firstLetter + category.substr(1) +
" ==\n";
207 strRet += strHelp +
"\n";
211 strRet =
strprintf(
"help: unknown command: %s\n", strCommand);
212 strRet = strRet.substr(0,strRet.size()-1);
219 throw std::runtime_error(
220 "help ( \"command\" )\n" 221 "\nList all commands, or get help for a specified command.\n" 223 "1. \"command\" (string, optional) The command to get help on\n" 225 "\"text\" (string) The help text\n" 228 std::string strCommand;
240 throw std::runtime_error(
242 "\nStop Raven server.");
246 return "Raven server stopping";
252 throw std::runtime_error(
254 "\nReturns the total uptime of the server.\n" 256 "ttt (numeric) The number of seconds that the server has been running\n" 272 {
"control",
"help", &
help, {
"command"} },
273 {
"control",
"stop", &
stop, {} },
274 {
"control",
"uptime", &
uptime, {} },
282 for (vcidx = 0; vcidx < (
sizeof(vRPCCommands) /
sizeof(vRPCCommands[0])); vcidx++)
286 pcmd = &vRPCCommands[vcidx];
287 mapCommands[pcmd->
name] = pcmd;
293 std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
294 if (it == mapCommands.end())
305 std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
306 if (it != mapCommands.end())
309 mapCommands[name] = pcmd;
317 g_rpcSignals.Started();
331 deadlineTimers.clear();
333 g_rpcSignals.Stopped();
344 rpcWarmupStatus = newStatus;
350 assert(fRPCInWarmup);
351 fRPCInWarmup =
false;
358 *outStatus = rpcWarmupStatus;
376 if (!valMethod.
isStr())
378 strMethod = valMethod.
get_str();
385 else if (valParams.
isNull())
393 const std::vector<std::string> enabled_methods =
gArgs.
GetArgs(
"-deprecatedrpc");
395 return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end();
412 catch (
const std::exception& e)
424 for (
unsigned int reqIdx = 0; reqIdx < vReq.
size(); reqIdx++)
425 ret.
push_back(JSONRPCExecOne(jreq, vReq[reqIdx]));
427 return ret.
write() +
"\n";
442 std::unordered_map<std::string, const UniValue*> argsIn;
443 for (
size_t i=0; i<keys.size(); ++i) {
444 argsIn[keys[i]] = &values[i];
448 for (
const std::string &argNamePattern: argNames) {
449 std::vector<std::string> vargNames;
450 boost::algorithm::split(vargNames, argNamePattern, boost::algorithm::is_any_of(
"|"));
451 auto fr = argsIn.end();
452 for (
const std::string & argName : vargNames) {
453 fr = argsIn.find(argName);
454 if (fr != argsIn.end()) {
458 if (fr != argsIn.end()) {
459 for (
int i = 0; i < hole; ++i) {
473 if (!argsIn.empty()) {
494 g_rpcSignals.PreCommand(*pcmd);
500 return pcmd->
actor(transformNamedArguments(request, pcmd->
argNames));
502 return pcmd->
actor(request);
505 catch (
const std::exception& e)
513 std::vector<std::string> commandList;
514 typedef std::map<std::string, const CRPCCommand*> commandMap;
516 std::transform( mapCommands.begin(), mapCommands.end(),
517 std::back_inserter(commandList),
518 boost::bind(&commandMap::value_type::first,_1) );
522 std::string
HelpExampleCli(
const std::string& methodname,
const std::string& args)
524 return "> raven-cli " + methodname +
" " + args +
"\n";
527 std::string
HelpExampleRpc(
const std::string& methodname,
const std::string& args)
529 return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", " 530 "\"method\": \"" + methodname +
"\", \"params\": [" + args +
"] }' -H 'content-type: text/plain;' http://127.0.0.1:8766/\n";
536 timerInterface = iface;
541 timerInterface = iface;
546 if (timerInterface == iface)
547 timerInterface =
nullptr;
550 void RPCRunLater(
const std::string& name, std::function<
void(
void)> func, int64_t nSeconds)
554 deadlineTimers.erase(name);
555 LogPrint(
BCLog::RPC,
"queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->
Name());
556 deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->
NewTimer(func, nSeconds*1000)));
562 if (
gArgs.
GetArg(
"-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0)
563 flag |= SERIALIZE_TRANSACTION_NO_WITNESS;
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
uint256 ParseHashO(const UniValue &o, std::string strKey)
std::vector< unsigned char > ParseHexO(const UniValue &o, std::string strKey)
std::string help(const std::string &name, const JSONRPCRequest &helpreq) const
Note: This interface may still be subject to change.
const std::vector< UniValue > & getValues() const
Raven RPC command dispatcher.
bool IsRPCRunning()
Query whether RPC is running.
void SetRPCWarmupStatus(const std::string &newStatus)
Set the RPC warmup status.
UniValue uptime(const JSONRPCRequest &jsonRequest)
int64_t GetStartupTime()
Server/client environment: argument handling, config file parsing, logging, thread wrappers...
bool MoneyRange(const CAmount &nValue)
void OnStopped(std::function< void()> slot)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
const std::string & get_str() const
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
const std::vector< std::string > & getKeys() const
const std::string & getValStr() const
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
std::vector< std::string > argNames
void RPCTypeCheck(const UniValue ¶ms, const std::list< UniValue::VType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Invalid, missing or duplicate parameter.
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded Values (throws error if not hex).
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
const UniValue & find_value(const UniValue &obj, const std::string &name)
int64_t CAmount
Amount in corbies (Can be negative)
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
const CRPCCommand * operator[](const std::string &name) const
void SetRPCWarmupFinished()
const char * uvTypeName(UniValue::VType t)
bool push_back(const UniValue &val)
virtual RPCTimerBase * NewTimer(std::function< void(void)> &func, int64_t millis)=0
Factory function for timers.
void RPCTypeCheckArgument(const UniValue &value, UniValue::VType typeExpected)
Type-check one argument; throws JSONRPCError if wrong type given.
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
std::string JSONRPCExecBatch(const JSONRPCRequest &jreq, const UniValue &vReq)
bool IsHex(const std::string &str)
Unexpected type was passed as parameter.
General application defined errors.
UniValue help(const JSONRPCRequest &jsonRequest)
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
CAmount AmountFromValue(const UniValue &value)
bool IsDeprecatedRPCEnabled(const std::string &method)
void RPCRunLater(const std::string &name, std::function< void(void)> func, int64_t nSeconds)
Run func nSeconds from now.
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
std::vector< unsigned char > ParseHexV(const UniValue &v, std::string strName)
#define LogPrint(category,...)
void parse(const UniValue &valRequest)
int RPCSerializationFlags()
const UniValue & get_obj() const
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
void RPCSetTimerInterface(RPCTimerInterface *iface)
Set the factory function for timers.
bool RPCIsInWarmup(std::string *outStatus)
const UniValue NullUniValue
Standard JSON-RPC 2.0 errors.
virtual const char * Name()=0
Implementation name.
UniValue JSONRPCError(int code, const std::string &message)
void OnStarted(std::function< void()> slot)
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
std::vector< std::string > listCommands() const
Returns a list of registered commands.
void SetHex(const char *psz)
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
UniValue(* rpcfn_type)(const JSONRPCRequest &jsonRequest)
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
UniValue stop(const JSONRPCRequest &jsonRequest)
std::vector< unsigned char > ParseHex(const char *psz)