Bitcoin Core  24.1.0
P2P Digital Currency
server.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2021 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <rpc/server.h>
7 
8 #include <rpc/util.h>
9 #include <shutdown.h>
10 #include <sync.h>
11 #include <util/strencodings.h>
12 #include <util/string.h>
13 #include <util/system.h>
14 #include <util/time.h>
15 
16 #include <boost/signals2/signal.hpp>
17 
18 #include <cassert>
19 #include <chrono>
20 #include <memory>
21 #include <mutex>
22 #include <unordered_map>
23 
25 static std::atomic<bool> g_rpc_running{false};
26 static bool fRPCInWarmup GUARDED_BY(g_rpc_warmup_mutex) = true;
27 static std::string rpcWarmupStatus GUARDED_BY(g_rpc_warmup_mutex) = "RPC server started";
28 /* Timer-creating functions */
30 /* Map of name to timer. */
32 static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers GUARDED_BY(g_deadline_timers_mutex);
33 static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler);
34 
36 {
37  std::string method;
38  SteadyClock::time_point start;
39 };
40 
42 {
44  std::list<RPCCommandExecutionInfo> active_commands GUARDED_BY(mutex);
45 };
46 
48 
50 {
51  std::list<RPCCommandExecutionInfo>::iterator it;
52  explicit RPCCommandExecution(const std::string& method)
53  {
55  it = g_rpc_server_info.active_commands.insert(g_rpc_server_info.active_commands.end(), {method, SteadyClock::now()});
56  }
58  {
60  g_rpc_server_info.active_commands.erase(it);
61  }
62 };
63 
64 static struct CRPCSignals
65 {
66  boost::signals2::signal<void ()> Started;
67  boost::signals2::signal<void ()> Stopped;
68 } g_rpcSignals;
69 
70 void RPCServer::OnStarted(std::function<void ()> slot)
71 {
72  g_rpcSignals.Started.connect(slot);
73 }
74 
75 void RPCServer::OnStopped(std::function<void ()> slot)
76 {
77  g_rpcSignals.Stopped.connect(slot);
78 }
79 
80 std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const
81 {
82  std::string strRet;
83  std::string category;
84  std::set<intptr_t> setDone;
85  std::vector<std::pair<std::string, const CRPCCommand*> > vCommands;
86 
87  for (const auto& entry : mapCommands)
88  vCommands.push_back(make_pair(entry.second.front()->category + entry.first, entry.second.front()));
89  sort(vCommands.begin(), vCommands.end());
90 
91  JSONRPCRequest jreq = helpreq;
93  jreq.params = UniValue();
94 
95  for (const std::pair<std::string, const CRPCCommand*>& command : vCommands)
96  {
97  const CRPCCommand *pcmd = command.second;
98  std::string strMethod = pcmd->name;
99  if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand)
100  continue;
101  jreq.strMethod = strMethod;
102  try
103  {
104  UniValue unused_result;
105  if (setDone.insert(pcmd->unique_id).second)
106  pcmd->actor(jreq, unused_result, true /* last_handler */);
107  }
108  catch (const std::exception& e)
109  {
110  // Help text is returned in an exception
111  std::string strHelp = std::string(e.what());
112  if (strCommand == "")
113  {
114  if (strHelp.find('\n') != std::string::npos)
115  strHelp = strHelp.substr(0, strHelp.find('\n'));
116 
117  if (category != pcmd->category)
118  {
119  if (!category.empty())
120  strRet += "\n";
121  category = pcmd->category;
122  strRet += "== " + Capitalize(category) + " ==\n";
123  }
124  }
125  strRet += strHelp + "\n";
126  }
127  }
128  if (strRet == "")
129  strRet = strprintf("help: unknown command: %s\n", strCommand);
130  strRet = strRet.substr(0,strRet.size()-1);
131  return strRet;
132 }
133 
134 static RPCHelpMan help()
135 {
136  return RPCHelpMan{"help",
137  "\nList all commands, or get help for a specified command.\n",
138  {
139  {"command", RPCArg::Type::STR, RPCArg::DefaultHint{"all commands"}, "The command to get help on"},
140  },
141  {
142  RPCResult{RPCResult::Type::STR, "", "The help text"},
144  },
145  RPCExamples{""},
146  [&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue
147 {
148  std::string strCommand;
149  if (jsonRequest.params.size() > 0) {
150  strCommand = jsonRequest.params[0].get_str();
151  }
152  if (strCommand == "dump_all_command_conversions") {
153  // Used for testing only, undocumented
154  return tableRPC.dumpArgMap(jsonRequest);
155  }
156 
157  return tableRPC.help(strCommand, jsonRequest);
158 },
159  };
160 }
161 
162 static RPCHelpMan stop()
163 {
164  static const std::string RESULT{PACKAGE_NAME " stopping"};
165  return RPCHelpMan{"stop",
166  // Also accept the hidden 'wait' integer argument (milliseconds)
167  // For instance, 'stop 1000' makes the call wait 1 second before returning
168  // to the client (intended for testing)
169  "\nRequest a graceful shutdown of " PACKAGE_NAME ".",
170  {
171  {"wait", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "how long to wait in ms", "", {}, /*hidden=*/true},
172  },
173  RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"},
174  RPCExamples{""},
175  [&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue
176 {
177  // Event loop will exit after current HTTP requests have been handled, so
178  // this reply will get back to the client.
179  StartShutdown();
180  if (jsonRequest.params[0].isNum()) {
181  UninterruptibleSleep(std::chrono::milliseconds{jsonRequest.params[0].getInt<int>()});
182  }
183  return RESULT;
184 },
185  };
186 }
187 
189 {
190  return RPCHelpMan{"uptime",
191  "\nReturns the total uptime of the server.\n",
192  {},
193  RPCResult{
194  RPCResult::Type::NUM, "", "The number of seconds that the server has been running"
195  },
196  RPCExamples{
197  HelpExampleCli("uptime", "")
198  + HelpExampleRpc("uptime", "")
199  },
200  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
201 {
202  return GetTime() - GetStartupTime();
203 }
204  };
205 }
206 
208 {
209  return RPCHelpMan{"getrpcinfo",
210  "\nReturns details of the RPC server.\n",
211  {},
212  RPCResult{
213  RPCResult::Type::OBJ, "", "",
214  {
215  {RPCResult::Type::ARR, "active_commands", "All active commands",
216  {
217  {RPCResult::Type::OBJ, "", "Information about an active command",
218  {
219  {RPCResult::Type::STR, "method", "The name of the RPC command"},
220  {RPCResult::Type::NUM, "duration", "The running time in microseconds"},
221  }},
222  }},
223  {RPCResult::Type::STR, "logpath", "The complete file path to the debug log"},
224  }
225  },
226  RPCExamples{
227  HelpExampleCli("getrpcinfo", "")
228  + HelpExampleRpc("getrpcinfo", "")},
229  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
230 {
232  UniValue active_commands(UniValue::VARR);
233  for (const RPCCommandExecutionInfo& info : g_rpc_server_info.active_commands) {
234  UniValue entry(UniValue::VOBJ);
235  entry.pushKV("method", info.method);
236  entry.pushKV("duration", int64_t{Ticks<std::chrono::microseconds>(SteadyClock::now() - info.start)});
237  active_commands.push_back(entry);
238  }
239 
240  UniValue result(UniValue::VOBJ);
241  result.pushKV("active_commands", active_commands);
242 
243  const std::string path = LogInstance().m_file_path.u8string();
244  UniValue log_path(UniValue::VSTR, path);
245  result.pushKV("logpath", log_path);
246 
247  return result;
248 }
249  };
250 }
251 
252 static const CRPCCommand vRPCCommands[]{
253  /* Overall control/query calls */
254  {"control", &getrpcinfo},
255  {"control", &help},
256  {"control", &stop},
257  {"control", &uptime},
258 };
259 
261 {
262  for (const auto& c : vRPCCommands) {
263  appendCommand(c.name, &c);
264  }
265 }
266 
267 void CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd)
268 {
269  CHECK_NONFATAL(!IsRPCRunning()); // Only add commands before rpc is running
270 
271  mapCommands[name].push_back(pcmd);
272 }
273 
274 bool CRPCTable::removeCommand(const std::string& name, const CRPCCommand* pcmd)
275 {
276  auto it = mapCommands.find(name);
277  if (it != mapCommands.end()) {
278  auto new_end = std::remove(it->second.begin(), it->second.end(), pcmd);
279  if (it->second.end() != new_end) {
280  it->second.erase(new_end, it->second.end());
281  return true;
282  }
283  }
284  return false;
285 }
286 
287 void StartRPC()
288 {
289  LogPrint(BCLog::RPC, "Starting RPC\n");
290  g_rpc_running = true;
292 }
293 
295 {
296  static std::once_flag g_rpc_interrupt_flag;
297  // This function could be called twice if the GUI has been started with -server=1.
298  std::call_once(g_rpc_interrupt_flag, []() {
299  LogPrint(BCLog::RPC, "Interrupting RPC\n");
300  // Interrupt e.g. running longpolls
301  g_rpc_running = false;
302  });
303 }
304 
305 void StopRPC()
306 {
307  static std::once_flag g_rpc_stop_flag;
308  // This function could be called twice if the GUI has been started with -server=1.
310  std::call_once(g_rpc_stop_flag, []() {
311  LogPrint(BCLog::RPC, "Stopping RPC\n");
312  WITH_LOCK(g_deadline_timers_mutex, deadlineTimers.clear());
315  });
316 }
317 
319 {
320  return g_rpc_running;
321 }
322 
324 {
325  if (!IsRPCRunning()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
326 }
327 
328 void SetRPCWarmupStatus(const std::string& newStatus)
329 {
331  rpcWarmupStatus = newStatus;
332 }
333 
335 {
337  assert(fRPCInWarmup);
338  fRPCInWarmup = false;
339 }
340 
341 bool RPCIsInWarmup(std::string *outStatus)
342 {
344  if (outStatus)
345  *outStatus = rpcWarmupStatus;
346  return fRPCInWarmup;
347 }
348 
349 bool IsDeprecatedRPCEnabled(const std::string& method)
350 {
351  const std::vector<std::string> enabled_methods = gArgs.GetArgs("-deprecatedrpc");
352 
353  return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end();
354 }
355 
357 {
358  UniValue rpc_result(UniValue::VOBJ);
359 
360  try {
361  jreq.parse(req);
362 
363  UniValue result = tableRPC.execute(jreq);
364  rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
365  }
366  catch (const UniValue& objError)
367  {
368  rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
369  }
370  catch (const std::exception& e)
371  {
372  rpc_result = JSONRPCReplyObj(NullUniValue,
373  JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
374  }
375 
376  return rpc_result;
377 }
378 
379 std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq)
380 {
382  for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
383  ret.push_back(JSONRPCExecOne(jreq, vReq[reqIdx]));
384 
385  return ret.write() + "\n";
386 }
387 
392 static inline JSONRPCRequest transformNamedArguments(const JSONRPCRequest& in, const std::vector<std::string>& argNames)
393 {
394  JSONRPCRequest out = in;
396  // Build a map of parameters, and remove ones that have been processed, so that we can throw a focused error if
397  // there is an unknown one.
398  const std::vector<std::string>& keys = in.params.getKeys();
399  const std::vector<UniValue>& values = in.params.getValues();
400  std::unordered_map<std::string, const UniValue*> argsIn;
401  for (size_t i=0; i<keys.size(); ++i) {
402  argsIn[keys[i]] = &values[i];
403  }
404  // Process expected parameters.
405  int hole = 0;
406  for (const std::string &argNamePattern: argNames) {
407  std::vector<std::string> vargNames = SplitString(argNamePattern, '|');
408  auto fr = argsIn.end();
409  for (const std::string & argName : vargNames) {
410  fr = argsIn.find(argName);
411  if (fr != argsIn.end()) {
412  break;
413  }
414  }
415  if (fr != argsIn.end()) {
416  for (int i = 0; i < hole; ++i) {
417  // Fill hole between specified parameters with JSON nulls,
418  // but not at the end (for backwards compatibility with calls
419  // that act based on number of specified parameters).
420  out.params.push_back(UniValue());
421  }
422  hole = 0;
423  out.params.push_back(*fr->second);
424  argsIn.erase(fr);
425  } else {
426  hole += 1;
427  }
428  }
429  // If there are still arguments in the argsIn map, this is an error.
430  if (!argsIn.empty()) {
431  throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown named parameter " + argsIn.begin()->first);
432  }
433  // Return request with named arguments transformed to positional arguments
434  return out;
435 }
436 
437 static bool ExecuteCommands(const std::vector<const CRPCCommand*>& commands, const JSONRPCRequest& request, UniValue& result)
438 {
439  for (const auto& command : commands) {
440  if (ExecuteCommand(*command, request, result, &command == &commands.back())) {
441  return true;
442  }
443  }
444  return false;
445 }
446 
448 {
449  // Return immediately if in warmup
450  {
452  if (fRPCInWarmup)
453  throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
454  }
455 
456  // Find method
457  auto it = mapCommands.find(request.strMethod);
458  if (it != mapCommands.end()) {
459  UniValue result;
460  if (ExecuteCommands(it->second, request, result)) {
461  return result;
462  }
463  }
464  throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
465 }
466 
467 static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler)
468 {
469  try
470  {
471  RPCCommandExecution execution(request.strMethod);
472  // Execute, convert arguments to array if necessary
473  if (request.params.isObject()) {
474  return command.actor(transformNamedArguments(request, command.argNames), result, last_handler);
475  } else {
476  return command.actor(request, result, last_handler);
477  }
478  }
479  catch (const std::exception& e)
480  {
481  throw JSONRPCError(RPC_MISC_ERROR, e.what());
482  }
483 }
484 
485 std::vector<std::string> CRPCTable::listCommands() const
486 {
487  std::vector<std::string> commandList;
488  for (const auto& i : mapCommands) commandList.emplace_back(i.first);
489  return commandList;
490 }
491 
493 {
494  JSONRPCRequest request = args_request;
495  request.mode = JSONRPCRequest::GET_ARGS;
496 
498  for (const auto& cmd : mapCommands) {
499  UniValue result;
500  if (ExecuteCommands(cmd.second, request, result)) {
501  for (const auto& values : result.getValues()) {
502  ret.push_back(values);
503  }
504  }
505  }
506  return ret;
507 }
508 
510 {
511  if (!timerInterface)
512  timerInterface = iface;
513 }
514 
516 {
517  timerInterface = iface;
518 }
519 
521 {
522  if (timerInterface == iface)
523  timerInterface = nullptr;
524 }
525 
526 void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds)
527 {
528  if (!timerInterface)
529  throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
531  deadlineTimers.erase(name);
532  LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
533  deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
534 }
535 
537 {
538  int flag = 0;
539  if (gArgs.GetIntArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0)
541  return flag;
542 }
543 
bool isObject() const
Definition: univalue.h:81
void push_back(UniValue val)
Definition: univalue.cpp:104
int ret
RPC timer "driver".
Definition: server.h:59
static const int SERIALIZE_TRANSACTION_NO_WITNESS
A flag that is ORed into the protocol version to designate that a transaction should be (un)serialize...
Definition: transaction.h:31
ArgsManager gArgs
Definition: system.cpp:86
std::string help(const std::string &name, const JSONRPCRequest &helpreq) const
Definition: server.cpp:80
std::string category
Definition: server.h:115
const std::vector< UniValue > & getValues() const
static JSONRPCRequest transformNamedArguments(const JSONRPCRequest &in, const std::vector< std::string > &argNames)
Process named arguments into a vector of positional arguments, based on the passed-in specification f...
Definition: server.cpp:392
BCLog::Logger & LogInstance()
Definition: logging.cpp:20
static GlobalMutex g_deadline_timers_mutex
Definition: server.cpp:31
RPC command dispatcher.
Definition: server.h:125
#define LogPrint(category,...)
Definition: logging.h:243
assert(!tx.IsCoinBase())
bool IsRPCRunning()
Query whether RPC is running.
Definition: server.cpp:318
void SetRPCWarmupStatus(const std::string &newStatus)
Set the RPC warmup status.
Definition: server.cpp:328
static const unsigned int DEFAULT_RPC_SERIALIZE_VERSION
Definition: server.h:19
Actor actor
Definition: server.h:117
fs::path m_file_path
Definition: logging.h:121
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
static bool ExecuteCommands(const std::vector< const CRPCCommand *> &commands, const JSONRPCRequest &request, UniValue &result)
Definition: server.cpp:437
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:267
static bool fRPCInWarmup GUARDED_BY(g_rpc_warmup_mutex)
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:47
static std::atomic< bool > g_rpc_running
Definition: server.cpp:25
void OnStopped(std::function< void()> slot)
Definition: server.cpp:75
static GlobalMutex g_rpc_warmup_mutex
Definition: server.cpp:24
bool removeCommand(const std::string &name, const CRPCCommand *pcmd)
Definition: server.cpp:274
const auto cmd
#define PACKAGE_NAME
void InterruptRPC()
Definition: server.cpp:294
const std::string & get_str() const
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
const std::vector< std::string > & getKeys() const
static const CRPCCommand vRPCCommands[]
Definition: server.cpp:252
void RPCRunLater(const std::string &name, std::function< void()> func, int64_t nSeconds)
Run func nSeconds from now.
Definition: server.cpp:526
std::vector< std::string > SplitString(std::string_view str, char sep)
Definition: string.h:21
Client still warming up.
Definition: protocol.h:49
std::string method
Definition: server.cpp:37
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
static RPCServerInfo g_rpc_server_info
Definition: server.cpp:47
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
Definition: server.cpp:520
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
Definition: request.cpp:129
int64_t GetStartupTime()
Definition: system.cpp:1419
static bool ExecuteCommand(const CRPCCommand &command, const JSONRPCRequest &request, UniValue &result, bool last_handler)
Definition: server.cpp:467
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
Definition: server.cpp:447
boost::signals2::signal< void()> Stopped
Definition: server.cpp:67
std::string strMethod
Definition: request.h:32
void SetRPCWarmupFinished()
Definition: server.cpp:334
std::string name
Definition: server.h:116
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:184
CRPCTable tableRPC
Definition: server.cpp:544
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:56
Mutex mutex
Definition: server.cpp:43
UniValue params
Definition: request.h:33
#define LOCK(cs)
Definition: sync.h:261
const char * name
Definition: rest.cpp:46
enum JSONRPCRequest::Mode mode
static RPCTimerInterface * timerInterface
Definition: server.cpp:29
boost::signals2::signal< void()> Started
Definition: server.cpp:66
std::string JSONRPCExecBatch(const JSONRPCRequest &jreq, const UniValue &vReq)
Definition: server.cpp:379
UniValue id
Definition: request.h:31
Special type to disable type checks (for testing only)
General application defined errors.
Definition: protocol.h:39
std::string DefaultHint
Definition: util.h:169
RPCCommandExecution(const std::string &method)
Definition: server.cpp:52
void StartRPC()
Definition: server.cpp:287
static RPCHelpMan stop()
Definition: server.cpp:162
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:166
bool IsDeprecatedRPCEnabled(const std::string &method)
Definition: server.cpp:349
static UniValue JSONRPCExecOne(JSONRPCRequest jreq, const UniValue &req)
Definition: server.cpp:356
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:305
static struct CRPCSignals g_rpcSignals
Optional arg that is a named argument and has a default value of null.
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
Definition: server.cpp:509
virtual RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis)=0
Factory function for timers.
void parse(const UniValue &valRequest)
Definition: request.cpp:158
void StopRPC()
Definition: server.cpp:305
const auto command
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:25
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
int RPCSerializationFlags()
Definition: server.cpp:536
void RpcInterruptionPoint()
Throw JSONRPCError if RPC is not running.
Definition: server.cpp:323
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: system.cpp:629
static RPCHelpMan getrpcinfo()
Definition: server.cpp:207
void RPCSetTimerInterface(RPCTimerInterface *iface)
Set the factory function for timers.
Definition: server.cpp:515
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:38
std::list< RPCCommandExecutionInfo >::iterator it
Definition: server.cpp:51
std::string u8string() const
Definition: fs.h:55
bool RPCIsInWarmup(std::string *outStatus)
Definition: server.cpp:341
const UniValue NullUniValue
Definition: univalue.cpp:16
void StartShutdown()
Request shutdown of the application.
Definition: shutdown.cpp:58
virtual const char * Name()=0
Implementation name.
void OnStarted(std::function< void()> slot)
Definition: server.cpp:70
std::map< std::string, std::vector< const CRPCCommand * > > mapCommands
Definition: server.h:128
size_t size() const
Definition: univalue.h:65
Different type to mark Mutex at global scope.
Definition: sync.h:141
std::list< RPCCommandExecutionInfo > active_commands GUARDED_BY(mutex)
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: system.cpp:491
SteadyClock::time_point start
Definition: server.cpp:38
intptr_t unique_id
Definition: server.h:119
int64_t GetTime()
DEPRECATED, see GetTime.
Definition: time.cpp:117
std::vector< std::string > listCommands() const
Returns a list of registered commands.
Definition: server.cpp:485
P2P client errors.
Definition: protocol.h:58
UniValue dumpArgMap(const JSONRPCRequest &request) const
Return all named arguments that need to be converted by the client from string to another JSON type...
Definition: server.cpp:492
static RPCHelpMan help()
Definition: server.cpp:134
CRPCTable()
Definition: server.cpp:260
std::string Capitalize(std::string str)
Capitalizes the first character of the given string.
static RPCHelpMan uptime()
Definition: server.cpp:188