diff options
| author | Daniel Cousens <[email protected]> | 2016-01-15 11:55:17 +1100 |
|---|---|---|
| committer | Daniel Cousens <[email protected]> | 2016-01-21 08:36:55 +1100 |
| commit | a0eaff8a1d18ebba33cdea4cd1efaddeb55519e7 (patch) | |
| tree | 5f13a0b8968d60274d86c44b685c9c980f7a33ca /src/rpcserver.cpp | |
| parent | Merge #7183: Improved readability of ApproximateBestSubset (diff) | |
| download | discoin-a0eaff8a1d18ebba33cdea4cd1efaddeb55519e7.tar.xz discoin-a0eaff8a1d18ebba33cdea4cd1efaddeb55519e7.zip | |
move rpc* to rpc/
Diffstat (limited to 'src/rpcserver.cpp')
| -rw-r--r-- | src/rpcserver.cpp | 539 |
1 files changed, 0 insertions, 539 deletions
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp deleted file mode 100644 index b638598f7..000000000 --- a/src/rpcserver.cpp +++ /dev/null @@ -1,539 +0,0 @@ -// 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 "rpcserver.h" - -#include "base58.h" -#include "init.h" -#include "random.h" -#include "sync.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" - -#include <univalue.h> - -#include <boost/bind.hpp> -#include <boost/filesystem.hpp> -#include <boost/foreach.hpp> -#include <boost/iostreams/concepts.hpp> -#include <boost/iostreams/stream.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/signals2/signal.hpp> -#include <boost/thread.hpp> -#include <boost/algorithm/string/case_conv.hpp> // 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<std::string, boost::shared_ptr<RPCTimerBase> > deadlineTimers; - -static struct CRPCSignals -{ - boost::signals2::signal<void ()> Started; - boost::signals2::signal<void ()> Stopped; - boost::signals2::signal<void (const CRPCCommand&)> PreCommand; - boost::signals2::signal<void (const CRPCCommand&)> PostCommand; -} g_rpcSignals; - -void RPCServer::OnStarted(boost::function<void ()> slot) -{ - g_rpcSignals.Started.connect(slot); -} - -void RPCServer::OnStopped(boost::function<void ()> slot) -{ - g_rpcSignals.Stopped.connect(slot); -} - -void RPCServer::OnPreCommand(boost::function<void (const CRPCCommand&)> slot) -{ - g_rpcSignals.PreCommand.connect(boost::bind(slot, _1)); -} - -void RPCServer::OnPostCommand(boost::function<void (const CRPCCommand&)> slot) -{ - g_rpcSignals.PostCommand.connect(boost::bind(slot, _1)); -} - -void RPCTypeCheck(const UniValue& params, - const list<UniValue::VType>& 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<string, UniValue::VType>& 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<unsigned char> 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<unsigned char> 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<rpcfn_type> setDone; - vector<pair<string, const CRPCCommand*> > vCommands; - - for (map<string, const CRPCCommand*>::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<string, const CRPCCommand*>::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<string, const CRPCCommand*>::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<void(void)> 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<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)))); -} - -CRPCTable tableRPC; |