]> Git Repo - VerusCoin.git/blob - src/rpcserver.cpp
Auto merge of #2213 - daira:2211.release-1.0.8, r=daira
[VerusCoin.git] / src / rpcserver.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 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 "rpcserver.h"
7
8 #include "base58.h"
9 #include "init.h"
10 #include "random.h"
11 #include "sync.h"
12 #include "ui_interface.h"
13 #include "util.h"
14 #include "utilstrencodings.h"
15 #include "asyncrpcqueue.h"
16
17 #include <memory>
18
19 #include <univalue.h>
20
21 #include <boost/bind.hpp>
22 #include <boost/filesystem.hpp>
23 #include <boost/foreach.hpp>
24 #include <boost/iostreams/concepts.hpp>
25 #include <boost/iostreams/stream.hpp>
26 #include <boost/shared_ptr.hpp>
27 #include <boost/signals2/signal.hpp>
28 #include <boost/thread.hpp>
29 #include <boost/algorithm/string/case_conv.hpp> // for to_upper()
30
31 using namespace RPCServer;
32 using namespace std;
33
34 static bool fRPCRunning = false;
35 static bool fRPCInWarmup = true;
36 static std::string rpcWarmupStatus("RPC server started");
37 static CCriticalSection cs_rpcWarmup;
38 /* Timer-creating functions */
39 static std::vector<RPCTimerInterface*> timerInterfaces;
40 /* Map of name to timer.
41  * @note Can be changed to std::unique_ptr when C++11 */
42 static std::map<std::string, boost::shared_ptr<RPCTimerBase> > deadlineTimers;
43
44 static struct CRPCSignals
45 {
46     boost::signals2::signal<void ()> Started;
47     boost::signals2::signal<void ()> Stopped;
48     boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
49     boost::signals2::signal<void (const CRPCCommand&)> PostCommand;
50 } g_rpcSignals;
51
52 void RPCServer::OnStarted(boost::function<void ()> slot)
53 {
54     g_rpcSignals.Started.connect(slot);
55 }
56
57 void RPCServer::OnStopped(boost::function<void ()> slot)
58 {
59     g_rpcSignals.Stopped.connect(slot);
60 }
61
62 void RPCServer::OnPreCommand(boost::function<void (const CRPCCommand&)> slot)
63 {
64     g_rpcSignals.PreCommand.connect(boost::bind(slot, _1));
65 }
66
67 void RPCServer::OnPostCommand(boost::function<void (const CRPCCommand&)> slot)
68 {
69     g_rpcSignals.PostCommand.connect(boost::bind(slot, _1));
70 }
71
72 void RPCTypeCheck(const UniValue& params,
73                   const list<UniValue::VType>& typesExpected,
74                   bool fAllowNull)
75 {
76     size_t i = 0;
77     BOOST_FOREACH(UniValue::VType t, typesExpected)
78     {
79         if (params.size() <= i)
80             break;
81
82         const UniValue& v = params[i];
83         if (!((v.type() == t) || (fAllowNull && (v.isNull()))))
84         {
85             string err = strprintf("Expected type %s, got %s",
86                                    uvTypeName(t), uvTypeName(v.type()));
87             throw JSONRPCError(RPC_TYPE_ERROR, err);
88         }
89         i++;
90     }
91 }
92
93 void RPCTypeCheckObj(const UniValue& o,
94                   const map<string, UniValue::VType>& typesExpected,
95                   bool fAllowNull)
96 {
97     BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected)
98     {
99         const UniValue& v = find_value(o, t.first);
100         if (!fAllowNull && v.isNull())
101             throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
102
103         if (!((v.type() == t.second) || (fAllowNull && (v.isNull()))))
104         {
105             string err = strprintf("Expected type %s for %s, got %s",
106                                    uvTypeName(t.second), t.first, uvTypeName(v.type()));
107             throw JSONRPCError(RPC_TYPE_ERROR, err);
108         }
109     }
110 }
111
112 CAmount AmountFromValue(const UniValue& value)
113 {
114     if (!value.isNum() && !value.isStr())
115         throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
116     CAmount amount;
117     if (!ParseFixedPoint(value.getValStr(), 8, &amount))
118         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
119     if (!MoneyRange(amount))
120         throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
121     return amount;
122 }
123
124 UniValue ValueFromAmount(const CAmount& amount)
125 {
126     bool sign = amount < 0;
127     int64_t n_abs = (sign ? -amount : amount);
128     int64_t quotient = n_abs / COIN;
129     int64_t remainder = n_abs % COIN;
130     return UniValue(UniValue::VNUM,
131             strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder));
132 }
133
134 uint256 ParseHashV(const UniValue& v, string strName)
135 {
136     string strHex;
137     if (v.isStr())
138         strHex = v.get_str();
139     if (!IsHex(strHex)) // Note: IsHex("") is false
140         throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
141     uint256 result;
142     result.SetHex(strHex);
143     return result;
144 }
145 uint256 ParseHashO(const UniValue& o, string strKey)
146 {
147     return ParseHashV(find_value(o, strKey), strKey);
148 }
149 vector<unsigned char> ParseHexV(const UniValue& v, string strName)
150 {
151     string strHex;
152     if (v.isStr())
153         strHex = v.get_str();
154     if (!IsHex(strHex))
155         throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
156     return ParseHex(strHex);
157 }
158 vector<unsigned char> ParseHexO(const UniValue& o, string strKey)
159 {
160     return ParseHexV(find_value(o, strKey), strKey);
161 }
162
163 /**
164  * Note: This interface may still be subject to change.
165  */
166
167 std::string CRPCTable::help(const std::string& strCommand) const
168 {
169     string strRet;
170     string category;
171     set<rpcfn_type> setDone;
172     vector<pair<string, const CRPCCommand*> > vCommands;
173
174     for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
175         vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second));
176     sort(vCommands.begin(), vCommands.end());
177
178     BOOST_FOREACH(const PAIRTYPE(string, const CRPCCommand*)& command, vCommands)
179     {
180         const CRPCCommand *pcmd = command.second;
181         string strMethod = pcmd->name;
182         // We already filter duplicates, but these deprecated screw up the sort order
183         if (strMethod.find("label") != string::npos)
184             continue;
185         if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand)
186             continue;
187         try
188         {
189             UniValue params;
190             rpcfn_type pfn = pcmd->actor;
191             if (setDone.insert(pfn).second)
192                 (*pfn)(params, true);
193         }
194         catch (const std::exception& e)
195         {
196             // Help text is returned in an exception
197             string strHelp = string(e.what());
198             if (strCommand == "")
199             {
200                 if (strHelp.find('\n') != string::npos)
201                     strHelp = strHelp.substr(0, strHelp.find('\n'));
202
203                 if (category != pcmd->category)
204                 {
205                     if (!category.empty())
206                         strRet += "\n";
207                     category = pcmd->category;
208                     string firstLetter = category.substr(0,1);
209                     boost::to_upper(firstLetter);
210                     strRet += "== " + firstLetter + category.substr(1) + " ==\n";
211                 }
212             }
213             strRet += strHelp + "\n";
214         }
215     }
216     if (strRet == "")
217         strRet = strprintf("help: unknown command: %s\n", strCommand);
218     strRet = strRet.substr(0,strRet.size()-1);
219     return strRet;
220 }
221
222 UniValue help(const UniValue& params, bool fHelp)
223 {
224     if (fHelp || params.size() > 1)
225         throw runtime_error(
226             "help ( \"command\" )\n"
227             "\nList all commands, or get help for a specified command.\n"
228             "\nArguments:\n"
229             "1. \"command\"     (string, optional) The command to get help on\n"
230             "\nResult:\n"
231             "\"text\"     (string) The help text\n"
232         );
233
234     string strCommand;
235     if (params.size() > 0)
236         strCommand = params[0].get_str();
237
238     return tableRPC.help(strCommand);
239 }
240
241
242 UniValue stop(const UniValue& params, bool fHelp)
243 {
244     // Accept the deprecated and ignored 'detach' boolean argument
245     if (fHelp || params.size() > 1)
246         throw runtime_error(
247             "stop\n"
248             "\nStop Zcash server.");
249     // Shutdown will take long enough that the response should get back
250     StartShutdown();
251     return "Zcash server stopping";
252 }
253
254 /**
255  * Call Table
256  */
257 static const CRPCCommand vRPCCommands[] =
258 { //  category              name                      actor (function)         okSafeMode
259   //  --------------------- ------------------------  -----------------------  ----------
260     /* Overall control/query calls */
261     { "control",            "getinfo",                &getinfo,                true  }, /* uses wallet if enabled */
262     { "control",            "help",                   &help,                   true  },
263     { "control",            "stop",                   &stop,                   true  },
264
265     /* P2P networking */
266     { "network",            "getnetworkinfo",         &getnetworkinfo,         true  },
267     { "network",            "addnode",                &addnode,                true  },
268     { "network",            "disconnectnode",         &disconnectnode,         true  },
269     { "network",            "getaddednodeinfo",       &getaddednodeinfo,       true  },
270     { "network",            "getconnectioncount",     &getconnectioncount,     true  },
271     { "network",            "getnettotals",           &getnettotals,           true  },
272     { "network",            "getpeerinfo",            &getpeerinfo,            true  },
273     { "network",            "ping",                   &ping,                   true  },
274     { "network",            "setban",                 &setban,                 true  },
275     { "network",            "listbanned",             &listbanned,             true  },
276     { "network",            "clearbanned",            &clearbanned,            true  },
277
278     /* Block chain and UTXO */
279     { "blockchain",         "getblockchaininfo",      &getblockchaininfo,      true  },
280     { "blockchain",         "getbestblockhash",       &getbestblockhash,       true  },
281     { "blockchain",         "getblockcount",          &getblockcount,          true  },
282     { "blockchain",         "getblock",               &getblock,               true  },
283     { "blockchain",         "getblockhash",           &getblockhash,           true  },
284     { "blockchain",         "getblockheader",         &getblockheader,         true  },
285     { "blockchain",         "getchaintips",           &getchaintips,           true  },
286     { "blockchain",         "getdifficulty",          &getdifficulty,          true  },
287     { "blockchain",         "getmempoolinfo",         &getmempoolinfo,         true  },
288     { "blockchain",         "getrawmempool",          &getrawmempool,          true  },
289     { "blockchain",         "gettxout",               &gettxout,               true  },
290     { "blockchain",         "gettxoutproof",          &gettxoutproof,          true  },
291     { "blockchain",         "verifytxoutproof",       &verifytxoutproof,       true  },
292     { "blockchain",         "gettxoutsetinfo",        &gettxoutsetinfo,        true  },
293     { "blockchain",         "verifychain",            &verifychain,            true  },
294
295     /* Mining */
296 #ifdef ENABLE_WALLET
297     { "mining",             "getblocktemplate",       &getblocktemplate,       true  },
298 #endif
299     { "mining",             "getmininginfo",          &getmininginfo,          true  },
300     { "mining",             "getlocalsolps",          &getlocalsolps,          true  },
301     { "mining",             "getnetworksolps",        &getnetworksolps,        true  },
302     { "mining",             "getnetworkhashps",       &getnetworkhashps,       true  },
303     { "mining",             "prioritisetransaction",  &prioritisetransaction,  true  },
304     { "mining",             "submitblock",            &submitblock,            true  },
305     { "mining",             "getblocksubsidy",        &getblocksubsidy,        true  },
306
307 #ifdef ENABLE_MINING
308     /* Coin generation */
309     { "generating",         "getgenerate",            &getgenerate,            true  },
310     { "generating",         "setgenerate",            &setgenerate,            true  },
311     { "generating",         "generate",               &generate,               true  },
312 #endif
313
314     /* Raw transactions */
315     { "rawtransactions",    "createrawtransaction",   &createrawtransaction,   true  },
316     { "rawtransactions",    "decoderawtransaction",   &decoderawtransaction,   true  },
317     { "rawtransactions",    "decodescript",           &decodescript,           true  },
318     { "rawtransactions",    "getrawtransaction",      &getrawtransaction,      true  },
319     { "rawtransactions",    "sendrawtransaction",     &sendrawtransaction,     false },
320     { "rawtransactions",    "signrawtransaction",     &signrawtransaction,     false }, /* uses wallet if enabled */
321 #ifdef ENABLE_WALLET
322     { "rawtransactions",    "fundrawtransaction",     &fundrawtransaction,     false },
323 #endif
324
325     /* Utility functions */
326     { "util",               "createmultisig",         &createmultisig,         true  },
327     { "util",               "validateaddress",        &validateaddress,        true  }, /* uses wallet if enabled */
328     { "util",               "verifymessage",          &verifymessage,          true  },
329     { "util",               "estimatefee",            &estimatefee,            true  },
330     { "util",               "estimatepriority",       &estimatepriority,       true  },
331     { "util",               "z_validateaddress",      &z_validateaddress,      true  }, /* uses wallet if enabled */
332
333     /* Not shown in help */
334     { "hidden",             "invalidateblock",        &invalidateblock,        true  },
335     { "hidden",             "reconsiderblock",        &reconsiderblock,        true  },
336     { "hidden",             "setmocktime",            &setmocktime,            true  },
337 #ifdef ENABLE_WALLET
338     { "hidden",             "resendwallettransactions", &resendwallettransactions, true},
339 #endif
340
341 #ifdef ENABLE_WALLET
342     /* Wallet */
343     { "wallet",             "addmultisigaddress",     &addmultisigaddress,     true  },
344     { "wallet",             "backupwallet",           &backupwallet,           true  },
345     { "wallet",             "dumpprivkey",            &dumpprivkey,            true  },
346     { "wallet",             "dumpwallet",             &dumpwallet,             true  },
347     { "wallet",             "encryptwallet",          &encryptwallet,          true  },
348     { "wallet",             "getaccountaddress",      &getaccountaddress,      true  },
349     { "wallet",             "getaccount",             &getaccount,             true  },
350     { "wallet",             "getaddressesbyaccount",  &getaddressesbyaccount,  true  },
351     { "wallet",             "getbalance",             &getbalance,             false },
352     { "wallet",             "getnewaddress",          &getnewaddress,          true  },
353     { "wallet",             "getrawchangeaddress",    &getrawchangeaddress,    true  },
354     { "wallet",             "getreceivedbyaccount",   &getreceivedbyaccount,   false },
355     { "wallet",             "getreceivedbyaddress",   &getreceivedbyaddress,   false },
356     { "wallet",             "gettransaction",         &gettransaction,         false },
357     { "wallet",             "getunconfirmedbalance",  &getunconfirmedbalance,  false },
358     { "wallet",             "getwalletinfo",          &getwalletinfo,          false },
359     { "wallet",             "importprivkey",          &importprivkey,          true  },
360     { "wallet",             "importwallet",           &importwallet,           true  },
361     { "wallet",             "importaddress",          &importaddress,          true  },
362     { "wallet",             "keypoolrefill",          &keypoolrefill,          true  },
363     { "wallet",             "listaccounts",           &listaccounts,           false },
364     { "wallet",             "listaddressgroupings",   &listaddressgroupings,   false },
365     { "wallet",             "listlockunspent",        &listlockunspent,        false },
366     { "wallet",             "listreceivedbyaccount",  &listreceivedbyaccount,  false },
367     { "wallet",             "listreceivedbyaddress",  &listreceivedbyaddress,  false },
368     { "wallet",             "listsinceblock",         &listsinceblock,         false },
369     { "wallet",             "listtransactions",       &listtransactions,       false },
370     { "wallet",             "listunspent",            &listunspent,            false },
371     { "wallet",             "lockunspent",            &lockunspent,            true  },
372     { "wallet",             "move",                   &movecmd,                false },
373     { "wallet",             "sendfrom",               &sendfrom,               false },
374     { "wallet",             "sendmany",               &sendmany,               false },
375     { "wallet",             "sendtoaddress",          &sendtoaddress,          false },
376     { "wallet",             "setaccount",             &setaccount,             true  },
377     { "wallet",             "settxfee",               &settxfee,               true  },
378     { "wallet",             "signmessage",            &signmessage,            true  },
379     { "wallet",             "walletlock",             &walletlock,             true  },
380     { "wallet",             "walletpassphrasechange", &walletpassphrasechange, true  },
381     { "wallet",             "walletpassphrase",       &walletpassphrase,       true  },
382     { "wallet",             "zcbenchmark",            &zc_benchmark,           true  },
383     { "wallet",             "zcrawkeygen",            &zc_raw_keygen,          true  },
384     { "wallet",             "zcrawjoinsplit",         &zc_raw_joinsplit,       true  },
385     { "wallet",             "zcrawreceive",           &zc_raw_receive,         true  },
386     { "wallet",             "zcsamplejoinsplit",      &zc_sample_joinsplit,    true  },
387     { "wallet",             "z_listreceivedbyaddress",&z_listreceivedbyaddress,false },
388     { "wallet",             "z_getbalance",           &z_getbalance,           false },
389     { "wallet",             "z_gettotalbalance",      &z_gettotalbalance,      false },
390     { "wallet",             "z_sendmany",             &z_sendmany,             false },
391     { "wallet",             "z_getoperationstatus",   &z_getoperationstatus,   true  },
392     { "wallet",             "z_getoperationresult",   &z_getoperationresult,   true  },
393     { "wallet",             "z_listoperationids",     &z_listoperationids,     true  },
394     { "wallet",             "z_getnewaddress",        &z_getnewaddress,        true  },
395     { "wallet",             "z_listaddresses",        &z_listaddresses,        true  },
396     { "wallet",             "z_exportkey",            &z_exportkey,            true  },
397     { "wallet",             "z_importkey",            &z_importkey,            true  },
398     { "wallet",             "z_exportwallet",         &z_exportwallet,         true  },
399     { "wallet",             "z_importwallet",         &z_importwallet,         true  }
400 #endif // ENABLE_WALLET
401 };
402
403 CRPCTable::CRPCTable()
404 {
405     unsigned int vcidx;
406     for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
407     {
408         const CRPCCommand *pcmd;
409
410         pcmd = &vRPCCommands[vcidx];
411         mapCommands[pcmd->name] = pcmd;
412     }
413 }
414
415 const CRPCCommand *CRPCTable::operator[](const std::string &name) const
416 {
417     map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
418     if (it == mapCommands.end())
419         return NULL;
420     return (*it).second;
421 }
422
423 bool StartRPC()
424 {
425     LogPrint("rpc", "Starting RPC\n");
426     fRPCRunning = true;
427     g_rpcSignals.Started();
428
429     // Launch one async rpc worker.  The ability to launch multiple workers is not recommended at present and thus the option is disabled.
430     getAsyncRPCQueue()->addWorker();
431 /*   
432     int n = GetArg("-rpcasyncthreads", 1);
433     if (n<1) {
434         LogPrintf("ERROR: Invalid value %d for -rpcasyncthreads.  Must be at least 1.\n", n);
435         strerr = strprintf(_("An error occurred while setting up the Async RPC threads, invalid parameter value of %d (must be at least 1)."), n);
436         uiInterface.ThreadSafeMessageBox(strerr, "", CClientUIInterface::MSG_ERROR);
437         StartShutdown();
438         return;
439     }
440     for (int i = 0; i < n; i++)
441         getAsyncRPCQueue()->addWorker();
442 */
443     return true;
444 }
445
446 void InterruptRPC()
447 {
448     LogPrint("rpc", "Interrupting RPC\n");
449     // Interrupt e.g. running longpolls
450     fRPCRunning = false;
451 }
452
453 void StopRPC()
454 {
455     LogPrint("rpc", "Stopping RPC\n");
456     deadlineTimers.clear();
457     g_rpcSignals.Stopped();
458
459     // Tells async queue to cancel all operations and shutdown.
460     LogPrintf("%s: waiting for async rpc workers to stop\n", __func__);
461     getAsyncRPCQueue()->closeAndWait();
462 }
463
464 bool IsRPCRunning()
465 {
466     return fRPCRunning;
467 }
468
469 void SetRPCWarmupStatus(const std::string& newStatus)
470 {
471     LOCK(cs_rpcWarmup);
472     rpcWarmupStatus = newStatus;
473 }
474
475 void SetRPCWarmupFinished()
476 {
477     LOCK(cs_rpcWarmup);
478     assert(fRPCInWarmup);
479     fRPCInWarmup = false;
480 }
481
482 bool RPCIsInWarmup(std::string *outStatus)
483 {
484     LOCK(cs_rpcWarmup);
485     if (outStatus)
486         *outStatus = rpcWarmupStatus;
487     return fRPCInWarmup;
488 }
489
490 void JSONRequest::parse(const UniValue& valRequest)
491 {
492     // Parse request
493     if (!valRequest.isObject())
494         throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
495     const UniValue& request = valRequest.get_obj();
496
497     // Parse id now so errors from here on will have the id
498     id = find_value(request, "id");
499
500     // Parse method
501     UniValue valMethod = find_value(request, "method");
502     if (valMethod.isNull())
503         throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
504     if (!valMethod.isStr())
505         throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
506     strMethod = valMethod.get_str();
507     if (strMethod != "getblocktemplate")
508         LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
509
510     // Parse params
511     UniValue valParams = find_value(request, "params");
512     if (valParams.isArray())
513         params = valParams.get_array();
514     else if (valParams.isNull())
515         params = UniValue(UniValue::VARR);
516     else
517         throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array");
518 }
519
520 static UniValue JSONRPCExecOne(const UniValue& req)
521 {
522     UniValue rpc_result(UniValue::VOBJ);
523
524     JSONRequest jreq;
525     try {
526         jreq.parse(req);
527
528         UniValue result = tableRPC.execute(jreq.strMethod, jreq.params);
529         rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id);
530     }
531     catch (const UniValue& objError)
532     {
533         rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id);
534     }
535     catch (const std::exception& e)
536     {
537         rpc_result = JSONRPCReplyObj(NullUniValue,
538                                      JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
539     }
540
541     return rpc_result;
542 }
543
544 std::string JSONRPCExecBatch(const UniValue& vReq)
545 {
546     UniValue ret(UniValue::VARR);
547     for (size_t reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
548         ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
549
550     return ret.write() + "\n";
551 }
552
553 UniValue CRPCTable::execute(const std::string &strMethod, const UniValue &params) const
554 {
555     // Return immediately if in warmup
556     {
557         LOCK(cs_rpcWarmup);
558         if (fRPCInWarmup)
559             throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
560     }
561
562     // Find method
563     const CRPCCommand *pcmd = tableRPC[strMethod];
564     if (!pcmd)
565         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
566
567     g_rpcSignals.PreCommand(*pcmd);
568
569     try
570     {
571         // Execute
572         return pcmd->actor(params, false);
573     }
574     catch (const std::exception& e)
575     {
576         throw JSONRPCError(RPC_MISC_ERROR, e.what());
577     }
578
579     g_rpcSignals.PostCommand(*pcmd);
580 }
581
582 std::string HelpExampleCli(const std::string& methodname, const std::string& args)
583 {
584     return "> zcash-cli " + methodname + " " + args + "\n";
585 }
586
587 std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
588 {
589     return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
590         "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8232/\n";
591 }
592
593 void RPCRegisterTimerInterface(RPCTimerInterface *iface)
594 {
595     timerInterfaces.push_back(iface);
596 }
597
598 void RPCUnregisterTimerInterface(RPCTimerInterface *iface)
599 {
600     std::vector<RPCTimerInterface*>::iterator i = std::find(timerInterfaces.begin(), timerInterfaces.end(), iface);
601     assert(i != timerInterfaces.end());
602     timerInterfaces.erase(i);
603 }
604
605 void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds)
606 {
607     if (timerInterfaces.empty())
608         throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
609     deadlineTimers.erase(name);
610     RPCTimerInterface* timerInterface = timerInterfaces[0];
611     LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
612     deadlineTimers.insert(std::make_pair(name, boost::shared_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000))));
613 }
614
615 const CRPCTable tableRPC;
616
617 // Return async rpc queue
618 std::shared_ptr<AsyncRPCQueue> getAsyncRPCQueue()
619 {
620     return AsyncRPCQueue::sharedInstance();
621 }
This page took 0.062831 seconds and 4 git commands to generate.