diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/blockchain.cpp | 95 | ||||
-rw-r--r-- | src/rpc/blockchain.h | 40 | ||||
-rw-r--r-- | src/rpc/client.cpp | 13 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 161 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 252 | ||||
-rw-r--r-- | src/rpc/net.cpp | 52 | ||||
-rw-r--r-- | src/rpc/protocol.cpp | 20 | ||||
-rw-r--r-- | src/rpc/protocol.h | 11 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 98 | ||||
-rw-r--r-- | src/rpc/server.cpp | 91 | ||||
-rw-r--r-- | src/rpc/server.h | 11 |
11 files changed, 471 insertions, 373 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 6826ce4a79..01066d0eb2 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -3,6 +3,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "rpc/blockchain.h" + #include "amount.h" #include "chain.h" #include "chainparams.h" @@ -28,7 +30,6 @@ #include <mutex> #include <condition_variable> -using namespace std; struct CUpdatedBlock { @@ -43,13 +44,6 @@ static CUpdatedBlock latestblock; extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -/** - * Get the difficulty of the net wrt to the given block index, or the chain tip if - * not provided. - * - * @return A floating point number that is a multiple of the main net minimum - * difficulty (4295032833 hashes). - */ double GetDifficulty(const CBlockIndex* blockindex) { if (blockindex == NULL) @@ -107,7 +101,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) return result; } -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) { UniValue result(UniValue::VOBJ); result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); @@ -154,7 +148,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx UniValue getblockcount(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getblockcount\n" "\nReturns the number of blocks in the longest blockchain.\n" "\nResult:\n" @@ -171,7 +165,7 @@ UniValue getblockcount(const JSONRPCRequest& request) UniValue getbestblockhash(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getbestblockhash\n" "\nReturns the hash of the best (tip) block in the longest blockchain.\n" "\nResult:\n" @@ -198,7 +192,7 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) UniValue waitfornewblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) - throw runtime_error( + throw std::runtime_error( "waitfornewblock (timeout)\n" "\nWaits for a specific new block and returns useful info about it.\n" "\nReturns the current block on timeout or exit.\n" @@ -236,7 +230,7 @@ UniValue waitfornewblock(const JSONRPCRequest& request) UniValue waitforblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "waitforblock <blockhash> (timeout)\n" "\nWaits for a specific new block and returns useful info about it.\n" "\nReturns the current block on timeout or exit.\n" @@ -278,7 +272,7 @@ UniValue waitforblock(const JSONRPCRequest& request) UniValue waitforblockheight(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "waitforblockheight <height> (timeout)\n" "\nWaits for (at least) block height and returns the height and hash\n" "of the current tip.\n" @@ -320,7 +314,7 @@ UniValue waitforblockheight(const JSONRPCRequest& request) UniValue getdifficulty(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getdifficulty\n" "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" "\nResult:\n" @@ -341,8 +335,6 @@ std::string EntryDescriptionString() " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority\n" " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"startingpriority\" : n, (numeric) DEPRECATED. Priority when transaction entered pool\n" - " \"currentpriority\" : n, (numeric) DEPRECATED. Transaction priority now\n" " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" " \"descendantsize\" : n, (numeric) virtual transaction size of in-mempool descendants (including this one)\n" " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one)\n" @@ -363,8 +355,6 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) info.push_back(Pair("modifiedfee", ValueFromAmount(e.GetModifiedFee()))); info.push_back(Pair("time", e.GetTime())); info.push_back(Pair("height", (int)e.GetHeight())); - info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); - info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); info.push_back(Pair("descendantcount", e.GetCountWithDescendants())); info.push_back(Pair("descendantsize", e.GetSizeWithDescendants())); info.push_back(Pair("descendantfees", e.GetModFeesWithDescendants())); @@ -372,7 +362,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) info.push_back(Pair("ancestorsize", e.GetSizeWithAncestors())); info.push_back(Pair("ancestorfees", e.GetModFeesWithAncestors())); const CTransaction& tx = e.GetTx(); - set<string> setDepends; + std::set<std::string> setDepends; BOOST_FOREACH(const CTxIn& txin, tx.vin) { if (mempool.exists(txin.prevout.hash)) @@ -380,7 +370,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) } UniValue depends(UniValue::VARR); - BOOST_FOREACH(const string& dep, setDepends) + BOOST_FOREACH(const std::string& dep, setDepends) { depends.push_back(dep); } @@ -388,7 +378,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) info.push_back(Pair("depends", depends)); } -UniValue mempoolToJSON(bool fVerbose = false) +UniValue mempoolToJSON(bool fVerbose) { if (fVerbose) { @@ -405,7 +395,7 @@ UniValue mempoolToJSON(bool fVerbose = false) } else { - vector<uint256> vtxid; + std::vector<uint256> vtxid; mempool.queryHashes(vtxid); UniValue a(UniValue::VARR); @@ -419,7 +409,7 @@ UniValue mempoolToJSON(bool fVerbose = false) UniValue getrawmempool(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) - throw runtime_error( + throw std::runtime_error( "getrawmempool ( verbose )\n" "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" "\nArguments:\n" @@ -450,7 +440,7 @@ UniValue getrawmempool(const JSONRPCRequest& request) UniValue getmempoolancestors(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw runtime_error( + throw std::runtime_error( "getmempoolancestors txid (verbose)\n" "\nIf txid is in the mempool, returns all in-mempool ancestors.\n" "\nArguments:\n" @@ -514,7 +504,7 @@ UniValue getmempoolancestors(const JSONRPCRequest& request) UniValue getmempooldescendants(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw runtime_error( + throw std::runtime_error( "getmempooldescendants txid (verbose)\n" "\nIf txid is in the mempool, returns all in-mempool descendants.\n" "\nArguments:\n" @@ -578,7 +568,7 @@ UniValue getmempooldescendants(const JSONRPCRequest& request) UniValue getmempoolentry(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) { - throw runtime_error( + throw std::runtime_error( "getmempoolentry txid\n" "\nReturns mempool data for given transaction\n" "\nArguments:\n" @@ -611,7 +601,7 @@ UniValue getmempoolentry(const JSONRPCRequest& request) UniValue getblockhash(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "getblockhash height\n" "\nReturns hash of block in best-block-chain at height provided.\n" "\nArguments:\n" @@ -636,7 +626,7 @@ UniValue getblockhash(const JSONRPCRequest& request) UniValue getblockheader(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "getblockheader \"hash\" ( verbose )\n" "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" "If verbose is true, returns an Object with information about blockheader <hash>.\n" @@ -695,7 +685,7 @@ UniValue getblockheader(const JSONRPCRequest& request) UniValue getblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "getblock \"blockhash\" ( verbose )\n" "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n" "If verbose is true, returns an Object with information about block <hash>.\n" @@ -749,10 +739,15 @@ UniValue getblock(const JSONRPCRequest& request) CBlockIndex* pblockindex = mapBlockIndex[hash]; if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)"); - if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) + // Block not found on disk. This could be because we have the block + // header in our index but don't have the block (for example if a + // non-whitelisted node sends us an unrequested long chain of valid + // blocks, we add the headers to our index, but don't accept the + // block). + throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk"); if (!fVerbose) { @@ -822,7 +817,7 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) UniValue pruneblockchain(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "pruneblockchain\n" "\nArguments:\n" "1. \"height\" (numeric, required) The block height to prune up to. May be set to a discrete height, or a unix timestamp\n" @@ -834,7 +829,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request) + HelpExampleRpc("pruneblockchain", "1000")); if (!fPruneMode) - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Cannot prune blocks because node is not in prune mode."); + throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode."); LOCK(cs_main); @@ -846,9 +841,9 @@ UniValue pruneblockchain(const JSONRPCRequest& request) // too low to be a block time (corresponds to timestamp from Sep 2001). if (heightParam > 1000000000) { // Add a 2 hour buffer to include blocks which might have had old timestamps - CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - 7200); + CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW); if (!pindex) { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not find block with at least the specified timestamp."); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp."); } heightParam = pindex->nHeight; } @@ -856,11 +851,11 @@ UniValue pruneblockchain(const JSONRPCRequest& request) unsigned int height = (unsigned int) heightParam; unsigned int chainHeight = (unsigned int) chainActive.Height(); if (chainHeight < Params().PruneAfterHeight()) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Blockchain is too short for pruning."); + throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning."); else if (height > chainHeight) throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height."); else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) { - LogPrint("rpc", "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks."); + LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks."); height = chainHeight - MIN_BLOCKS_TO_KEEP; } @@ -871,7 +866,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request) UniValue gettxoutsetinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "gettxoutsetinfo\n" "\nReturns statistics about the unspent transaction output set.\n" "Note this call may take some time.\n" @@ -911,7 +906,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) UniValue gettxout(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw runtime_error( + throw std::runtime_error( "gettxout \"txid\" n ( include_mempool )\n" "\nReturns details about an unspent transaction output.\n" "\nArguments:\n" @@ -993,7 +988,7 @@ UniValue verifychain(const JSONRPCRequest& request) int nCheckLevel = GetArg("-checklevel", DEFAULT_CHECKLEVEL); int nCheckDepth = GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); if (request.fHelp || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "verifychain ( checklevel nblocks )\n" "\nVerifies blockchain database.\n" "\nArguments:\n" @@ -1079,7 +1074,7 @@ void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, UniValue getblockchaininfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getblockchaininfo\n" "Returns an object containing various state info regarding blockchain processing.\n" "\nResult:\n" @@ -1172,7 +1167,7 @@ struct CompareBlocksByHeight UniValue getchaintips(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getchaintips\n" "Return information about all known tips in the block tree," " including the main chain as well as orphaned branches.\n" @@ -1205,7 +1200,7 @@ UniValue getchaintips(const JSONRPCRequest& request) LOCK(cs_main); /* - * Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them. + * Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them. * Algorithm: * - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers. * - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip. @@ -1244,7 +1239,7 @@ UniValue getchaintips(const JSONRPCRequest& request) const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight; obj.push_back(Pair("branchlen", branchLen)); - string status; + std::string status; if (chainActive.Contains(block)) { // This block is part of the currently active chain. status = "active"; @@ -1288,7 +1283,7 @@ UniValue mempoolInfoToJSON() UniValue getmempoolinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getmempoolinfo\n" "\nReturns details on the active state of the TX memory pool.\n" "\nResult:\n" @@ -1310,7 +1305,7 @@ UniValue getmempoolinfo(const JSONRPCRequest& request) UniValue preciousblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "preciousblock \"blockhash\"\n" "\nTreats a block as if it were received before others with the same work.\n" "\nA later preciousblock call can override the effect of an earlier one.\n" @@ -1348,7 +1343,7 @@ UniValue preciousblock(const JSONRPCRequest& request) UniValue invalidateblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "invalidateblock \"blockhash\"\n" "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" "\nArguments:\n" @@ -1386,7 +1381,7 @@ UniValue invalidateblock(const JSONRPCRequest& request) UniValue reconsiderblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "reconsiderblock \"blockhash\"\n" "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" "This can be used to undo the effects of invalidateblock.\n" diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h new file mode 100644 index 0000000000..c021441b0a --- /dev/null +++ b/src/rpc/blockchain.h @@ -0,0 +1,40 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RPC_BLOCKCHAIN_H +#define BITCOIN_RPC_BLOCKCHAIN_H + +class CBlock; +class CBlockIndex; +class CScript; +class CTransaction; +class uint256; +class UniValue; + +/** + * Get the difficulty of the net wrt to the given block index, or the chain tip if + * not provided. + * + * @return A floating point number that is a multiple of the main net minimum + * difficulty (4295032833 hashes). + */ +double GetDifficulty(const CBlockIndex* blockindex = nullptr); + +/** Callback for when block tip changed. */ +void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); + +/** Block description to JSON */ +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); + +/** Mempool information to JSON */ +UniValue mempoolInfoToJSON(); + +/** Mempool to JSON */ +UniValue mempoolToJSON(bool fVerbose = false); + +/** Block header to JSON */ +UniValue blockheaderToJSON(const CBlockIndex* blockindex); + +#endif + diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 29bdb37682..1f3c4e52ad 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -13,8 +13,6 @@ #include <boost/algorithm/string/case_conv.hpp> // for to_lower() #include <univalue.h> -using namespace std; - class CRPCConvertParam { public: @@ -83,7 +81,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getblockheader", 1, "verbose" }, { "gettransaction", 1, "include_watchonly" }, { "getrawtransaction", 1, "verbose" }, - { "createrawtransaction", 0, "transactions" }, + { "createrawtransaction", 0, "inputs" }, { "createrawtransaction", 1, "outputs" }, { "createrawtransaction", 2, "locktime" }, { "signrawtransaction", 1, "prevtxs" }, @@ -107,17 +105,16 @@ static const CRPCConvertParam vRPCConvertParams[] = { "keypoolrefill", 0, "newsize" }, { "getrawmempool", 0, "verbose" }, { "estimatefee", 0, "nblocks" }, - { "estimatepriority", 0, "nblocks" }, { "estimatesmartfee", 0, "nblocks" }, - { "estimatesmartpriority", 0, "nblocks" }, - { "prioritisetransaction", 1, "priority_delta" }, - { "prioritisetransaction", 2, "fee_delta" }, + { "prioritisetransaction", 1, "fee_delta" }, { "setban", 2, "bantime" }, { "setban", 3, "absolute" }, { "setnetworkactive", 0, "state" }, { "getmempoolancestors", 1, "verbose" }, { "getmempooldescendants", 1, "verbose" }, { "bumpfee", 1, "options" }, + { "logging", 0, "include" }, + { "logging", 1, "exclude" }, // Echo with conversion (For testing only) { "echojson", 0, "arg0" }, { "echojson", 1, "arg1" }, @@ -171,7 +168,7 @@ UniValue ParseNonRFCJSONValue(const std::string& strVal) UniValue jVal; if (!jVal.read(std::string("[")+strVal+std::string("]")) || !jVal.isArray() || jVal.size()!=1) - throw runtime_error(string("Error parsing JSON:")+strVal); + throw std::runtime_error(std::string("Error parsing JSON:")+strVal); return jVal[0]; } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 7708771d00..d234bb69ae 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -16,6 +16,7 @@ #include "miner.h" #include "net.h" #include "pow.h" +#include "rpc/blockchain.h" #include "rpc/server.h" #include "txmempool.h" #include "util.h" @@ -26,12 +27,9 @@ #include <stdint.h> #include <boost/assign/list_of.hpp> -#include <boost/shared_ptr.hpp> #include <univalue.h> -using namespace std; - /** * Return average network hashes per second based on the last 'lookup' blocks, * or from the last difficulty change if 'lookup' is nonpositive. @@ -77,7 +75,7 @@ UniValue GetNetworkHashPS(int lookup, int height) { UniValue getnetworkhashps(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "getnetworkhashps ( nblocks height )\n" "\nReturns the estimated network hashes per second based on the last n blocks.\n" "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n" @@ -96,7 +94,7 @@ UniValue getnetworkhashps(const JSONRPCRequest& request) return GetNetworkHashPS(request.params.size() > 0 ? request.params[0].get_int() : 120, request.params.size() > 1 ? request.params[1].get_int() : -1); } -UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) +UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) { static const int nInnerLoopCount = 0x10000; int nHeightStart = 0; @@ -149,7 +147,7 @@ UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nG UniValue generate(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "generate nblocks ( maxtries )\n" "\nMine up to nblocks blocks immediately (before the RPC call returns)\n" "\nArguments:\n" @@ -168,7 +166,7 @@ UniValue generate(const JSONRPCRequest& request) nMaxTries = request.params[1].get_int(); } - boost::shared_ptr<CReserveScript> coinbaseScript; + std::shared_ptr<CReserveScript> coinbaseScript; GetMainSignals().ScriptForMining(coinbaseScript); // If the keypool is exhausted, no script is returned at all. Catch this. @@ -185,7 +183,7 @@ UniValue generate(const JSONRPCRequest& request) UniValue generatetoaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw runtime_error( + throw std::runtime_error( "generatetoaddress nblocks address (maxtries)\n" "\nMine blocks immediately to a specified address (before the RPC call returns)\n" "\nArguments:\n" @@ -208,8 +206,8 @@ UniValue generatetoaddress(const JSONRPCRequest& request) CBitcoinAddress address(request.params[1].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address"); - - boost::shared_ptr<CReserveScript> coinbaseScript(new CReserveScript()); + + std::shared_ptr<CReserveScript> coinbaseScript = std::make_shared<CReserveScript>(); coinbaseScript->reserveScript = GetScriptForDestination(address.Get()); return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false); @@ -218,7 +216,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request) UniValue getmininginfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getmininginfo\n" "\nReturns a json object containing mining-related information." "\nResult:\n" @@ -258,31 +256,28 @@ UniValue getmininginfo(const JSONRPCRequest& request) // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts UniValue prioritisetransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 3) - throw runtime_error( - "prioritisetransaction <txid> <priority delta> <fee delta>\n" + if (request.fHelp || request.params.size() != 2) + throw std::runtime_error( + "prioritisetransaction <txid> <fee delta>\n" "Accepts the transaction into mined blocks at a higher (or lower) priority\n" "\nArguments:\n" "1. \"txid\" (string, required) The transaction id.\n" - "2. priority_delta (numeric, required) The priority to add or subtract.\n" - " The transaction selection algorithm considers the tx as it would have a higher priority.\n" - " (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n" - "3. fee_delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n" + "2. fee_delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n" " The fee is not actually paid, only the algorithm for selecting transactions into a block\n" " considers the transaction as it would have paid a higher (or lower) fee.\n" "\nResult:\n" "true (boolean) Returns true\n" "\nExamples:\n" - + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000") - + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000") + + HelpExampleCli("prioritisetransaction", "\"txid\" 10000") + + HelpExampleRpc("prioritisetransaction", "\"txid\", 10000") ); LOCK(cs_main); uint256 hash = ParseHashStr(request.params[0].get_str(), "txid"); - CAmount nAmount = request.params[2].get_int64(); + CAmount nAmount = request.params[1].get_int64(); - mempool.PrioritiseTransaction(hash, request.params[1].get_real(), nAmount); + mempool.PrioritiseTransaction(hash, nAmount); return true; } @@ -318,7 +313,7 @@ std::string gbt_vb_name(const Consensus::DeploymentPos pos) { UniValue getblocktemplate(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) - throw runtime_error( + throw std::runtime_error( "getblocktemplate ( TemplateRequest )\n" "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" "It returns data needed to construct a block to work on.\n" @@ -519,12 +514,22 @@ UniValue getblocktemplate(const JSONRPCRequest& request) // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners? } + const struct BIP9DeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT]; + // If the caller is indicating segwit support, then allow CreateNewBlock() + // to select witness transactions, after segwit activates (otherwise + // don't). + bool fSupportsSegwit = setClientRules.find(segwit_info.name) != setClientRules.end(); + // Update block static CBlockIndex* pindexPrev; static int64_t nStart; static std::unique_ptr<CBlockTemplate> pblocktemplate; + // Cache whether the last invocation was with segwit support, to avoid returning + // a segwit-block to a non-segwit caller. + static bool fLastTemplateSupportsSegwit = true; if (pindexPrev != chainActive.Tip() || - (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) + (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5) || + fLastTemplateSupportsSegwit != fSupportsSegwit) { // Clear pindexPrev so future calls make a new block, despite any failures from here on pindexPrev = nullptr; @@ -533,10 +538,11 @@ UniValue getblocktemplate(const JSONRPCRequest& request) nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrevNew = chainActive.Tip(); nStart = GetTime(); + fLastTemplateSupportsSegwit = fSupportsSegwit; // Create new block CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy); + pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); @@ -556,7 +562,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); UniValue transactions(UniValue::VARR); - map<uint256, int64_t> setTxIndex; + std::map<uint256, int64_t> setTxIndex; int i = 0; for (const auto& it : pblock->vtx) { const CTransaction& tx = *it; @@ -686,8 +692,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); - const struct BIP9DeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT]; - if (!pblocktemplate->vchCoinbaseCommitment.empty() && setClientRules.find(segwit_info.name) != setClientRules.end()) { + if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) { result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()))); } @@ -704,7 +709,7 @@ public: submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {} protected: - virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) { + void BlockChecked(const CBlock& block, const CValidationState& stateIn) override { if (block.GetHash() != hash) return; found = true; @@ -714,8 +719,8 @@ protected: UniValue submitblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { + throw std::runtime_error( "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n" "\nAttempts to submit new block to network.\n" "The 'jsonparametersobject' parameter is currently ignored.\n" @@ -732,11 +737,17 @@ UniValue submitblock(const JSONRPCRequest& request) + HelpExampleCli("submitblock", "\"mydata\"") + HelpExampleRpc("submitblock", "\"mydata\"") ); + } std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>(); CBlock& block = *blockptr; - if (!DecodeHexBlk(block, request.params[0].get_str())) + if (!DecodeHexBlk(block, request.params[0].get_str())) { throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); + } + + if (block.vtx.empty() || !block.vtx[0]->IsCoinBase()) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block does not start with a coinbase"); + } uint256 hash = block.GetHash(); bool fBlockPresent = false; @@ -745,10 +756,12 @@ UniValue submitblock(const JSONRPCRequest& request) BlockMap::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) { CBlockIndex *pindex = mi->second; - if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) + if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) { return "duplicate"; - if (pindex->nStatus & BLOCK_FAILED_MASK) + } + if (pindex->nStatus & BLOCK_FAILED_MASK) { return "duplicate-invalid"; + } // Otherwise, we might only have the header - process the block before returning fBlockPresent = true; } @@ -766,21 +779,22 @@ UniValue submitblock(const JSONRPCRequest& request) RegisterValidationInterface(&sc); bool fAccepted = ProcessNewBlock(Params(), blockptr, true, NULL); UnregisterValidationInterface(&sc); - if (fBlockPresent) - { - if (fAccepted && !sc.found) + if (fBlockPresent) { + if (fAccepted && !sc.found) { return "duplicate-inconclusive"; + } return "duplicate"; } - if (!sc.found) + if (!sc.found) { return "inconclusive"; + } return BIP22ValidationResult(sc.state); } UniValue estimatefee(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "estimatefee nblocks\n" "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" "confirmation within nblocks blocks. Uses virtual transaction size of transaction\n" @@ -811,37 +825,10 @@ UniValue estimatefee(const JSONRPCRequest& request) return ValueFromAmount(feeRate.GetFeePerK()); } -UniValue estimatepriority(const JSONRPCRequest& request) -{ - if (request.fHelp || request.params.size() != 1) - throw runtime_error( - "estimatepriority nblocks\n" - "\nDEPRECATED. Estimates the approximate priority a zero-fee transaction needs to begin\n" - "confirmation within nblocks blocks.\n" - "\nArguments:\n" - "1. nblocks (numeric, required)\n" - "\nResult:\n" - "n (numeric) estimated priority\n" - "\n" - "A negative value is returned if not enough transactions and blocks\n" - "have been observed to make an estimate.\n" - "\nExample:\n" - + HelpExampleCli("estimatepriority", "6") - ); - - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); - - int nBlocks = request.params[0].get_int(); - if (nBlocks < 1) - nBlocks = 1; - - return mempool.estimatePriority(nBlocks); -} - UniValue estimatesmartfee(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "estimatesmartfee nblocks\n" "\nWARNING: This interface is unstable and may disappear or change!\n" "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" @@ -875,48 +862,12 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) return result; } -UniValue estimatesmartpriority(const JSONRPCRequest& request) -{ - if (request.fHelp || request.params.size() != 1) - throw runtime_error( - "estimatesmartpriority nblocks\n" - "\nDEPRECATED. WARNING: This interface is unstable and may disappear or change!\n" - "\nEstimates the approximate priority a zero-fee transaction needs to begin\n" - "confirmation within nblocks blocks if possible and return the number of blocks\n" - "for which the estimate is valid.\n" - "\nArguments:\n" - "1. nblocks (numeric, required)\n" - "\nResult:\n" - "{\n" - " \"priority\" : x.x, (numeric) estimated priority\n" - " \"blocks\" : n (numeric) block number where estimate was found\n" - "}\n" - "\n" - "A negative value is returned if not enough transactions and blocks\n" - "have been observed to make an estimate for any number of blocks.\n" - "However if the mempool reject fee is set it will return 1e9 * MAX_MONEY.\n" - "\nExample:\n" - + HelpExampleCli("estimatesmartpriority", "6") - ); - - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); - - int nBlocks = request.params[0].get_int(); - - UniValue result(UniValue::VOBJ); - int answerFound; - double priority = mempool.estimateSmartPriority(nBlocks, &answerFound); - result.push_back(Pair("priority", priority)); - result.push_back(Pair("blocks", answerFound)); - return result; -} - static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- { "mining", "getnetworkhashps", &getnetworkhashps, true, {"nblocks","height"} }, { "mining", "getmininginfo", &getmininginfo, true, {} }, - { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","priority_delta","fee_delta"} }, + { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","fee_delta"} }, { "mining", "getblocktemplate", &getblocktemplate, true, {"template_request"} }, { "mining", "submitblock", &submitblock, true, {"hexdata","parameters"} }, @@ -924,9 +875,7 @@ static const CRPCCommand commands[] = { "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} }, { "util", "estimatefee", &estimatefee, true, {"nblocks"} }, - { "util", "estimatepriority", &estimatepriority, true, {"nblocks"} }, { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks"} }, - { "util", "estimatesmartpriority", &estimatesmartpriority, true, {"nblocks"} }, }; void RegisterMiningRPCCommands(CRPCTable &t) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index c84eab7d23..7b8aa572d7 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -7,25 +7,29 @@ #include "clientversion.h" #include "init.h" #include "validation.h" +#include "httpserver.h" #include "net.h" #include "netbase.h" +#include "rpc/blockchain.h" #include "rpc/server.h" #include "timedata.h" #include "util.h" #include "utilstrencodings.h" #ifdef ENABLE_WALLET +#include "wallet/rpcwallet.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" #endif #include <stdint.h> +#ifdef HAVE_MALLOC_INFO +#include <malloc.h> +#endif #include <boost/assign/list_of.hpp> #include <univalue.h> -using namespace std; - /** * @note Do not add or change anything in the information returned by this * method. `getinfo` exists for backwards-compatibility only. It combines @@ -42,7 +46,7 @@ using namespace std; UniValue getinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getinfo\n" "\nDEPRECATED. Returns an object containing various state info.\n" "\nResult:\n" @@ -61,7 +65,7 @@ UniValue getinfo(const JSONRPCRequest& request) " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n" - " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" + " \"relayfee\": x.xxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n" " \"errors\": \"...\" (string) any error messages\n" "}\n" "\nExamples:\n" @@ -70,7 +74,9 @@ UniValue getinfo(const JSONRPCRequest& request) ); #ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL); #else LOCK(cs_main); #endif @@ -82,25 +88,26 @@ UniValue getinfo(const JSONRPCRequest& request) obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("protocolversion", PROTOCOL_VERSION)); #ifdef ENABLE_WALLET - if (pwalletMain) { - obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); - obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); + if (pwallet) { + obj.push_back(Pair("walletversion", pwallet->GetVersion())); + obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance()))); } #endif obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("timeoffset", GetTimeOffset())); if(g_connman) obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL))); - obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()))); + obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET)); #ifdef ENABLE_WALLET - if (pwalletMain) { - obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); - obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); + if (pwallet) { + obj.push_back(Pair("keypoololdest", pwallet->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoolsize", (int)pwallet->GetKeyPoolSize())); + } + if (pwallet && pwallet->IsCrypted()) { + obj.push_back(Pair("unlocked_until", pwallet->nRelockTime)); } - if (pwalletMain && pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); #endif obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); @@ -112,13 +119,17 @@ UniValue getinfo(const JSONRPCRequest& request) class DescribeAddressVisitor : public boost::static_visitor<UniValue> { public: + CWallet * const pwallet; + + DescribeAddressVisitor(CWallet *_pwallet) : pwallet(_pwallet) {} + UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } UniValue operator()(const CKeyID &keyID) const { UniValue obj(UniValue::VOBJ); CPubKey vchPubKey; obj.push_back(Pair("isscript", false)); - if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) { + if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) { obj.push_back(Pair("pubkey", HexStr(vchPubKey))); obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); } @@ -129,7 +140,7 @@ public: UniValue obj(UniValue::VOBJ); CScript subscript; obj.push_back(Pair("isscript", true)); - if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) { + if (pwallet && pwallet->GetCScript(scriptID, subscript)) { std::vector<CTxDestination> addresses; txnouttype whichType; int nRequired; @@ -151,7 +162,7 @@ public: UniValue validateaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "validateaddress \"address\"\n" "\nReturn information about the given bitcoin address.\n" "\nArguments:\n" @@ -177,7 +188,9 @@ UniValue validateaddress(const JSONRPCRequest& request) ); #ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); + + LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL); #else LOCK(cs_main); #endif @@ -190,23 +203,24 @@ UniValue validateaddress(const JSONRPCRequest& request) if (isValid) { CTxDestination dest = address.Get(); - string currentAddress = address.ToString(); + std::string currentAddress = address.ToString(); ret.push_back(Pair("address", currentAddress)); CScript scriptPubKey = GetScriptForDestination(dest); ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); #ifdef ENABLE_WALLET - isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO; + isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO; ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false)); ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false)); - UniValue detail = boost::apply_visitor(DescribeAddressVisitor(), dest); + UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest); ret.pushKVs(detail); - if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) - ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name)); + if (pwallet && pwallet->mapAddressBook.count(dest)) { + ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); + } CKeyID keyID; - if (pwalletMain) { - const auto& meta = pwalletMain->mapKeyMetadata; + if (pwallet) { + const auto& meta = pwallet->mapKeyMetadata; auto it = address.GetKeyID(keyID) ? meta.find(keyID) : meta.end(); if (it == meta.end()) { it = meta.find(CScriptID(scriptPubKey)); @@ -224,23 +238,26 @@ UniValue validateaddress(const JSONRPCRequest& request) return ret; } +// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around +class CWallet; + /** * Used by addmultisigaddress / createmultisig: */ -CScript _createmultisig_redeemScript(const UniValue& params) +CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params) { int nRequired = params[0].get_int(); const UniValue& keys = params[1].get_array(); // Gather public keys if (nRequired < 1) - throw runtime_error("a multisignature address must require at least one key to redeem"); + throw std::runtime_error("a multisignature address must require at least one key to redeem"); if ((int)keys.size() < nRequired) - throw runtime_error( + throw std::runtime_error( strprintf("not enough keys supplied " "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired)); if (keys.size() > 16) - throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number"); + throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number"); std::vector<CPubKey> pubkeys; pubkeys.resize(keys.size()); for (unsigned int i = 0; i < keys.size(); i++) @@ -249,18 +266,18 @@ CScript _createmultisig_redeemScript(const UniValue& params) #ifdef ENABLE_WALLET // Case 1: Bitcoin address and we have full public key: CBitcoinAddress address(ks); - if (pwalletMain && address.IsValid()) - { + if (pwallet && address.IsValid()) { CKeyID keyID; if (!address.GetKeyID(keyID)) - throw runtime_error( + throw std::runtime_error( strprintf("%s does not refer to a key",ks)); CPubKey vchPubKey; - if (!pwalletMain->GetPubKey(keyID, vchPubKey)) - throw runtime_error( + if (!pwallet->GetPubKey(keyID, vchPubKey)) { + throw std::runtime_error( strprintf("no full public key for address %s",ks)); + } if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); + throw std::runtime_error(" Invalid public key: "+ks); pubkeys[i] = vchPubKey; } @@ -271,18 +288,18 @@ CScript _createmultisig_redeemScript(const UniValue& params) { CPubKey vchPubKey(ParseHex(ks)); if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); + throw std::runtime_error(" Invalid public key: "+ks); pubkeys[i] = vchPubKey; } else { - throw runtime_error(" Invalid public key: "+ks); + throw std::runtime_error(" Invalid public key: "+ks); } } CScript result = GetScriptForMultisig(nRequired, pubkeys); if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) - throw runtime_error( + throw std::runtime_error( strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)); return result; @@ -290,9 +307,15 @@ CScript _createmultisig_redeemScript(const UniValue& params) UniValue createmultisig(const JSONRPCRequest& request) { +#ifdef ENABLE_WALLET + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); +#else + CWallet * const pwallet = NULL; +#endif + if (request.fHelp || request.params.size() < 2 || request.params.size() > 2) { - string msg = "createmultisig nrequired [\"key\",...]\n" + std::string msg = "createmultisig nrequired [\"key\",...]\n" "\nCreates a multi-signature address with n signature of m keys required.\n" "It returns a json object with the address and redeemScript.\n" @@ -316,11 +339,11 @@ UniValue createmultisig(const JSONRPCRequest& request) "\nAs a json rpc call\n" + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") ; - throw runtime_error(msg); + throw std::runtime_error(msg); } // Construct using pay-to-script-hash: - CScript inner = _createmultisig_redeemScript(request.params); + CScript inner = _createmultisig_redeemScript(pwallet, request.params); CScriptID innerID(inner); CBitcoinAddress address(innerID); @@ -334,7 +357,7 @@ UniValue createmultisig(const JSONRPCRequest& request) UniValue verifymessage(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 3) - throw runtime_error( + throw std::runtime_error( "verifymessage \"address\" \"signature\" \"message\"\n" "\nVerify a signed message\n" "\nArguments:\n" @@ -356,9 +379,9 @@ UniValue verifymessage(const JSONRPCRequest& request) LOCK(cs_main); - string strAddress = request.params[0].get_str(); - string strSign = request.params[1].get_str(); - string strMessage = request.params[2].get_str(); + std::string strAddress = request.params[0].get_str(); + std::string strSign = request.params[1].get_str(); + std::string strMessage = request.params[2].get_str(); CBitcoinAddress addr(strAddress); if (!addr.IsValid()) @@ -369,7 +392,7 @@ UniValue verifymessage(const JSONRPCRequest& request) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); bool fInvalid = false; - vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid); + std::vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid); if (fInvalid) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); @@ -388,7 +411,7 @@ UniValue verifymessage(const JSONRPCRequest& request) UniValue signmessagewithprivkey(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 2) - throw runtime_error( + throw std::runtime_error( "signmessagewithprivkey \"privkey\" \"message\"\n" "\nSign a message with the private key of an address\n" "\nArguments:\n" @@ -405,8 +428,8 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request) + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") ); - string strPrivkey = request.params[0].get_str(); - string strMessage = request.params[1].get_str(); + std::string strPrivkey = request.params[0].get_str(); + std::string strMessage = request.params[1].get_str(); CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(strPrivkey); @@ -420,7 +443,7 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request) ss << strMessageMagic; ss << strMessage; - vector<unsigned char> vchSig; + std::vector<unsigned char> vchSig; if (!key.SignCompact(ss.GetHash(), vchSig)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); @@ -430,7 +453,7 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request) UniValue setmocktime(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "setmocktime timestamp\n" "\nSet the local time to given timestamp (-regtest only)\n" "\nArguments:\n" @@ -439,7 +462,7 @@ UniValue setmocktime(const JSONRPCRequest& request) ); if (!Params().MineBlocksOnDemand()) - throw runtime_error("setmocktime for regression testing (-regtest mode) only"); + throw std::runtime_error("setmocktime for regression testing (-regtest mode) only"); // For now, don't change mocktime if we're in the middle of validation, as // this could have an effect on mempool time-based eviction, as well as @@ -467,16 +490,39 @@ static UniValue RPCLockedMemoryInfo() return obj; } +#ifdef HAVE_MALLOC_INFO +static std::string RPCMallocInfo() +{ + char *ptr = nullptr; + size_t size = 0; + FILE *f = open_memstream(&ptr, &size); + if (f) { + malloc_info(0, f); + fclose(f); + if (ptr) { + std::string rv(ptr, size); + free(ptr); + return rv; + } + } + return ""; +} +#endif + UniValue getmemoryinfo(const JSONRPCRequest& request) { /* Please, avoid using the word "pool" here in the RPC interface or help, * as users will undoubtedly confuse it with the other "memory pool" */ - if (request.fHelp || request.params.size() != 0) - throw runtime_error( - "getmemoryinfo\n" + if (request.fHelp || request.params.size() > 1) + throw std::runtime_error( + "getmemoryinfo (\"mode\")\n" "Returns an object containing information about memory usage.\n" - "\nResult:\n" + "Arguments:\n" + "1. \"mode\" determines what kind of information is returned. This argument is optional, the default mode is \"stats\".\n" + " - \"stats\" returns general statistics about memory usage in the daemon.\n" + " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+).\n" + "\nResult (mode \"stats\"):\n" "{\n" " \"locked\": { (json object) Information about locked memory manager\n" " \"used\": xxxxx, (numeric) Number of bytes used\n" @@ -487,19 +533,100 @@ UniValue getmemoryinfo(const JSONRPCRequest& request) " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n" " }\n" "}\n" + "\nResult (mode \"mallocinfo\"):\n" + "\"<malloc version=\"1\">...\"\n" "\nExamples:\n" + HelpExampleCli("getmemoryinfo", "") + HelpExampleRpc("getmemoryinfo", "") ); - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("locked", RPCLockedMemoryInfo())); - return obj; + + std::string mode = (request.params.size() < 1 || request.params[0].isNull()) ? "stats" : request.params[0].get_str(); + if (mode == "stats") { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("locked", RPCLockedMemoryInfo())); + return obj; + } else if (mode == "mallocinfo") { +#ifdef HAVE_MALLOC_INFO + return RPCMallocInfo(); +#else + throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo is only available when compiled with glibc 2.10+"); +#endif + } else { + throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode); + } +} + +uint32_t getCategoryMask(UniValue cats) { + cats = cats.get_array(); + uint32_t mask = 0; + for (unsigned int i = 0; i < cats.size(); ++i) { + uint32_t flag = 0; + std::string cat = cats[i].get_str(); + if (!GetLogCategory(&flag, &cat)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); + } + mask |= flag; + } + return mask; +} + +UniValue logging(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() > 2) { + throw std::runtime_error( + "logging [include,...] <exclude>\n" + "Gets and sets the logging configuration.\n" + "When called without an argument, returns the list of categories that are currently being debug logged.\n" + "When called with arguments, adds or removes categories from debug logging.\n" + "The valid logging categories are: " + ListLogCategories() + "\n" + "libevent logging is configured on startup and cannot be modified by this RPC during runtime." + "Arguments:\n" + "1. \"include\" (array of strings) add debug logging for these categories.\n" + "2. \"exclude\" (array of strings) remove debug logging for these categories.\n" + "\nResult: <categories> (string): a list of the logging categories that are active.\n" + "\nExamples:\n" + + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") + ); + } + + uint32_t originalLogCategories = logCategories; + if (request.params.size() > 0 && request.params[0].isArray()) { + logCategories |= getCategoryMask(request.params[0]); + } + + if (request.params.size() > 1 && request.params[1].isArray()) { + logCategories &= ~getCategoryMask(request.params[1]); + } + + // Update libevent logging if BCLog::LIBEVENT has changed. + // If the library version doesn't allow it, UpdateHTTPServerLogging() returns false, + // in which case we should clear the BCLog::LIBEVENT flag. + // Throw an error if the user has explicitly asked to change only the libevent + // flag and it failed. + uint32_t changedLogCategories = originalLogCategories ^ logCategories; + if (changedLogCategories & BCLog::LIBEVENT) { + if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) { + logCategories &= ~BCLog::LIBEVENT; + if (changedLogCategories == BCLog::LIBEVENT) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1."); + } + } + } + + UniValue result(UniValue::VOBJ); + std::vector<CLogCategoryActive> vLogCatActive = ListActiveLogCategories(); + for (const auto& logCatActive : vLogCatActive) { + result.pushKV(logCatActive.category, logCatActive.active); + } + + return result; } UniValue echo(const JSONRPCRequest& request) { if (request.fHelp) - throw runtime_error( + throw std::runtime_error( "echo|echojson \"message\" ...\n" "\nSimply echo back the input arguments. This command is for testing.\n" "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in" @@ -513,7 +640,7 @@ static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- { "control", "getinfo", &getinfo, true, {} }, /* uses wallet if enabled */ - { "control", "getmemoryinfo", &getmemoryinfo, true, {} }, + { "control", "getmemoryinfo", &getmemoryinfo, true, {"mode"} }, { "util", "validateaddress", &validateaddress, true, {"address"} }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, true, {"nrequired","keys"} }, { "util", "verifymessage", &verifymessage, true, {"address","signature","message"} }, @@ -522,7 +649,8 @@ static const CRPCCommand commands[] = /* Not shown in help */ { "hidden", "setmocktime", &setmocktime, true, {"timestamp"}}, { "hidden", "echo", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, - { "hidden", "echojson", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, + { "hidden", "echojson", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, + { "hidden", "logging", &logging, true, {"include", "exclude"}}, }; void RegisterMiscRPCCommands(CRPCTable &t) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index f590db5efa..e4a909c1f6 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -23,12 +23,10 @@ #include <univalue.h> -using namespace std; - UniValue getconnectioncount(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getconnectioncount\n" "\nReturns the number of connections to other nodes.\n" "\nResult:\n" @@ -47,7 +45,7 @@ UniValue getconnectioncount(const JSONRPCRequest& request) UniValue ping(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "ping\n" "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" @@ -70,7 +68,7 @@ UniValue ping(const JSONRPCRequest& request) UniValue getpeerinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getpeerinfo\n" "\nReturns data about each connected network node as a json array of objects.\n" "\nResult:\n" @@ -102,7 +100,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) " n, (numeric) The heights of blocks we're currently asking from this peer\n" " ...\n" " ],\n" - " \"whitelisted\": true|false, (boolean) Whether the peer is whitelisted\n" + " \"whitelisted\": true|false, (boolean) Whether the peer is whitelisted\n" " \"bytessent_per_msg\": {\n" " \"addr\": n, (numeric) The total bytes sent aggregated by message type\n" " ...\n" @@ -122,7 +120,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - vector<CNodeStats> vstats; + std::vector<CNodeStats> vstats; g_connman->GetNodeStats(vstats); UniValue ret(UniValue::VARR); @@ -191,12 +189,12 @@ UniValue getpeerinfo(const JSONRPCRequest& request) UniValue addnode(const JSONRPCRequest& request) { - string strCommand; + std::string strCommand; if (request.params.size() == 2) strCommand = request.params[1].get_str(); if (request.fHelp || request.params.size() != 2 || (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) - throw runtime_error( + throw std::runtime_error( "addnode \"node\" \"add|remove|onetry\"\n" "\nAttempts add or remove a node from the addnode list.\n" "Or try a connection to a node once.\n" @@ -211,7 +209,7 @@ UniValue addnode(const JSONRPCRequest& request) if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - string strNode = request.params[0].get_str(); + std::string strNode = request.params[0].get_str(); if (strCommand == "onetry") { @@ -237,11 +235,11 @@ UniValue addnode(const JSONRPCRequest& request) UniValue disconnectnode(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( - "disconnectnode \"node\" \n" + throw std::runtime_error( + "disconnectnode \"address\" \n" "\nImmediately disconnects from the specified node.\n" "\nArguments:\n" - "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" + "1. \"address\" (string, required) The IP address/port of the node\n" "\nExamples:\n" + HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") @@ -260,7 +258,7 @@ UniValue disconnectnode(const JSONRPCRequest& request) UniValue getaddednodeinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) - throw runtime_error( + throw std::runtime_error( "getaddednodeinfo ( \"node\" )\n" "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n" @@ -328,7 +326,7 @@ UniValue getaddednodeinfo(const JSONRPCRequest& request) UniValue getnettotals(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 0) - throw runtime_error( + throw std::runtime_error( "getnettotals\n" "\nReturns information about network traffic, including bytes in, bytes out,\n" "and current time.\n" @@ -384,7 +382,7 @@ static UniValue GetNetworksInfo() obj.push_back(Pair("name", GetNetworkName(network))); obj.push_back(Pair("limited", IsLimited(network))); obj.push_back(Pair("reachable", IsReachable(network))); - obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())); + obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string())); obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials)); networks.push_back(obj); } @@ -394,7 +392,7 @@ static UniValue GetNetworksInfo() UniValue getnetworkinfo(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "getnetworkinfo\n" "Returns an object containing various state info regarding P2P networking.\n" "\nResult:\n" @@ -417,7 +415,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request) " }\n" " ,...\n" " ],\n" - " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n" + " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n" " \"incrementalfee\": x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n" " \"localaddresses\": [ (array) list of local addresses\n" " {\n" @@ -469,12 +467,12 @@ UniValue getnetworkinfo(const JSONRPCRequest& request) UniValue setban(const JSONRPCRequest& request) { - string strCommand; + std::string strCommand; if (request.params.size() >= 2) strCommand = request.params[1].get_str(); if (request.fHelp || request.params.size() < 2 || (strCommand != "add" && strCommand != "remove")) - throw runtime_error( + throw std::runtime_error( "setban \"subnet\" \"add|remove\" (bantime) (absolute)\n" "\nAttempts add or remove a IP/Subnet from the banned list.\n" "\nArguments:\n" @@ -494,7 +492,7 @@ UniValue setban(const JSONRPCRequest& request) CNetAddr netAddr; bool isSubnet = false; - if (request.params[0].get_str().find("/") != string::npos) + if (request.params[0].get_str().find("/") != std::string::npos) isSubnet = true; if (!isSubnet) { @@ -506,7 +504,7 @@ UniValue setban(const JSONRPCRequest& request) LookupSubNet(request.params[0].get_str().c_str(), subNet); if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) - throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet"); + throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet"); if (strCommand == "add") { @@ -526,7 +524,7 @@ UniValue setban(const JSONRPCRequest& request) else if(strCommand == "remove") { if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) )) - throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); + throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned."); } return NullUniValue; } @@ -534,7 +532,7 @@ UniValue setban(const JSONRPCRequest& request) UniValue listbanned(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "listbanned\n" "\nList all banned IPs/Subnets.\n" "\nExamples:\n" @@ -567,7 +565,7 @@ UniValue listbanned(const JSONRPCRequest& request) UniValue clearbanned(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) - throw runtime_error( + throw std::runtime_error( "clearbanned\n" "\nClear all banned IPs.\n" "\nExamples:\n" @@ -585,7 +583,7 @@ UniValue clearbanned(const JSONRPCRequest& request) UniValue setnetworkactive(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) { - throw runtime_error( + throw std::runtime_error( "setnetworkactive true|false\n" "\nDisable/enable all p2p network activity.\n" "\nArguments:\n" @@ -609,7 +607,7 @@ static const CRPCCommand commands[] = { "network", "ping", &ping, true, {} }, { "network", "getpeerinfo", &getpeerinfo, true, {} }, { "network", "addnode", &addnode, true, {"node","command"} }, - { "network", "disconnectnode", &disconnectnode, true, {"node"} }, + { "network", "disconnectnode", &disconnectnode, true, {"address"} }, { "network", "getaddednodeinfo", &getaddednodeinfo, true, {"node"} }, { "network", "getnettotals", &getnettotals, true, {} }, { "network", "getnetworkinfo", &getnetworkinfo, true, {} }, diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index dc710d939f..823a5775f6 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -15,8 +15,6 @@ #include <stdint.h> #include <fstream> -using namespace std; - /** * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, * but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were @@ -26,7 +24,7 @@ using namespace std; * 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html */ -UniValue JSONRPCRequestObj(const string& strMethod, const UniValue& params, const UniValue& id) +UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id) { UniValue request(UniValue::VOBJ); request.push_back(Pair("method", strMethod)); @@ -47,13 +45,13 @@ UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const Un return reply; } -string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id) +std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id) { UniValue reply = JSONRPCReplyObj(result, error, id); return reply.write() + "\n"; } -UniValue JSONRPCError(int code, const string& message) +UniValue JSONRPCError(int code, const std::string& message) { UniValue error(UniValue::VOBJ); error.push_back(Pair("code", code)); @@ -68,9 +66,9 @@ static const std::string COOKIEAUTH_USER = "__cookie__"; /** Default name for auth cookie file */ static const std::string COOKIEAUTH_FILE = ".cookie"; -boost::filesystem::path GetAuthCookieFile() +fs::path GetAuthCookieFile() { - boost::filesystem::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE)); + fs::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE)); if (!path.is_complete()) path = GetDataDir() / path; return path; } @@ -86,7 +84,7 @@ bool GenerateAuthCookie(std::string *cookie_out) * these are set to 077 in init.cpp unless overridden with -sysperms. */ std::ofstream file; - boost::filesystem::path filepath = GetAuthCookieFile(); + fs::path filepath = GetAuthCookieFile(); file.open(filepath.string().c_str()); if (!file.is_open()) { LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath.string()); @@ -105,7 +103,7 @@ bool GetAuthCookie(std::string *cookie_out) { std::ifstream file; std::string cookie; - boost::filesystem::path filepath = GetAuthCookieFile(); + fs::path filepath = GetAuthCookieFile(); file.open(filepath.string().c_str()); if (!file.is_open()) return false; @@ -120,8 +118,8 @@ bool GetAuthCookie(std::string *cookie_out) void DeleteAuthCookie() { try { - boost::filesystem::remove(GetAuthCookieFile()); - } catch (const boost::filesystem::filesystem_error& e) { + fs::remove(GetAuthCookieFile()); + } catch (const fs::filesystem_error& e) { LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, e.what()); } } diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 47e56e712b..70f7092cfe 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -6,11 +6,12 @@ #ifndef BITCOIN_RPCPROTOCOL_H #define BITCOIN_RPCPROTOCOL_H +#include "fs.h" + #include <list> #include <map> #include <stdint.h> #include <string> -#include <boost/filesystem.hpp> #include <univalue.h> @@ -31,9 +32,15 @@ enum HTTPStatusCode enum RPCErrorCode { //! Standard JSON-RPC 2.0 errors + // RPC_INVALID_REQUEST is internally mapped to HTTP_BAD_REQUEST (400). + // It should not be used for application-layer errors. RPC_INVALID_REQUEST = -32600, + // RPC_METHOD_NOT_FOUND is internally mapped to HTTP_NOT_FOUND (404). + // It should not be used for application-layer errors. RPC_METHOD_NOT_FOUND = -32601, RPC_INVALID_PARAMS = -32602, + // RPC_INTERNAL_ERROR should only be used for genuine errors in bitcoind + // (for example datadir corruption). RPC_INTERNAL_ERROR = -32603, RPC_PARSE_ERROR = -32700, @@ -83,7 +90,7 @@ std::string JSONRPCReply(const UniValue& result, const UniValue& error, const Un UniValue JSONRPCError(int code, const std::string& message); /** Get name of RPC authentication cookie file */ -boost::filesystem::path GetAuthCookieFile(); +fs::path GetAuthCookieFile(); /** Generate a new RPC authentication cookie and write it to disk */ bool GenerateAuthCookie(std::string *cookie_out); /** Read the RPC authentication cookie from disk */ diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index bf16f27498..717e9d75f3 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -24,6 +24,7 @@ #include "uint256.h" #include "utilstrencodings.h" #ifdef ENABLE_WALLET +#include "wallet/rpcwallet.h" #include "wallet/wallet.h" #endif @@ -33,12 +34,10 @@ #include <univalue.h> -using namespace std; - void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) { txnouttype type; - vector<CTxDestination> addresses; + std::vector<CTxDestination> addresses; int nRequired; out.push_back(Pair("asm", ScriptToAsmStr(scriptPubKey))); @@ -126,7 +125,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) UniValue getrawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "getrawtransaction \"txid\" ( verbose )\n" "\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n" @@ -139,7 +138,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request) "\nArguments:\n" "1. \"txid\" (string, required) The transaction id\n" - "2. verbose (bool, optional, default=false) If true, return a string, other return a json object\n" + "2. verbose (bool, optional, default=false) If false, return a string, otherwise return a json object\n" "\nResult (if verbose is not set or set to false):\n" "\"data\" (string) The serialized, hex-encoded data for 'txid'\n" @@ -214,7 +213,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request) } else { throw JSONRPCError(RPC_TYPE_ERROR, "Invalid type provided. Verbose parameter must be a boolean."); - } + } } CTransactionRef tx; @@ -224,7 +223,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request) : "No such mempool transaction. Use -txindex to enable blockchain transaction queries") + ". Use gettransaction for wallet transactions."); - string strHex = EncodeHexTx(*tx, RPCSerializationFlags()); + std::string strHex = EncodeHexTx(*tx, RPCSerializationFlags()); if (!fVerbose) return strHex; @@ -238,7 +237,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request) UniValue gettxoutproof(const JSONRPCRequest& request) { if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2)) - throw runtime_error( + throw std::runtime_error( "gettxoutproof [\"txid\",...] ( blockhash )\n" "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n" "\nNOTE: By default this function only works sometimes. This is when there is an\n" @@ -256,16 +255,16 @@ UniValue gettxoutproof(const JSONRPCRequest& request) "\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n" ); - set<uint256> setTxids; + std::set<uint256> setTxids; uint256 oneTxid; UniValue txids = request.params[0].get_array(); for (unsigned int idx = 0; idx < txids.size(); idx++) { const UniValue& txid = txids[idx]; if (txid.get_str().length() != 64 || !IsHex(txid.get_str())) - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid txid ")+txid.get_str()); + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid txid ")+txid.get_str()); uint256 hash(uint256S(txid.get_str())); if (setTxids.count(hash)) - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated txid: ")+txid.get_str()); + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ")+txid.get_str()); setTxids.insert(hash); oneTxid = hash; } @@ -318,7 +317,7 @@ UniValue gettxoutproof(const JSONRPCRequest& request) UniValue verifytxoutproof(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "verifytxoutproof \"proof\"\n" "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n" "and throwing an RPC error if the block is not in our best chain\n" @@ -334,8 +333,8 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) UniValue res(UniValue::VARR); - vector<uint256> vMatch; - vector<unsigned int> vIndex; + std::vector<uint256> vMatch; + std::vector<unsigned int> vIndex; if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) != merkleBlock.header.hashMerkleRoot) return res; @@ -352,7 +351,7 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) UniValue createrawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw runtime_error( + throw std::runtime_error( "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime )\n" "\nCreate a transaction spending the given inputs and creating new outputs.\n" "Outputs can be addresses or data.\n" @@ -361,7 +360,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) "it is not stored in the wallet or transmitted to the network.\n" "\nArguments:\n" - "1. \"inputs\" (string, required) A json array of json objects\n" + "1. \"inputs\" (array, required) A json array of json objects\n" " [\n" " {\n" " \"txid\":\"id\", (string, required) The transaction id\n" @@ -370,7 +369,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) " } \n" " ,...\n" " ]\n" - "2. \"outputs\" (string, required) a json object with outputs\n" + "2. \"outputs\" (object, required) a json object with outputs\n" " {\n" " \"address\": x.xxx, (numeric or string, required) The key is the bitcoin address, the numeric value (can be string) is the " + CURRENCY_UNIT + " amount\n" " \"data\": \"hex\" (string, required) The key is \"data\", the value is hex encoded data\n" @@ -433,9 +432,9 @@ UniValue createrawtransaction(const JSONRPCRequest& request) rawTx.vin.push_back(in); } - set<CBitcoinAddress> setAddress; - vector<string> addrList = sendTo.getKeys(); - BOOST_FOREACH(const string& name_, addrList) { + std::set<CBitcoinAddress> setAddress; + std::vector<std::string> addrList = sendTo.getKeys(); + BOOST_FOREACH(const std::string& name_, addrList) { if (name_ == "data") { std::vector<unsigned char> data = ParseHexV(sendTo[name_].getValStr(),"Data"); @@ -445,10 +444,10 @@ UniValue createrawtransaction(const JSONRPCRequest& request) } else { CBitcoinAddress address(name_); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ")+name_); if (setAddress.count(address)) - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_); + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+name_); setAddress.insert(address); CScript scriptPubKey = GetScriptForDestination(address.Get()); @@ -465,7 +464,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) UniValue decoderawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "decoderawtransaction \"hexstring\"\n" "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n" @@ -534,7 +533,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) UniValue decodescript(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) - throw runtime_error( + throw std::runtime_error( "decodescript \"hexstring\"\n" "\nDecode a hex-encoded script.\n" "\nArguments:\n" @@ -561,7 +560,7 @@ UniValue decodescript(const JSONRPCRequest& request) UniValue r(UniValue::VOBJ); CScript script; if (request.params[0].get_str().size() > 0){ - vector<unsigned char> scriptData(ParseHexV(request.params[0], "argument")); + std::vector<unsigned char> scriptData(ParseHexV(request.params[0], "argument")); script = CScript(scriptData.begin(), scriptData.end()); } else { // Empty scripts are valid @@ -594,8 +593,12 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std:: UniValue signrawtransaction(const JSONRPCRequest& request) { +#ifdef ENABLE_WALLET + CWallet * const pwallet = GetWalletForJSONRPCRequest(request); +#endif + if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) - throw runtime_error( + throw std::runtime_error( "signrawtransaction \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] [\"privatekey1\",...] sighashtype )\n" "\nSign inputs for raw transaction (serialized, hex-encoded).\n" "The second optional argument (may be null) is an array of previous transaction outputs that\n" @@ -603,7 +606,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) "The third optional argument (may be null) is an array of base58-encoded private\n" "keys that, if given, will be the only keys used to sign the transaction.\n" #ifdef ENABLE_WALLET - + HelpRequiringPassphrase() + "\n" + + HelpRequiringPassphrase(pwallet) + "\n" #endif "\nArguments:\n" @@ -654,15 +657,15 @@ UniValue signrawtransaction(const JSONRPCRequest& request) ); #ifdef ENABLE_WALLET - LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); + LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : NULL); #else LOCK(cs_main); #endif RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true); - vector<unsigned char> txData(ParseHexV(request.params[0], "argument 1")); + std::vector<unsigned char> txData(ParseHexV(request.params[0], "argument 1")); CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); - vector<CMutableTransaction> txVariants; + std::vector<CMutableTransaction> txVariants; while (!ssData.empty()) { try { CMutableTransaction tx; @@ -717,8 +720,9 @@ UniValue signrawtransaction(const JSONRPCRequest& request) } } #ifdef ENABLE_WALLET - else if (pwalletMain) - EnsureWalletIsUnlocked(); + else if (pwallet) { + EnsureWalletIsUnlocked(pwallet); + } #endif // Add previous txouts given in the RPC call: @@ -744,13 +748,13 @@ UniValue signrawtransaction(const JSONRPCRequest& request) if (nOut < 0) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive"); - vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey")); + std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey")); CScript scriptPubKey(pkData.begin(), pkData.end()); { CCoinsModifier coins = view.ModifyCoins(txid); if (coins->IsAvailable(nOut) && coins->vout[nOut].scriptPubKey != scriptPubKey) { - string err("Previous output scriptPubKey mismatch:\n"); + std::string err("Previous output scriptPubKey mismatch:\n"); err = err + ScriptToAsmStr(coins->vout[nOut].scriptPubKey) + "\nvs:\n"+ ScriptToAsmStr(scriptPubKey); throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err); @@ -776,7 +780,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) }); UniValue v = find_value(prevOut, "redeemScript"); if (!v.isNull()) { - vector<unsigned char> rsData(ParseHexV(v, "redeemScript")); + std::vector<unsigned char> rsData(ParseHexV(v, "redeemScript")); CScript redeemScript(rsData.begin(), rsData.end()); tempKeystore.AddCScript(redeemScript); } @@ -785,23 +789,23 @@ UniValue signrawtransaction(const JSONRPCRequest& request) } #ifdef ENABLE_WALLET - const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain); + const CKeyStore& keystore = ((fGivenKeys || !pwallet) ? tempKeystore : *pwallet); #else const CKeyStore& keystore = tempKeystore; #endif int nHashType = SIGHASH_ALL; if (request.params.size() > 3 && !request.params[3].isNull()) { - static map<string, int> mapSigHashValues = + static std::map<std::string, int> mapSigHashValues = boost::assign::map_list_of - (string("ALL"), int(SIGHASH_ALL)) - (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)) - (string("NONE"), int(SIGHASH_NONE)) - (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)) - (string("SINGLE"), int(SIGHASH_SINGLE)) - (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) + (std::string("ALL"), int(SIGHASH_ALL)) + (std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)) + (std::string("NONE"), int(SIGHASH_NONE)) + (std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)) + (std::string("SINGLE"), int(SIGHASH_SINGLE)) + (std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) ; - string strHashType = request.params[3].get_str(); + std::string strHashType = request.params[3].get_str(); if (mapSigHashValues.count(strHashType)) nHashType = mapSigHashValues[strHashType]; else @@ -861,7 +865,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) UniValue sendrawtransaction(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw runtime_error( + throw std::runtime_error( "sendrawtransaction \"hexstring\" ( allowhighfees )\n" "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n" "\nAlso see createrawtransaction and signrawtransaction calls.\n" @@ -891,7 +895,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) CTransactionRef tx(MakeTransactionRef(std::move(mtx))); const uint256& hashTx = tx->GetHash(); - bool fLimitFree = false; + bool fLimitFree = true; CAmount nMaxRawTxFee = maxTxFee; if (request.params.size() > 1 && request.params[1].get_bool()) nMaxRawTxFee = 0; @@ -932,7 +936,7 @@ static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- { "rawtransactions", "getrawtransaction", &getrawtransaction, true, {"txid","verbose"} }, - { "rawtransactions", "createrawtransaction", &createrawtransaction, true, {"transactions","outputs","locktime"} }, + { "rawtransactions", "createrawtransaction", &createrawtransaction, true, {"inputs","outputs","locktime"} }, { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, {"hexstring"} }, { "rawtransactions", "decodescript", &decodescript, true, {"hexstring"} }, { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, {"hexstring","allowhighfees"} }, diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 0b763acd45..5c493428d8 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -6,6 +6,7 @@ #include "rpc/server.h" #include "base58.h" +#include "fs.h" #include "init.h" #include "random.h" #include "sync.h" @@ -16,7 +17,6 @@ #include <univalue.h> #include <boost/bind.hpp> -#include <boost/filesystem.hpp> #include <boost/foreach.hpp> #include <boost/shared_ptr.hpp> #include <boost/signals2/signal.hpp> @@ -26,9 +26,6 @@ #include <memory> // for unique_ptr #include <unordered_map> -using namespace RPCServer; -using namespace std; - static bool fRPCRunning = false; static bool fRPCInWarmup = true; static std::string rpcWarmupStatus("RPC server started"); @@ -43,7 +40,6 @@ 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) @@ -61,13 +57,8 @@ 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, + const std::list<UniValue::VType>& typesExpected, bool fAllowNull) { unsigned int i = 0; @@ -92,7 +83,7 @@ void RPCTypeCheckArgument(const UniValue& value, UniValue::VType typeExpected) } void RPCTypeCheckObj(const UniValue& o, - const map<string, UniValueType>& typesExpected, + const std::map<std::string, UniValueType>& typesExpected, bool fAllowNull, bool fStrict) { @@ -102,7 +93,7 @@ void RPCTypeCheckObj(const UniValue& o, throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first)); if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) { - string err = strprintf("Expected type %s for %s, got %s", + std::string err = strprintf("Expected type %s for %s, got %s", uvTypeName(t.second.type), t.first, uvTypeName(v.type())); throw JSONRPCError(RPC_TYPE_ERROR, err); } @@ -110,11 +101,11 @@ void RPCTypeCheckObj(const UniValue& o, if (fStrict) { - BOOST_FOREACH(const string& k, o.getKeys()) + BOOST_FOREACH(const std::string& k, o.getKeys()) { if (typesExpected.count(k) == 0) { - string err = strprintf("Unexpected key %s", k); + std::string err = strprintf("Unexpected key %s", k); throw JSONRPCError(RPC_TYPE_ERROR, err); } } @@ -143,9 +134,9 @@ UniValue ValueFromAmount(const CAmount& amount) strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder)); } -uint256 ParseHashV(const UniValue& v, string strName) +uint256 ParseHashV(const UniValue& v, std::string strName) { - string strHex; + std::string strHex; if (v.isStr()) strHex = v.get_str(); if (!IsHex(strHex)) // Note: IsHex("") is false @@ -156,20 +147,20 @@ uint256 ParseHashV(const UniValue& v, string strName) result.SetHex(strHex); return result; } -uint256 ParseHashO(const UniValue& o, string strKey) +uint256 ParseHashO(const UniValue& o, std::string strKey) { return ParseHashV(find_value(o, strKey), strKey); } -vector<unsigned char> ParseHexV(const UniValue& v, string strName) +std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName) { - string strHex; + std::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) +std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey) { return ParseHexV(find_value(o, strKey), strKey); } @@ -178,30 +169,30 @@ vector<unsigned char> ParseHexO(const UniValue& o, string strKey) * Note: This interface may still be subject to change. */ -std::string CRPCTable::help(const std::string& strCommand) const +std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const { - string strRet; - string category; - set<rpcfn_type> setDone; - vector<pair<string, const CRPCCommand*> > vCommands; + std::string strRet; + std::string category; + std::set<rpcfn_type> setDone; + std::vector<std::pair<std::string, const CRPCCommand*> > vCommands; - for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi) + for (std::map<std::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) + JSONRPCRequest jreq(helpreq); + jreq.fHelp = true; + jreq.params = UniValue(); + + BOOST_FOREACH(const PAIRTYPE(std::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; + std::string strMethod = pcmd->name; if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand) continue; + jreq.strMethod = strMethod; try { - JSONRPCRequest jreq; - jreq.fHelp = true; rpcfn_type pfn = pcmd->actor; if (setDone.insert(pfn).second) (*pfn)(jreq); @@ -209,10 +200,10 @@ std::string CRPCTable::help(const std::string& strCommand) const catch (const std::exception& e) { // Help text is returned in an exception - string strHelp = string(e.what()); + std::string strHelp = std::string(e.what()); if (strCommand == "") { - if (strHelp.find('\n') != string::npos) + if (strHelp.find('\n') != std::string::npos) strHelp = strHelp.substr(0, strHelp.find('\n')); if (category != pcmd->category) @@ -220,7 +211,7 @@ std::string CRPCTable::help(const std::string& strCommand) const if (!category.empty()) strRet += "\n"; category = pcmd->category; - string firstLetter = category.substr(0,1); + std::string firstLetter = category.substr(0,1); boost::to_upper(firstLetter); strRet += "== " + firstLetter + category.substr(1) + " ==\n"; } @@ -237,7 +228,7 @@ std::string CRPCTable::help(const std::string& strCommand) const UniValue help(const JSONRPCRequest& jsonRequest) { if (jsonRequest.fHelp || jsonRequest.params.size() > 1) - throw runtime_error( + throw std::runtime_error( "help ( \"command\" )\n" "\nList all commands, or get help for a specified command.\n" "\nArguments:\n" @@ -246,11 +237,11 @@ UniValue help(const JSONRPCRequest& jsonRequest) "\"text\" (string) The help text\n" ); - string strCommand; + std::string strCommand; if (jsonRequest.params.size() > 0) strCommand = jsonRequest.params[0].get_str(); - return tableRPC.help(strCommand); + return tableRPC.help(strCommand, jsonRequest); } @@ -258,7 +249,7 @@ UniValue stop(const JSONRPCRequest& jsonRequest) { // Accept the deprecated and ignored 'detach' boolean argument if (jsonRequest.fHelp || jsonRequest.params.size() > 1) - throw runtime_error( + throw std::runtime_error( "stop\n" "\nStop Bitcoin server."); // Event loop will exit after current HTTP requests have been handled, so @@ -292,7 +283,7 @@ CRPCTable::CRPCTable() const CRPCCommand *CRPCTable::operator[](const std::string &name) const { - map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name); + std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name); if (it == mapCommands.end()) return NULL; return (*it).second; @@ -304,7 +295,7 @@ bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd) return false; // don't allow overwriting for now - map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name); + std::map<std::string, const CRPCCommand*>::const_iterator it = mapCommands.find(name); if (it != mapCommands.end()) return false; @@ -314,7 +305,7 @@ bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd) bool StartRPC() { - LogPrint("rpc", "Starting RPC\n"); + LogPrint(BCLog::RPC, "Starting RPC\n"); fRPCRunning = true; g_rpcSignals.Started(); return true; @@ -322,15 +313,16 @@ bool StartRPC() void InterruptRPC() { - LogPrint("rpc", "Interrupting RPC\n"); + LogPrint(BCLog::RPC, "Interrupting RPC\n"); // Interrupt e.g. running longpolls fRPCRunning = false; } void StopRPC() { - LogPrint("rpc", "Stopping RPC\n"); + LogPrint(BCLog::RPC, "Stopping RPC\n"); deadlineTimers.clear(); + DeleteAuthCookie(); g_rpcSignals.Stopped(); } @@ -377,8 +369,7 @@ void JSONRPCRequest::parse(const UniValue& valRequest) 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)); + LogPrint(BCLog::RPC, "ThreadRPCServer method=%s\n", SanitizeString(strMethod)); // Parse params UniValue valParams = find_value(request, "params"); @@ -494,8 +485,6 @@ UniValue CRPCTable::execute(const JSONRPCRequest &request) const { throw JSONRPCError(RPC_MISC_ERROR, e.what()); } - - g_rpcSignals.PostCommand(*pcmd); } std::vector<std::string> CRPCTable::listCommands() const @@ -542,7 +531,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6 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()); + LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000))); } diff --git a/src/rpc/server.h b/src/rpc/server.h index 52f82866dc..34a9d3c24c 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -28,7 +28,6 @@ namespace RPCServer void OnStarted(boost::function<void ()> slot); void OnStopped(boost::function<void ()> slot); void OnPreCommand(boost::function<void (const CRPCCommand&)> slot); - void OnPostCommand(boost::function<void (const CRPCCommand&)> slot); } class CBlockIndex; @@ -69,7 +68,7 @@ void SetRPCWarmupStatus(const std::string& newStatus); void SetRPCWarmupFinished(); /* returns the current warmup state. */ -bool RPCIsInWarmup(std::string *statusOut); +bool RPCIsInWarmup(std::string *outStatus); /** * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that @@ -154,7 +153,7 @@ private: public: CRPCTable(); const CRPCCommand* operator[](const std::string& name) const; - std::string help(const std::string& name) const; + std::string help(const std::string& name, const JSONRPCRequest& helpreq) const; /** * Execute a method. @@ -190,21 +189,15 @@ extern uint256 ParseHashO(const UniValue& o, std::string strKey); extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName); extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey); -extern int64_t nWalletUnlockTime; extern CAmount AmountFromValue(const UniValue& value); extern UniValue ValueFromAmount(const CAmount& amount); -extern double GetDifficulty(const CBlockIndex* blockindex = NULL); -extern std::string HelpRequiringPassphrase(); extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); -extern void EnsureWalletIsUnlocked(); - bool StartRPC(); void InterruptRPC(); void StopRPC(); std::string JSONRPCExecBatch(const UniValue& vReq); -void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); // Retrieves any serialization flags requested in command line argument int RPCSerializationFlags(); |