23 #include <boost/signals2/signal.hpp>
24 #include <boost/thread.hpp>
25 #include <boost/algorithm/string/classification.hpp>
26 #include <boost/algorithm/string/split.hpp>
29 #include <unordered_map>
31 static std::atomic<bool> g_rpc_running{
false};
32 static bool fRPCInWarmup =
true;
33 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);
60 g_rpcSignals.PreCommand.connect(std::bind(slot, std::placeholders::_1));
64 const std::list<UniValue::VType>& typesExpected,
69 if (params.
size() <= i)
73 if (!((v.
type() == t) || (fAllowNull && (v.
isNull())))) {
74 std::string err =
strprintf(
"Expected type %s, got %s",
90 const std::map<std::string, UniValueType>& typesExpected,
94 for (
const auto& t : typesExpected) {
96 if (!fAllowNull && v.
isNull())
99 if (!(t.second.typeAny || v.
type() == t.second.type || (fAllowNull && v.
isNull()))) {
100 std::string err =
strprintf(
"Expected type %s for %s, got %s",
107 for (
const std::string& k : o.
getKeys()) {
108 if (typesExpected.count(k) == 0) {
109 std::string err =
strprintf(
"Unexpected key %s", k);
123 if (!
Params().GetConsensus().MoneyRange(nAmount))
130 bool sign = amount < 0;
131 int64_t n_abs = (sign ? -amount : amount);
132 int64_t quotient = n_abs / COIN;
133 int64_t remainder = n_abs % COIN;
135 strprintf(
"%s%d.%08d", sign ?
"-" :
"", quotient, remainder));
140 std::string strHex(v.
get_str());
141 if (64 != strHex.length())
200 std::string category;
201 std::set<rpcfn_type> setDone;
202 std::vector<std::pair<std::string, const CRPCCommand*> > vCommands;
205 vCommands.emplace_back(entry.second->category + entry.first, entry.second);
206 std::sort(vCommands.begin(), vCommands.end());
212 for (
const std::pair<std::string, const CRPCCommand*>& command : vCommands) {
214 std::string strMethod = pcmd->
name;
215 if ((strCommand !=
"" || pcmd->
category ==
"hidden") && strMethod != strCommand)
220 if (setDone.insert(pfn).second)
222 }
catch (
const std::exception& e) {
224 std::string strHelp = std::string(e.what());
225 if (strCommand ==
"") {
226 if (strHelp.find(
'\n') != std::string::npos)
227 strHelp = strHelp.substr(0, strHelp.find(
'\n'));
230 if (!category.empty())
233 strRet +=
"== " +
Capitalize(category) +
" ==\n";
236 strRet += strHelp +
"\n";
240 strRet =
strprintf(
"help: unknown command: %s\n", strCommand);
241 strRet = strRet.substr(0, strRet.size() - 1);
248 throw std::runtime_error(
249 "help ( \"command\" )\n"
250 "\nList all commands, or get help for a specified command.\n"
252 "1. \"command\" (string, optional) The command to get help on\n"
254 "\"text\" (string) The help text\n");
256 std::string strCommand;
270 throw std::runtime_error(
272 "\nStop PIVX server.");
279 return "PIVX server stopping";
291 {
"control",
"help", &
help,
true, {
"command"} },
292 {
"control",
"stop", &
stop,
true, {
"wait"} },
298 for (vcidx = 0; vcidx < (
sizeof(vRPCCommands) /
sizeof(vRPCCommands[0])); vcidx++) {
301 pcmd = &vRPCCommands[vcidx];
308 std::map<std::string, const CRPCCommand*>::const_iterator it =
mapCommands.find(
name);
320 std::map<std::string, const CRPCCommand*>::const_iterator it =
mapCommands.find(
name);
331 g_rpc_running =
true;
332 g_rpcSignals.Started();
340 g_rpc_running =
false;
346 deadlineTimers.clear();
348 g_rpcSignals.Stopped();
353 return g_rpc_running;
359 rpcWarmupStatus = newStatus;
365 assert(fRPCInWarmup);
366 fRPCInWarmup =
false;
373 *outStatus = rpcWarmupStatus;
391 if (!valMethod.
isStr())
401 else if (valParams.
isNull())
409 const std::vector<std::string> enabled_methods =
gArgs.
GetArgs(
"-deprecatedrpc");
411 return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end();
424 }
catch (
const UniValue& objError) {
426 }
catch (
const std::exception& e) {
437 for (
unsigned int reqIdx = 0; reqIdx < vReq.
size(); reqIdx++)
438 ret.
push_back(JSONRPCExecOne(vReq[reqIdx]));
440 return ret.
write() +
"\n";
455 std::unordered_map<std::string, const UniValue*> argsIn;
456 for (
size_t i=0; i<keys.size(); ++i) {
457 argsIn[keys[i]] = &values[i];
461 for (
const std::string &argNamePattern: argNames) {
462 std::vector<std::string> vargNames;
463 boost::algorithm::split(vargNames, argNamePattern, boost::algorithm::is_any_of(
"|"));
464 auto fr = argsIn.end();
465 for (
const std::string & argName : vargNames) {
466 fr = argsIn.find(argName);
467 if (fr != argsIn.end()) {
471 if (fr != argsIn.end()) {
472 for (
int i = 0; i < hole; ++i) {
486 if (!argsIn.empty()) {
496 std::string strWarmupStatus;
506 g_rpcSignals.PreCommand(*pcmd);
511 return pcmd->
actor(transformNamedArguments(request, pcmd->
argNames));
513 return pcmd->
actor(request);
515 }
catch (
const std::exception& e) {
522 std::vector<std::string> commandList;
523 for (
const auto& i :
mapCommands) commandList.emplace_back(i.first);
529 return "> pivx-cli " + methodname +
" " + args +
"\n";
534 return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
536 methodname +
"\", \"params\": [" + args +
"] }' -H 'content-type: text/plain;' http://127.0.0.1:51473/\n";
542 timerInterface = iface;
547 timerInterface = iface;
552 if (timerInterface == iface)
553 timerInterface =
nullptr;
556 void RPCRunLater(
const std::string&
name, std::function<
void(
void)> func, int64_t nSeconds)
560 deadlineTimers.erase(
name);
562 deadlineTimers.emplace(
name, std::unique_ptr<RPCTimerBase>(timerInterface->
NewTimer(func, nSeconds*1000)));
int64_t CAmount
Amount in PIV (Can be negative)
const CChainParams & Params()
Return the currently selected parameters.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
std::vector< std::string > argNames
PIVX RPC command dispatcher.
std::vector< std::string > listCommands() const
Returns a list of registered commands.
const CRPCCommand * operator[](const std::string &name) const
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
std::map< std::string, const CRPCCommand * > mapCommands
std::string help(const std::string &name, const JSONRPCRequest &helpreq) const
Note: This interface may still be subject to change.
void parse(const UniValue &valRequest)
virtual RPCTimerBase * NewTimer(std::function< void(void)> &func, int64_t millis)=0
Factory function for timers.
virtual const char * Name()=0
Implementation name.
const std::string & get_str() const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const UniValue & get_obj() const
const std::string & getValStr() const
const std::vector< UniValue > & getValues() const
const std::vector< std::string > & getKeys() const
bool push_back(const UniValue &val)
#define LogPrint(category,...)
void OnPreCommand(std::function< void(const CRPCCommand &)> slot)
void OnStarted(std::function< void()> slot)
void OnStopped(std::function< void()> slot)
UniValue JSONRPCError(int code, const std::string &message)
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
@ RPC_MISC_ERROR
General application defined errors.
@ RPC_TYPE_ERROR
Server is in safe mode, and command is not allowed in safe mode.
@ RPC_INVALID_PARAMETER
Ran out of memory during operation.
@ RPC_IN_WARMUP
Transaction already in chain.
@ RPC_INVALID_REQUEST
Standard JSON-RPC 2.0 errors.
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set factory function for timers, but only if unset.
bool IsDeprecatedRPCEnabled(const std::string &method)
void SetRPCWarmupFinished()
std::vector< unsigned char > ParseHexV(const UniValue &v, std::string strName)
UniValue stop(const JSONRPCRequest &jsonRequest)
void RPCTypeCheckArgument(const UniValue &value, const UniValueType &typeExpected)
Type-check one argument; throws JSONRPCError if wrong type given.
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
bool RPCIsInWarmup(std::string *outStatus)
bool ParseBool(const UniValue &o, std::string strKey)
UniValue ValueFromAmount(const CAmount &amount)
bool IsRPCRunning()
Query whether RPC is running.
void RPCRunLater(const std::string &name, std::function< void(void)> func, int64_t nSeconds)
Run func nSeconds from now.
std::string JSONRPCExecBatch(const UniValue &vReq)
int ParseInt(const UniValue &o, std::string strKey)
std::string HelpExampleCli(std::string methodname, std::string args)
void RPCTypeCheck(const UniValue ¶ms, const std::list< UniValue::VType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
CAmount AmountFromValue(const UniValue &value)
UniValue help(const JSONRPCRequest &jsonRequest)
uint256 ParseHashO(const UniValue &o, std::string strKey)
double ParseDoubleV(const UniValue &v, const std::string &strName)
std::vector< unsigned char > ParseHexO(const UniValue &o, std::string strKey)
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded Values (throws error if not hex).
std::string HelpExampleRpc(std::string methodname, std::string args)
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Check for expected keys/value types in an Object.
void SetRPCWarmupStatus(const std::string &newStatus)
Set the RPC warmup status.
void RPCSetTimerInterface(RPCTimerInterface *iface)
Set factory function for timers.
UniValue(* rpcfn_type)(const JSONRPCRequest &jsonRequest)
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
uint256 uint256S(const char *str)
const UniValue & find_value(const UniValue &obj, const std::string &name)
const char * uvTypeName(UniValue::VType t)
const UniValue NullUniValue
std::string Capitalize(std::string str)
Capitalizes the first character of the given string.
std::vector< unsigned char > ParseHex(const char *psz)
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
bool IsHex(const std::string &str)
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
bool ParseDouble(const std::string &str, double *out)
Convert string to double with strict parse error feedback.
void MilliSleep(int64_t n)