6#include <bitcoin-build-config.h>
22#include <validation.h>
28#include <unordered_map>
59 std::list<RPCCommandExecutionInfo>::iterator
it;
76 std::set<intptr_t> setDone;
77 std::vector<std::pair<std::string, const CRPCCommand*> > vCommands;
81 vCommands.emplace_back(entry.second.front()->category + entry.first, entry.second.front());
82 sort(vCommands.begin(), vCommands.end());
88 for (
const std::pair<std::string, const CRPCCommand*>&
command : vCommands)
91 std::string strMethod = pcmd->
name;
92 if ((strCommand !=
"" || pcmd->
category ==
"hidden") && strMethod != strCommand)
98 if (setDone.insert(pcmd->
unique_id).second)
99 pcmd->
actor(jreq, unused_result,
true);
101 catch (
const std::exception& e)
104 std::string strHelp = std::string(e.what());
105 if (strCommand ==
"")
107 if (strHelp.find(
'\n') != std::string::npos)
108 strHelp = strHelp.substr(0, strHelp.find(
'\n'));
112 if (!category.empty())
115 strRet +=
"== " +
Capitalize(category) +
" ==\n";
118 strRet += strHelp +
"\n";
122 strRet =
strprintf(
"help: unknown command: %s\n", strCommand);
123 strRet = strRet.substr(0,strRet.size()-1);
130 "\nList all commands, or get help for a specified command.\n",
141 std::string strCommand;
142 if (jsonRequest.params.size() > 0) {
143 strCommand = jsonRequest.params[0].
get_str();
145 if (strCommand ==
"dump_all_command_conversions") {
157 static const std::string RESULT{CLIENT_NAME
" stopping"};
162 "\nRequest a graceful shutdown of " CLIENT_NAME
".",
173 if (jsonRequest.params[0].isNum()) {
184 "\nReturns the total uptime of the server.\n",
203 "\nReturns details of the RPC server.\n",
229 entry.
pushKV(
"duration", int64_t{Ticks<std::chrono::microseconds>(SteadyClock::now() - info.
start)});
230 active_commands.
push_back(std::move(entry));
234 result.
pushKV(
"active_commands", std::move(active_commands));
238 result.
pushKV(
"logpath", std::move(log_path));
271 auto new_end = std::remove(it->second.begin(), it->second.end(), pcmd);
272 if (it->second.end() != new_end) {
273 it->second.erase(new_end, it->second.end());
288 static std::once_flag g_rpc_interrupt_flag;
290 std::call_once(g_rpc_interrupt_flag, []() {
299 static std::once_flag g_rpc_stop_flag;
302 std::call_once(g_rpc_stop_flag, [&]() {
323 rpcWarmupStatus = newStatus;
330 fRPCInWarmup =
false;
337 *outStatus = rpcWarmupStatus;
343 const std::vector<std::string> enabled_methods =
gArgs.
GetArgs(
"-deprecatedrpc");
345 return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end();
356 }
catch (
const std::exception& e) {
378 std::unordered_map<std::string, const UniValue*> argsIn;
379 for (
size_t i=0; i<keys.size(); ++i) {
380 auto [
_, inserted] = argsIn.emplace(keys[i], &
values[i]);
394 int initial_hole_size = 0;
395 const std::string* initial_param =
nullptr;
397 for (
const auto& [argNamePattern, named_only]: argNames) {
398 std::vector<std::string> vargNames =
SplitString(argNamePattern,
'|');
399 auto fr = argsIn.end();
400 for (
const std::string & argName : vargNames) {
401 fr = argsIn.find(argName);
402 if (fr != argsIn.end()) {
411 if (fr != argsIn.end()) {
412 if (options.exists(fr->first)) {
415 options.pushKVEnd(fr->first, *fr->second);
421 if (!options.empty() || fr != argsIn.end()) {
422 for (
int i = 0; i < hole; ++i) {
429 if (!initial_param) initial_param = &argNamePattern;
432 if (
out.params.empty()) initial_hole_size = hole;
438 if (fr != argsIn.end()) {
439 if (!options.empty()) {
442 out.params.push_back(*fr->second);
445 if (!options.empty()) {
446 out.params.push_back(std::move(options));
454 auto positional_args{argsIn.extract(
"args")};
455 if (positional_args && positional_args.mapped()->isArray()) {
456 if (initial_hole_size < (
int)positional_args.mapped()->size() && initial_param) {
461 out.params = *positional_args.mapped();
462 for (
size_t i{
out.params.size()}; i < named_args.size(); ++i) {
463 out.params.push_back(named_args[i]);
467 if (!argsIn.empty()) {
476 for (
const auto&
command : commands) {
512 return command.actor(request, result, last_handler);
516 }
catch (
const std::exception& e) {
523 std::vector<std::string> commandList;
525 for (
const auto& i :
mapCommands) commandList.emplace_back(i.first);
563void RPCRunLater(
const std::string&
name, std::function<
void()> func, int64_t nSeconds)
568 deadlineTimers.erase(
name);
#define CHECK_NONFATAL(condition)
Identity function.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
std::map< std::string, std::vector< const CRPCCommand * > > mapCommands
bool removeCommand(const std::string &name, const CRPCCommand *pcmd)
std::vector< std::string > listCommands() const
Returns a list of registered commands.
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
std::string help(const std::string &name, const JSONRPCRequest &helpreq) const
UniValue dumpArgMap(const JSONRPCRequest &request) const
Return all named arguments that need to be converted by the client from string to another JSON type.
Different type to mark Mutex at global scope.
JSONRPCVersion m_json_version
enum JSONRPCRequest::Mode mode
std::optional< UniValue > id
virtual RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis)=0
Factory function for timers.
virtual const char * Name()=0
Implementation name.
void push_back(UniValue val)
const std::string & get_str() const
const std::vector< UniValue > & getValues() const
const std::vector< std::string > & getKeys() const
void pushKV(std::string key, UniValue val)
std::string utf8string() const
Return a UTF-8 representation of the path as a std::string, for compatibility with code using std::st...
BCLog::Logger & LogInstance()
#define LogDebug(category,...)
std::vector< std::string > SplitString(std::string_view str, char sep)
UniValue JSONRPCError(int code, const std::string &message)
UniValue JSONRPCReplyObj(UniValue result, UniValue error, std::optional< UniValue > id, JSONRPCVersion jsonrpc_version)
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
@ RPC_MISC_ERROR
General application defined errors.
@ RPC_TYPE_ERROR
Unexpected type was passed as parameter.
@ RPC_CLIENT_NOT_CONNECTED
P2P client errors.
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
@ RPC_IN_WARMUP
Client still warming up.
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
bool IsDeprecatedRPCEnabled(const std::string &method)
void SetRPCWarmupFinished()
static RPCHelpMan uptime()
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
static RPCHelpMan getrpcinfo()
void RPCRunLater(const std::string &name, std::function< void()> func, int64_t nSeconds)
Run func nSeconds from now.
static bool ExecuteCommands(const std::vector< const CRPCCommand * > &commands, const JSONRPCRequest &request, UniValue &result)
bool RPCIsInWarmup(std::string *outStatus)
static RPCTimerInterface * timerInterface
static bool ExecuteCommand(const CRPCCommand &command, const JSONRPCRequest &request, UniValue &result, bool last_handler)
static std::atomic< bool > g_rpc_running
static JSONRPCRequest transformNamedArguments(const JSONRPCRequest &in, const std::vector< std::pair< std::string, bool > > &argNames)
Process named arguments into a vector of positional arguments, based on the passed-in specification f...
static GlobalMutex g_deadline_timers_mutex
bool IsRPCRunning()
Query whether RPC is running.
UniValue JSONRPCExec(const JSONRPCRequest &jreq, bool catch_errors)
static bool fRPCInWarmup GUARDED_BY(g_rpc_warmup_mutex)
static GlobalMutex g_rpc_warmup_mutex
static RPCServerInfo g_rpc_server_info
static const CRPCCommand vRPCCommands[]
void SetRPCWarmupStatus(const std::string &newStatus)
Set the RPC warmup status.
void RPCSetTimerInterface(RPCTimerInterface *iface)
Set the factory function for timers.
void RpcInterruptionPoint()
Throw JSONRPCError if RPC is not running.
NodeContext & EnsureAnyNodeContext(const std::any &context)
std::string DefaultHint
Hint for default value.
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
bool hidden
For testing only.
RPCCommandExecution(const std::string &method)
std::list< RPCCommandExecutionInfo >::iterator it
SteadyClock::time_point start
@ ANY
Special type to disable type checks (for testing only)
std::list< RPCCommandExecutionInfo > active_commands GUARDED_BY(mutex)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void UninterruptibleSleep(const std::chrono::microseconds &n)
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
bilingual_str _(ConstevalStringLiteral str)
Translation function.
const UniValue NullUniValue
std::string Capitalize(std::string str)
Capitalizes the first character of the given string.