From a0eaff8a1d18ebba33cdea4cd1efaddeb55519e7 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 15 Jan 2016 11:55:17 +1100 Subject: move rpc* to rpc/ --- src/rpc/server.cpp | 539 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 539 insertions(+) create mode 100644 src/rpc/server.cpp (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp new file mode 100644 index 000000000..b2d4559cc --- /dev/null +++ b/src/rpc/server.cpp @@ -0,0 +1,539 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "rpc/server.h" + +#include "base58.h" +#include "init.h" +#include "random.h" +#include "sync.h" +#include "ui_interface.h" +#include "util.h" +#include "utilstrencodings.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include // for to_upper() + +using namespace RPCServer; +using namespace std; + +static bool fRPCRunning = false; +static bool fRPCInWarmup = true; +static std::string rpcWarmupStatus("RPC server started"); +static CCriticalSection cs_rpcWarmup; +/* Timer-creating functions */ +static RPCTimerInterface* timerInterface = NULL; +/* Map of name to timer. + * @note Can be changed to std::unique_ptr when C++11 */ +static std::map > deadlineTimers; + +static struct CRPCSignals +{ + boost::signals2::signal Started; + boost::signals2::signal Stopped; + boost::signals2::signal PreCommand; + boost::signals2::signal PostCommand; +} g_rpcSignals; + +void RPCServer::OnStarted(boost::function slot) +{ + g_rpcSignals.Started.connect(slot); +} + +void RPCServer::OnStopped(boost::function slot) +{ + g_rpcSignals.Stopped.connect(slot); +} + +void RPCServer::OnPreCommand(boost::function slot) +{ + g_rpcSignals.PreCommand.connect(boost::bind(slot, _1)); +} + +void RPCServer::OnPostCommand(boost::function slot) +{ + g_rpcSignals.PostCommand.connect(boost::bind(slot, _1)); +} + +void RPCTypeCheck(const UniValue& params, + const list& typesExpected, + bool fAllowNull) +{ + unsigned int i = 0; + BOOST_FOREACH(UniValue::VType t, typesExpected) + { + if (params.size() <= i) + break; + + const UniValue& v = params[i]; + if (!((v.type() == t) || (fAllowNull && (v.isNull())))) + { + string err = strprintf("Expected type %s, got %s", + uvTypeName(t), uvTypeName(v.type())); + throw JSONRPCError(RPC_TYPE_ERROR, err); + } + i++; + } +} + +void RPCTypeCheckObj(const UniValue& o, + const map& typesExpected, + bool fAllowNull) +{ + BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected) + { + const UniValue& v = find_value(o, t.first); + if (!fAllowNull && v.isNull()) + throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first)); + + if (!((v.type() == t.second) || (fAllowNull && (v.isNull())))) + { + string err = strprintf("Expected type %s for %s, got %s", + uvTypeName(t.second), t.first, uvTypeName(v.type())); + throw JSONRPCError(RPC_TYPE_ERROR, err); + } + } +} + +CAmount AmountFromValue(const UniValue& value) +{ + if (!value.isNum() && !value.isStr()) + throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string"); + CAmount amount; + if (!ParseFixedPoint(value.getValStr(), 8, &amount)) + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); + if (!MoneyRange(amount)) + throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range"); + return amount; +} + +UniValue ValueFromAmount(const CAmount& amount) +{ + bool sign = amount < 0; + int64_t n_abs = (sign ? -amount : amount); + int64_t quotient = n_abs / COIN; + int64_t remainder = n_abs % COIN; + return UniValue(UniValue::VNUM, + strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder)); +} + +uint256 ParseHashV(const UniValue& v, string strName) +{ + string strHex; + if (v.isStr()) + strHex = v.get_str(); + if (!IsHex(strHex)) // Note: IsHex("") is false + throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')"); + uint256 result; + result.SetHex(strHex); + return result; +} +uint256 ParseHashO(const UniValue& o, string strKey) +{ + return ParseHashV(find_value(o, strKey), strKey); +} +vector ParseHexV(const UniValue& v, string strName) +{ + string strHex; + if (v.isStr()) + strHex = v.get_str(); + if (!IsHex(strHex)) + throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')"); + return ParseHex(strHex); +} +vector ParseHexO(const UniValue& o, string strKey) +{ + return ParseHexV(find_value(o, strKey), strKey); +} + +/** + * Note: This interface may still be subject to change. + */ + +std::string CRPCTable::help(const std::string& strCommand) const +{ + string strRet; + string category; + set setDone; + vector > vCommands; + + for (map::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi) + vCommands.push_back(make_pair(mi->second->category + mi->first, mi->second)); + sort(vCommands.begin(), vCommands.end()); + + BOOST_FOREACH(const PAIRTYPE(string, const CRPCCommand*)& command, vCommands) + { + const CRPCCommand *pcmd = command.second; + string strMethod = pcmd->name; + // We already filter duplicates, but these deprecated screw up the sort order + if (strMethod.find("label") != string::npos) + continue; + if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand) + continue; + try + { + UniValue params; + rpcfn_type pfn = pcmd->actor; + if (setDone.insert(pfn).second) + (*pfn)(params, true); + } + catch (const std::exception& e) + { + // Help text is returned in an exception + string strHelp = string(e.what()); + if (strCommand == "") + { + if (strHelp.find('\n') != string::npos) + strHelp = strHelp.substr(0, strHelp.find('\n')); + + if (category != pcmd->category) + { + if (!category.empty()) + strRet += "\n"; + category = pcmd->category; + string firstLetter = category.substr(0,1); + boost::to_upper(firstLetter); + strRet += "== " + firstLetter + category.substr(1) + " ==\n"; + } + } + strRet += strHelp + "\n"; + } + } + if (strRet == "") + strRet = strprintf("help: unknown command: %s\n", strCommand); + strRet = strRet.substr(0,strRet.size()-1); + return strRet; +} + +UniValue help(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() > 1) + throw runtime_error( + "help ( \"command\" )\n" + "\nList all commands, or get help for a specified command.\n" + "\nArguments:\n" + "1. \"command\" (string, optional) The command to get help on\n" + "\nResult:\n" + "\"text\" (string) The help text\n" + ); + + string strCommand; + if (params.size() > 0) + strCommand = params[0].get_str(); + + return tableRPC.help(strCommand); +} + + +UniValue stop(const UniValue& params, bool fHelp) +{ + // Accept the deprecated and ignored 'detach' boolean argument + if (fHelp || params.size() > 1) + throw runtime_error( + "stop\n" + "\nStop Bitcoin server."); + // Event loop will exit after current HTTP requests have been handled, so + // this reply will get back to the client. + StartShutdown(); + return "Bitcoin server stopping"; +} + +/** + * Call Table + */ +static const CRPCCommand vRPCCommands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + /* Overall control/query calls */ + { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ + { "control", "help", &help, true }, + { "control", "stop", &stop, true }, + + /* P2P networking */ + { "network", "getnetworkinfo", &getnetworkinfo, true }, + { "network", "addnode", &addnode, true }, + { "network", "disconnectnode", &disconnectnode, true }, + { "network", "getaddednodeinfo", &getaddednodeinfo, true }, + { "network", "getconnectioncount", &getconnectioncount, true }, + { "network", "getnettotals", &getnettotals, true }, + { "network", "getpeerinfo", &getpeerinfo, true }, + { "network", "ping", &ping, true }, + { "network", "setban", &setban, true }, + { "network", "listbanned", &listbanned, true }, + { "network", "clearbanned", &clearbanned, true }, + + /* Block chain and UTXO */ + { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, + { "blockchain", "getbestblockhash", &getbestblockhash, true }, + { "blockchain", "getblockcount", &getblockcount, true }, + { "blockchain", "getblock", &getblock, true }, + { "blockchain", "getblockhash", &getblockhash, true }, + { "blockchain", "getblockheader", &getblockheader, true }, + { "blockchain", "getchaintips", &getchaintips, true }, + { "blockchain", "getdifficulty", &getdifficulty, true }, + { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, + { "blockchain", "getrawmempool", &getrawmempool, true }, + { "blockchain", "gettxout", &gettxout, true }, + { "blockchain", "gettxoutproof", &gettxoutproof, true }, + { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, + { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, + { "blockchain", "verifychain", &verifychain, true }, + + /* Mining */ + { "mining", "getblocktemplate", &getblocktemplate, true }, + { "mining", "getmininginfo", &getmininginfo, true }, + { "mining", "getnetworkhashps", &getnetworkhashps, true }, + { "mining", "prioritisetransaction", &prioritisetransaction, true }, + { "mining", "submitblock", &submitblock, true }, + + /* Coin generation */ + { "generating", "getgenerate", &getgenerate, true }, + { "generating", "setgenerate", &setgenerate, true }, + { "generating", "generate", &generate, true }, + + /* Raw transactions */ + { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, + { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true }, + { "rawtransactions", "decodescript", &decodescript, true }, + { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, + { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, + { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ + + /* Utility functions */ + { "util", "createmultisig", &createmultisig, true }, + { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ + { "util", "verifymessage", &verifymessage, true }, + { "util", "estimatefee", &estimatefee, true }, + { "util", "estimatepriority", &estimatepriority, true }, + { "util", "estimatesmartfee", &estimatesmartfee, true }, + { "util", "estimatesmartpriority", &estimatesmartpriority, true }, + + /* Not shown in help */ + { "hidden", "invalidateblock", &invalidateblock, true }, + { "hidden", "reconsiderblock", &reconsiderblock, true }, + { "hidden", "setmocktime", &setmocktime, true }, +}; + +CRPCTable::CRPCTable() +{ + unsigned int vcidx; + for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++) + { + const CRPCCommand *pcmd; + + pcmd = &vRPCCommands[vcidx]; + mapCommands[pcmd->name] = pcmd; + } +} + +const CRPCCommand *CRPCTable::operator[](const std::string &name) const +{ + map::const_iterator it = mapCommands.find(name); + if (it == mapCommands.end()) + return NULL; + return (*it).second; +} + +bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd) +{ + if (IsRPCRunning()) + return false; + + // don't allow overwriting for now + map::const_iterator it = mapCommands.find(name); + if (it != mapCommands.end()) + return false; + + mapCommands[name] = pcmd; + return true; +} + +bool StartRPC() +{ + LogPrint("rpc", "Starting RPC\n"); + fRPCRunning = true; + g_rpcSignals.Started(); + return true; +} + +void InterruptRPC() +{ + LogPrint("rpc", "Interrupting RPC\n"); + // Interrupt e.g. running longpolls + fRPCRunning = false; +} + +void StopRPC() +{ + LogPrint("rpc", "Stopping RPC\n"); + deadlineTimers.clear(); + g_rpcSignals.Stopped(); +} + +bool IsRPCRunning() +{ + return fRPCRunning; +} + +void SetRPCWarmupStatus(const std::string& newStatus) +{ + LOCK(cs_rpcWarmup); + rpcWarmupStatus = newStatus; +} + +void SetRPCWarmupFinished() +{ + LOCK(cs_rpcWarmup); + assert(fRPCInWarmup); + fRPCInWarmup = false; +} + +bool RPCIsInWarmup(std::string *outStatus) +{ + LOCK(cs_rpcWarmup); + if (outStatus) + *outStatus = rpcWarmupStatus; + return fRPCInWarmup; +} + +void JSONRequest::parse(const UniValue& valRequest) +{ + // Parse request + if (!valRequest.isObject()) + throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object"); + const UniValue& request = valRequest.get_obj(); + + // Parse id now so errors from here on will have the id + id = find_value(request, "id"); + + // Parse method + UniValue valMethod = find_value(request, "method"); + if (valMethod.isNull()) + throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method"); + if (!valMethod.isStr()) + throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string"); + strMethod = valMethod.get_str(); + if (strMethod != "getblocktemplate") + LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod)); + + // Parse params + UniValue valParams = find_value(request, "params"); + if (valParams.isArray()) + params = valParams.get_array(); + else if (valParams.isNull()) + params = UniValue(UniValue::VARR); + else + throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array"); +} + +static UniValue JSONRPCExecOne(const UniValue& req) +{ + UniValue rpc_result(UniValue::VOBJ); + + JSONRequest jreq; + try { + jreq.parse(req); + + UniValue result = tableRPC.execute(jreq.strMethod, jreq.params); + rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id); + } + catch (const UniValue& objError) + { + rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id); + } + catch (const std::exception& e) + { + rpc_result = JSONRPCReplyObj(NullUniValue, + JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); + } + + return rpc_result; +} + +std::string JSONRPCExecBatch(const UniValue& vReq) +{ + UniValue ret(UniValue::VARR); + for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++) + ret.push_back(JSONRPCExecOne(vReq[reqIdx])); + + return ret.write() + "\n"; +} + +UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms) const +{ + // Return immediately if in warmup + { + LOCK(cs_rpcWarmup); + if (fRPCInWarmup) + throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus); + } + + // Find method + const CRPCCommand *pcmd = tableRPC[strMethod]; + if (!pcmd) + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); + + g_rpcSignals.PreCommand(*pcmd); + + try + { + // Execute + return pcmd->actor(params, false); + } + catch (const std::exception& e) + { + throw JSONRPCError(RPC_MISC_ERROR, e.what()); + } + + g_rpcSignals.PostCommand(*pcmd); +} + +std::string HelpExampleCli(const std::string& methodname, const std::string& args) +{ + return "> bitcoin-cli " + methodname + " " + args + "\n"; +} + +std::string HelpExampleRpc(const std::string& methodname, const std::string& args) +{ + return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", " + "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n"; +} + +void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface) +{ + if (!timerInterface) + timerInterface = iface; +} + +void RPCSetTimerInterface(RPCTimerInterface *iface) +{ + timerInterface = iface; +} + +void RPCUnsetTimerInterface(RPCTimerInterface *iface) +{ + if (timerInterface == iface) + timerInterface = NULL; +} + +void RPCRunLater(const std::string& name, boost::function func, int64_t nSeconds) +{ + if (!timerInterface) + throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC"); + deadlineTimers.erase(name); + LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); + deadlineTimers.insert(std::make_pair(name, boost::shared_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); +} + +CRPCTable tableRPC; -- cgit v1.2.3 From 8d1de43f0cbc79940d870d0ba09c7d28dd812ef8 Mon Sep 17 00:00:00 2001 From: Leviathn Date: Wed, 10 Feb 2016 18:29:13 -0800 Subject: Remove internal miner This code removes the internal miner which is only useful on Testnet. This leaves the internal miner that is useful on RegTest intact. --- src/rpc/server.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index b2d4559cc..77076e029 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -298,8 +298,6 @@ static const CRPCCommand vRPCCommands[] = { "mining", "submitblock", &submitblock, true }, /* Coin generation */ - { "generating", "getgenerate", &getgenerate, true }, - { "generating", "setgenerate", &setgenerate, true }, { "generating", "generate", &generate, true }, /* Raw transactions */ -- cgit v1.2.3 From ce7413fcb7d28bd72e5ade7dc9756504de766fc2 Mon Sep 17 00:00:00 2001 From: Luv Khemani Date: Sat, 27 Feb 2016 11:57:12 +0800 Subject: Add autocomplete to bitcoin-qt's console window. Removed externs Added listCommands() to CRPCTable Move autocomplete init to RPCConsole::setClientModel() --- src/rpc/server.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index b2d4559cc..e6fae263b 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -499,6 +499,17 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms g_rpcSignals.PostCommand(*pcmd); } +std::vector CRPCTable::listCommands() const +{ + std::vector commandList; + typedef std::map commandMap; + + std::transform( mapCommands.begin(), mapCommands.end(), + std::back_inserter(commandList), + boost::bind(&commandMap::value_type::first,_1) ); + return commandList; +} + std::string HelpExampleCli(const std::string& methodname, const std::string& args) { return "> bitcoin-cli " + methodname + " " + args + "\n"; -- cgit v1.2.3 From fe00ca758a0f1ab2db3f7441c04780630a9df11a Mon Sep 17 00:00:00 2001 From: Andrew C Date: Sat, 12 Mar 2016 11:41:51 -0500 Subject: Create generatetoaddress rpc Creates the generatetoaddress rpc which is virtually identical to the generate rpc except that it takes an argument for the address to mine to. It does not rely on wallet functionality. The mining code shared by generate and generatetoaddress has been moved to another method to reduce duplication. --- src/rpc/server.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 33fa1437e..1303a3bb1 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -299,6 +299,7 @@ static const CRPCCommand vRPCCommands[] = /* Coin generation */ { "generating", "generate", &generate, true }, + { "generating", "generatetoaddress", &generatetoaddress, true }, /* Raw transactions */ { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, -- cgit v1.2.3 From fb8a8cf2e610920e9eee61c19ed6080af064bb43 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 29 Mar 2016 19:43:02 +0200 Subject: rpc: Register calls where they are defined Split out methods to every module, apart from 'help' and 'stop' which are implemented in rpcserver.cpp itself. - This makes it easier to add or remove RPC commands - no longer everything that includes rpcserver.h has to be rebuilt when there's a change there. - Cleans up `rpc/server.h` by getting rid of the huge cluttered list of function definitions. - Removes most of the bitcoin-specific code from rpcserver.cpp and .h. Continues #7307 for the non-wallet. --- src/rpc/server.cpp | 64 ------------------------------------------------------ 1 file changed, 64 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1303a3bb1..8326fe14d 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -256,72 +256,8 @@ static const CRPCCommand vRPCCommands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- /* Overall control/query calls */ - { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ { "control", "help", &help, true }, { "control", "stop", &stop, true }, - - /* P2P networking */ - { "network", "getnetworkinfo", &getnetworkinfo, true }, - { "network", "addnode", &addnode, true }, - { "network", "disconnectnode", &disconnectnode, true }, - { "network", "getaddednodeinfo", &getaddednodeinfo, true }, - { "network", "getconnectioncount", &getconnectioncount, true }, - { "network", "getnettotals", &getnettotals, true }, - { "network", "getpeerinfo", &getpeerinfo, true }, - { "network", "ping", &ping, true }, - { "network", "setban", &setban, true }, - { "network", "listbanned", &listbanned, true }, - { "network", "clearbanned", &clearbanned, true }, - - /* Block chain and UTXO */ - { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, - { "blockchain", "getbestblockhash", &getbestblockhash, true }, - { "blockchain", "getblockcount", &getblockcount, true }, - { "blockchain", "getblock", &getblock, true }, - { "blockchain", "getblockhash", &getblockhash, true }, - { "blockchain", "getblockheader", &getblockheader, true }, - { "blockchain", "getchaintips", &getchaintips, true }, - { "blockchain", "getdifficulty", &getdifficulty, true }, - { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, - { "blockchain", "getrawmempool", &getrawmempool, true }, - { "blockchain", "gettxout", &gettxout, true }, - { "blockchain", "gettxoutproof", &gettxoutproof, true }, - { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, - { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, - { "blockchain", "verifychain", &verifychain, true }, - - /* Mining */ - { "mining", "getblocktemplate", &getblocktemplate, true }, - { "mining", "getmininginfo", &getmininginfo, true }, - { "mining", "getnetworkhashps", &getnetworkhashps, true }, - { "mining", "prioritisetransaction", &prioritisetransaction, true }, - { "mining", "submitblock", &submitblock, true }, - - /* Coin generation */ - { "generating", "generate", &generate, true }, - { "generating", "generatetoaddress", &generatetoaddress, true }, - - /* Raw transactions */ - { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, - { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true }, - { "rawtransactions", "decodescript", &decodescript, true }, - { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, - { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, - { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ - - /* Utility functions */ - { "util", "createmultisig", &createmultisig, true }, - { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ - { "util", "verifymessage", &verifymessage, true }, - { "util", "estimatefee", &estimatefee, true }, - { "util", "estimatepriority", &estimatepriority, true }, - { "util", "estimatesmartfee", &estimatesmartfee, true }, - { "util", "estimatesmartpriority", &estimatesmartpriority, true }, - - /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true }, - { "hidden", "reconsiderblock", &reconsiderblock, true }, - { "hidden", "setmocktime", &setmocktime, true }, }; CRPCTable::CRPCTable() -- cgit v1.2.3 From 41e835dd50d358c127bab17a1f2872471dbdfe9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 30 Mar 2016 00:59:29 +0100 Subject: Add strict flag to RPCTypeCheckObj Strict flag forces type check on all object keys. --- src/rpc/server.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 8326fe14d..d06a9142b 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -89,7 +89,8 @@ void RPCTypeCheck(const UniValue& params, void RPCTypeCheckObj(const UniValue& o, const map& typesExpected, - bool fAllowNull) + bool fAllowNull, + bool fStrict) { BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected) { @@ -104,6 +105,18 @@ void RPCTypeCheckObj(const UniValue& o, throw JSONRPCError(RPC_TYPE_ERROR, err); } } + + if (fStrict) + { + BOOST_FOREACH(const string& k, o.getKeys()) + { + if (typesExpected.count(k) == 0) + { + string err = strprintf("Unexpected key %s", k); + throw JSONRPCError(RPC_TYPE_ERROR, err); + } + } + } } CAmount AmountFromValue(const UniValue& value) -- cgit v1.2.3 From fa7f4f577cbab2b4bc03b5427704c2ec16680c34 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 6 Jun 2016 17:50:50 +0200 Subject: [rpc] fundrawtransaction feeRate: Use BTC/kB Also introduce UniValueType UniValueType is a wrapper for UniValue::VType which allows setting a typeAny flag. This flag indicates the type does not matter. (Used by RPCTypeCheckObj) --- src/rpc/server.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index d06a9142b..23149baa6 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -88,20 +88,18 @@ void RPCTypeCheck(const UniValue& params, } void RPCTypeCheckObj(const UniValue& o, - const map& typesExpected, - bool fAllowNull, - bool fStrict) + const map& typesExpected, + bool fAllowNull, + bool fStrict) { - BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected) - { + for (const auto& t : typesExpected) { const UniValue& v = find_value(o, t.first); if (!fAllowNull && v.isNull()) throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first)); - if (!((v.type() == t.second) || (fAllowNull && (v.isNull())))) - { + if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) { string err = strprintf("Expected type %s for %s, got %s", - uvTypeName(t.second), t.first, uvTypeName(v.type())); + uvTypeName(t.second.type), t.first, uvTypeName(v.type())); throw JSONRPCError(RPC_TYPE_ERROR, err); } } -- cgit v1.2.3 From 5e187e70012c247b96783f7fa9bcbd0289504ad5 Mon Sep 17 00:00:00 2001 From: whythat Date: Mon, 18 Jul 2016 12:26:21 +0300 Subject: use c++11 std::unique_ptr instead of boost::shared_ptr --- src/rpc/server.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 23149baa6..4b594f5fa 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -25,6 +25,8 @@ #include #include // for to_upper() +#include // for unique_ptr + using namespace RPCServer; using namespace std; @@ -34,9 +36,8 @@ static std::string rpcWarmupStatus("RPC server started"); static CCriticalSection cs_rpcWarmup; /* Timer-creating functions */ static RPCTimerInterface* timerInterface = NULL; -/* Map of name to timer. - * @note Can be changed to std::unique_ptr when C++11 */ -static std::map > deadlineTimers; +/* Map of name to timer. */ +static std::map > deadlineTimers; static struct CRPCSignals { @@ -490,7 +491,7 @@ void RPCRunLater(const std::string& name, boost::function func, int6 throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC"); deadlineTimers.erase(name); LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); - deadlineTimers.insert(std::make_pair(name, boost::shared_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); + deadlineTimers.insert(std::make_pair(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); } CRPCTable tableRPC; -- cgit v1.2.3 From c78408607536bf030947f69f6dc6e09e07873c84 Mon Sep 17 00:00:00 2001 From: whythat Date: Tue, 19 Jul 2016 02:15:59 +0300 Subject: use std::map::emplace() instead of std::map::insert() --- src/rpc/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 4b594f5fa..5fb97f749 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -491,7 +491,7 @@ void RPCRunLater(const std::string& name, boost::function func, int6 throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC"); deadlineTimers.erase(name); LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); - deadlineTimers.insert(std::make_pair(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); + deadlineTimers.emplace(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000))); } CRPCTable tableRPC; -- cgit v1.2.3 From 69d1c25768a8649bfc7eb8e9c35b8fe9874ac9fc Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 22 Sep 2016 09:46:41 +0200 Subject: [RPC] Give RPC commands more information about the RPC request --- src/rpc/server.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 5fb97f749..29d0bee1b 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -195,10 +195,11 @@ std::string CRPCTable::help(const std::string& strCommand) const continue; try { - UniValue params; + JSONRPCRequest jreq; + jreq.fHelp = true; rpcfn_type pfn = pcmd->actor; if (setDone.insert(pfn).second) - (*pfn)(params, true); + (*pfn)(jreq); } catch (const std::exception& e) { @@ -228,9 +229,9 @@ std::string CRPCTable::help(const std::string& strCommand) const return strRet; } -UniValue help(const UniValue& params, bool fHelp) +UniValue help(const JSONRPCRequest& jsonRequest) { - if (fHelp || params.size() > 1) + if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw runtime_error( "help ( \"command\" )\n" "\nList all commands, or get help for a specified command.\n" @@ -241,17 +242,17 @@ UniValue help(const UniValue& params, bool fHelp) ); string strCommand; - if (params.size() > 0) - strCommand = params[0].get_str(); + if (jsonRequest.params.size() > 0) + strCommand = jsonRequest.params[0].get_str(); return tableRPC.help(strCommand); } -UniValue stop(const UniValue& params, bool fHelp) +UniValue stop(const JSONRPCRequest& jsonRequest) { // Accept the deprecated and ignored 'detach' boolean argument - if (fHelp || params.size() > 1) + if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw runtime_error( "stop\n" "\nStop Bitcoin server."); @@ -354,7 +355,7 @@ bool RPCIsInWarmup(std::string *outStatus) return fRPCInWarmup; } -void JSONRequest::parse(const UniValue& valRequest) +void JSONRPCRequest::parse(const UniValue& valRequest) { // Parse request if (!valRequest.isObject()) @@ -388,11 +389,11 @@ static UniValue JSONRPCExecOne(const UniValue& req) { UniValue rpc_result(UniValue::VOBJ); - JSONRequest jreq; + JSONRPCRequest jreq; try { jreq.parse(req); - UniValue result = tableRPC.execute(jreq.strMethod, jreq.params); + UniValue result = tableRPC.execute(jreq); rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id); } catch (const UniValue& objError) @@ -417,7 +418,7 @@ std::string JSONRPCExecBatch(const UniValue& vReq) return ret.write() + "\n"; } -UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms) const +UniValue CRPCTable::execute(const JSONRPCRequest &request) const { // Return immediately if in warmup { @@ -427,7 +428,7 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms } // Find method - const CRPCCommand *pcmd = tableRPC[strMethod]; + const CRPCCommand *pcmd = tableRPC[request.strMethod]; if (!pcmd) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); @@ -436,7 +437,7 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms try { // Execute - return pcmd->actor(params, false); + return pcmd->actor(request); } catch (const std::exception& e) { -- cgit v1.2.3 From fa326193ad739d1f93da456b3fa73af0bbf9fdd1 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 30 Oct 2016 16:58:13 +0100 Subject: [rpc] ParseHash: Fail when length is not 64 --- src/rpc/server.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 29d0bee1b..164e0f00e 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -147,6 +147,8 @@ uint256 ParseHashV(const UniValue& v, string strName) strHex = v.get_str(); if (!IsHex(strHex)) // Note: IsHex("") is false throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')"); + if (64 != strHex.length()) + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d)", strName, 64, strHex.length())); uint256 result; result.SetHex(strHex); return result; -- cgit v1.2.3 From bc7ff8db99dbc28f8b2d7a22f4650fa5349cb23b Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Sun, 20 Nov 2016 09:54:51 -0500 Subject: Add option to return non-segwit serialization via rpc --- src/rpc/server.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 164e0f00e..212281939 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -497,4 +497,12 @@ void RPCRunLater(const std::string& name, boost::function func, int6 deadlineTimers.emplace(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000))); } +int RPCSerializationFlags() +{ + int flag = 0; + if (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0) + flag |= SERIALIZE_TRANSACTION_NO_WITNESS; + return flag; +} + CRPCTable tableRPC; -- cgit v1.2.3 From 27765b6403cece54320374b37afb01a0cfe571c3 Mon Sep 17 00:00:00 2001 From: isle2983 Date: Sat, 31 Dec 2016 11:01:21 -0700 Subject: Increment MIT Licence copyright header year on files modified in 2016 Edited via: $ contrib/devtools/copyright_header.py update . --- src/rpc/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 212281939..8a223d8aa 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -- cgit v1.2.3 From 6f1c76ae14c884c919db9ed720c7776aa0748244 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 25 Sep 2016 20:42:49 +0200 Subject: rpc: Support named arguments The [JSON-RPC specification](http://www.jsonrpc.org/specification) allows passing parameters as an Array, for by-position arguments, or an Object, for by-name arguments. This implements by-name arguments, but preserves full backwards compatibility. API using by-name arguments are easier to extend, and easier to use (no need to guess which argument goes where). Named are mapped to positions by a per-call structure, provided through the RPC command table. Missing arguments will be replaced by null, except if at the end, then the argument is left out completely. Currently calls fail (though not crash) on intermediate nulls, but this should be improved on a per-call basis later. --- src/rpc/server.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 9 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 8a223d8aa..1b94e1007 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -26,6 +26,7 @@ #include // for to_upper() #include // for unique_ptr +#include using namespace RPCServer; using namespace std; @@ -268,11 +269,11 @@ UniValue stop(const JSONRPCRequest& jsonRequest) * Call Table */ static const CRPCCommand vRPCCommands[] = -{ // category name actor (function) okSafeMode - // --------------------- ------------------------ ----------------------- ---------- +{ // category name actor (function) okSafe argNames + // --------------------- ------------------------ ----------------------- ------ ---------- /* Overall control/query calls */ - { "control", "help", &help, true }, - { "control", "stop", &stop, true }, + { "control", "help", &help, true, {"command"} }, + { "control", "stop", &stop, true, {} }, }; CRPCTable::CRPCTable() @@ -379,12 +380,12 @@ void JSONRPCRequest::parse(const UniValue& valRequest) // Parse params UniValue valParams = find_value(request, "params"); - if (valParams.isArray()) - params = valParams.get_array(); + if (valParams.isArray() || valParams.isObject()) + params = valParams; else if (valParams.isNull()) params = UniValue(UniValue::VARR); else - throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array"); + throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object"); } static UniValue JSONRPCExecOne(const UniValue& req) @@ -420,6 +421,48 @@ std::string JSONRPCExecBatch(const UniValue& vReq) return ret.write() + "\n"; } +/** + * Process named arguments into a vector of positional arguments, based on the + * passed-in specification for the RPC call's arguments. + */ +static inline JSONRPCRequest transformNamedArguments(const JSONRPCRequest& in, const std::vector& argNames) +{ + JSONRPCRequest out = in; + out.params = UniValue(UniValue::VARR); + // Build a map of parameters, and remove ones that have been processed, so that we can throw a focused error if + // there is an unknown one. + const std::vector& keys = in.params.getKeys(); + const std::vector& values = in.params.getValues(); + std::unordered_map argsIn; + for (size_t i=0; isecond); + argsIn.erase(fr); + } else { + hole += 1; + } + } + // If there are still arguments in the argsIn map, this is an error. + if (!argsIn.empty()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown named parameter " + argsIn.begin()->first); + } + // Return request with named arguments transformed to positional arguments + return out; +} + UniValue CRPCTable::execute(const JSONRPCRequest &request) const { // Return immediately if in warmup @@ -438,8 +481,12 @@ UniValue CRPCTable::execute(const JSONRPCRequest &request) const try { - // Execute - return pcmd->actor(request); + // Execute, convert arguments to array if necessary + if (request.params.isObject()) { + return pcmd->actor(transformNamedArguments(request, pcmd->argNames)); + } else { + return pcmd->actor(request); + } } catch (const std::exception& e) { -- cgit v1.2.3 From 52dde66770d833ee5e42e7c5fee610453ae3852a Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Tue, 17 Jan 2017 10:40:41 -0500 Subject: [wallet] Add include_unsafe argument to listunspent RPC --- src/rpc/server.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1b94e1007..283d458c8 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -79,16 +79,20 @@ void RPCTypeCheck(const UniValue& params, break; const UniValue& v = params[i]; - if (!((v.type() == t) || (fAllowNull && (v.isNull())))) - { - string err = strprintf("Expected type %s, got %s", - uvTypeName(t), uvTypeName(v.type())); - throw JSONRPCError(RPC_TYPE_ERROR, err); + if (!(fAllowNull && v.isNull())) { + RPCTypeCheckArgument(v, t); } i++; } } +void RPCTypeCheckArgument(const UniValue& value, UniValue::VType typeExpected) +{ + if (value.type() != typeExpected) { + throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected), uvTypeName(value.type()))); + } +} + void RPCTypeCheckObj(const UniValue& o, const map& typesExpected, bool fAllowNull, -- cgit v1.2.3 From 2afefeade6e668cab0643a5c22ff203ce1e509b0 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 17 Feb 2017 15:04:30 -0500 Subject: boost: remove iostreams includes They're unused and produce nasty deprecation warnings Github-Pull: #9786 Rebased-From: 3301587dc5c7937141282f3799592d1e398495fb --- src/rpc/server.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 283d458c8..0b763acd4 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include #include #include -- cgit v1.2.3 From f15268db3bf1a8c4ea410f4f63c6187b45e06ded Mon Sep 17 00:00:00 2001 From: practicalswift Date: Tue, 28 Mar 2017 08:20:08 +0200 Subject: [rpc] Remove auth cookie on shutdown Accidentally removed in 40b556d3742a1f65d67e2d4c760d0b13fe8be5b7 Github-Pull: #10139 Rebased-From: 4b87973c32bcaa5fa7509793e4f0c4f4f981f21b --- src/rpc/server.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 0b763acd4..67fc82580 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -331,6 +331,7 @@ void StopRPC() { LogPrint("rpc", "Stopping RPC\n"); deadlineTimers.clear(); + DeleteAuthCookie(); g_rpcSignals.Stopped(); } -- cgit v1.2.3 From c6eeab75a1c70b6ad63854e036e5843b7f104d31 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Mon, 1 Jan 2018 16:24:14 +0000 Subject: Change count type used by `gettxoutsetinfo` (#1415) changing CAmount (is a int64_t) to arith_uint256 for nTotalAmount in CCoinsStats to prevent overflow --- src/rpc/server.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 67fc82580..26e7297f3 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -143,6 +143,16 @@ UniValue ValueFromAmount(const CAmount& amount) strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder)); } +UniValue ValueFromAmount(const arith_uint256& amount) +{ + bool sign = amount < 0; + arith_uint256 n_abs = (sign ? -amount : amount); + arith_uint256 quotient = n_abs / COIN; + arith_uint256 remainder = n_abs - (quotient * COIN); + return UniValue(UniValue::VNUM, + strprintf("%s%d.%08d", sign ? "-" : "", (int64_t)quotient.getdouble(), (int64_t)remainder.getdouble())); +} + uint256 ParseHashV(const UniValue& v, string strName) { string strHex; -- cgit v1.2.3 From 148a2aca05fe98031bcf857fa186d792c507090c Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Mon, 27 Jul 2015 16:35:30 +0100 Subject: Introduce basic Dogecoin branding --- src/rpc/server.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/rpc/server.cpp') diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 26e7297f3..6ab5f834f 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -270,11 +270,11 @@ UniValue stop(const JSONRPCRequest& jsonRequest) if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw runtime_error( "stop\n" - "\nStop Bitcoin server."); + "\nStop Dogecoin server."); // Event loop will exit after current HTTP requests have been handled, so // this reply will get back to the client. StartShutdown(); - return "Bitcoin server stopping"; + return "Dogecoin server stopping"; } /** @@ -522,7 +522,7 @@ std::vector CRPCTable::listCommands() const std::string HelpExampleCli(const std::string& methodname, const std::string& args) { - return "> bitcoin-cli " + methodname + " " + args + "\n"; + return "> dogecoin-cli " + methodname + " " + args + "\n"; } std::string HelpExampleRpc(const std::string& methodname, const std::string& args) -- cgit v1.2.3