aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/blockchain.cpp130
-rw-r--r--src/rpc/blockchain.h40
-rw-r--r--src/rpc/client.cpp13
-rw-r--r--src/rpc/mining.cpp143
-rw-r--r--src/rpc/misc.cpp73
-rw-r--r--src/rpc/net.cpp34
-rw-r--r--src/rpc/protocol.cpp12
-rw-r--r--src/rpc/protocol.h5
-rw-r--r--src/rpc/rawtransaction.cpp89
-rw-r--r--src/rpc/server.cpp36
-rw-r--r--src/rpc/server.h14
11 files changed, 429 insertions, 160 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index bec87e613a..b4b160aac9 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"
@@ -10,6 +12,8 @@
#include "coins.h"
#include "consensus/validation.h"
#include "validation.h"
+#include "core_io.h"
+#include "policy/feerate.h"
#include "policy/policy.h"
#include "primitives/transaction.h"
#include "rpc/server.h"
@@ -40,15 +44,7 @@ static std::condition_variable cond_blockchange;
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)
@@ -106,7 +102,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()));
@@ -128,7 +124,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
if(txDetails)
{
UniValue objTx(UniValue::VOBJ);
- TxToJSON(*tx, uint256(), objTx);
+ TxToUniv(*tx, uint256(), objTx);
txs.push_back(objTx);
}
else
@@ -383,7 +379,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)
{
@@ -417,6 +413,7 @@ UniValue getrawmempool(const JSONRPCRequest& request)
throw std::runtime_error(
"getrawmempool ( verbose )\n"
"\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
+ "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n"
"\nArguments:\n"
"1. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
"\nResult: (for verbose = false):\n"
@@ -691,13 +688,16 @@ UniValue getblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
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"
+ "getblock \"blockhash\" ( verbosity ) \n"
+ "\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
+ "If verbosity is 1, returns an Object with information about block <hash>.\n"
+ "If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n"
"\nArguments:\n"
"1. \"blockhash\" (string, required) The block hash\n"
- "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
- "\nResult (for verbose = true):\n"
+ "2. verbosity (numeric, optional, default=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data\n"
+ "\nResult (for verbosity = 0):\n"
+ "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
+ "\nResult (for verbosity = 1):\n"
"{\n"
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
@@ -721,8 +721,14 @@ UniValue getblock(const JSONRPCRequest& request)
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
" \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
"}\n"
- "\nResult (for verbose=false):\n"
- "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
+ "\nResult (for verbosity = 2):\n"
+ "{\n"
+ " ..., Same output as verbosity = 1.\n"
+ " \"tx\" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result.\n"
+ " ,...\n"
+ " ],\n"
+ " ,... Same output as verbosity = 1.\n"
+ "}\n"
"\nExamples:\n"
+ HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
@@ -733,9 +739,13 @@ UniValue getblock(const JSONRPCRequest& request)
std::string strHash = request.params[0].get_str();
uint256 hash(uint256S(strHash));
- bool fVerbose = true;
- if (request.params.size() > 1)
- fVerbose = request.params[1].get_bool();
+ int verbosity = 1;
+ if (request.params.size() > 1) {
+ if(request.params[1].isNum())
+ verbosity = request.params[1].get_int();
+ else
+ verbosity = request.params[1].get_bool() ? 1 : 0;
+ }
if (mapBlockIndex.count(hash) == 0)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
@@ -754,7 +764,7 @@ UniValue getblock(const JSONRPCRequest& request)
// block).
throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
- if (!fVerbose)
+ if (verbosity <= 0)
{
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
ssBlock << block;
@@ -762,7 +772,7 @@ UniValue getblock(const JSONRPCRequest& request)
return strHex;
}
- return blockToJSON(block, pblockindex);
+ return blockToJSON(block, pblockindex, verbosity >= 2);
}
struct CCoinsStats
@@ -860,7 +870,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request)
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;
}
@@ -980,7 +990,7 @@ UniValue gettxout(const JSONRPCRequest& request)
ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
UniValue o(UniValue::VOBJ);
- ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
+ ScriptPubKeyToUniv(coins.vout[n].scriptPubKey, o, true);
ret.push_back(Pair("scriptPubKey", o));
ret.push_back(Pair("version", coins.nVersion));
ret.push_back(Pair("coinbase", coins.fCoinBase));
@@ -1438,13 +1448,79 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
return NullUniValue;
}
+UniValue getchaintxstats(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 2)
+ throw std::runtime_error(
+ "getchaintxstats ( nblocks blockhash )\n"
+ "\nCompute statistics about the total number and rate of transactions in the chain.\n"
+ "\nArguments:\n"
+ "1. nblocks (numeric, optional) Size of the window in number of blocks (default: one month).\n"
+ "2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n"
+ "\nResult:\n"
+ "{\n"
+ " \"time\": xxxxx, (numeric) The timestamp for the statistics in UNIX format.\n"
+ " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
+ " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window.\n"
+ "}\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getchaintxstats", "")
+ + HelpExampleRpc("getchaintxstats", "2016")
+ );
+
+ const CBlockIndex* pindex;
+ int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
+
+ if (request.params.size() > 0 && !request.params[0].isNull()) {
+ blockcount = request.params[0].get_int();
+ }
+
+ bool havehash = request.params.size() > 1 && !request.params[1].isNull();
+ uint256 hash;
+ if (havehash) {
+ hash = uint256S(request.params[1].get_str());
+ }
+
+ {
+ LOCK(cs_main);
+ if (havehash) {
+ auto it = mapBlockIndex.find(hash);
+ if (it == mapBlockIndex.end()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+ pindex = it->second;
+ if (!chainActive.Contains(pindex)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain");
+ }
+ } else {
+ pindex = chainActive.Tip();
+ }
+ }
+
+ if (blockcount < 1 || blockcount >= pindex->nHeight) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height");
+ }
+
+ const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount);
+ int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast();
+ int nTxDiff = pindex->nChainTx - pindexPast->nChainTx;
+
+ UniValue ret(UniValue::VOBJ);
+ ret.push_back(Pair("time", (int64_t)pindex->nTime));
+ ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx));
+ ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff));
+
+ return ret;
+}
+
static const CRPCCommand commands[] =
{ // category name actor (function) okSafe argNames
// --------------------- ------------------------ ----------------------- ------ ----------
{ "blockchain", "getblockchaininfo", &getblockchaininfo, true, {} },
+ { "blockchain", "getchaintxstats", &getchaintxstats, true, {"nblocks", "blockhash"} },
{ "blockchain", "getbestblockhash", &getbestblockhash, true, {} },
{ "blockchain", "getblockcount", &getblockcount, true, {} },
- { "blockchain", "getblock", &getblock, true, {"blockhash","verbose"} },
+ { "blockchain", "getblock", &getblock, true, {"blockhash","verbosity|verbose"} },
{ "blockchain", "getblockhash", &getblockhash, true, {"height"} },
{ "blockchain", "getblockheader", &getblockheader, true, {"blockhash","verbose"} },
{ "blockchain", "getchaintips", &getchaintips, true, {} },
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 2cb250a198..a3a692c14d 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -77,11 +77,13 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listunspent", 0, "minconf" },
{ "listunspent", 1, "maxconf" },
{ "listunspent", 2, "addresses" },
- { "getblock", 1, "verbose" },
+ { "listunspent", 4, "query_options" },
+ { "getblock", 1, "verbosity" },
{ "getblockheader", 1, "verbose" },
+ { "getchaintxstats", 0, "nblocks" },
{ "gettransaction", 1, "include_watchonly" },
{ "getrawtransaction", 1, "verbose" },
- { "createrawtransaction", 0, "transactions" },
+ { "createrawtransaction", 0, "inputs" },
{ "createrawtransaction", 1, "outputs" },
{ "createrawtransaction", 2, "locktime" },
{ "signrawtransaction", 1, "prevtxs" },
@@ -106,6 +108,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getrawmempool", 0, "verbose" },
{ "estimatefee", 0, "nblocks" },
{ "estimatesmartfee", 0, "nblocks" },
+ { "estimatesmartfee", 1, "conservative" },
+ { "estimaterawfee", 0, "nblocks" },
+ { "estimaterawfee", 1, "threshold" },
+ { "estimaterawfee", 2, "horizon" },
{ "prioritisetransaction", 1, "fee_delta" },
{ "setban", 2, "bantime" },
{ "setban", 3, "absolute" },
@@ -113,6 +119,9 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getmempoolancestors", 1, "verbose" },
{ "getmempooldescendants", 1, "verbose" },
{ "bumpfee", 1, "options" },
+ { "logging", 0, "include" },
+ { "logging", 1, "exclude" },
+ { "disconnectnode", 1, "nodeid" },
// Echo with conversion (For testing only)
{ "echojson", 0, "arg0" },
{ "echojson", 1, "arg1" },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 4db8ffaa7d..d744269df1 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -15,7 +15,9 @@
#include "validation.h"
#include "miner.h"
#include "net.h"
+#include "policy/fees.h"
#include "pow.h"
+#include "rpc/blockchain.h"
#include "rpc/server.h"
#include "txmempool.h"
#include "util.h"
@@ -26,7 +28,6 @@
#include <stdint.h>
#include <boost/assign/list_of.hpp>
-#include <boost/shared_ptr.hpp>
#include <univalue.h>
@@ -94,7 +95,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;
@@ -166,7 +167,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.
@@ -207,7 +208,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request)
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);
@@ -709,7 +710,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;
@@ -719,7 +720,7 @@ protected:
UniValue submitblock(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
+ 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"
@@ -737,11 +738,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;
@@ -750,10 +757,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;
}
@@ -771,14 +780,15 @@ 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);
}
@@ -787,6 +797,7 @@ UniValue estimatefee(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"estimatefee nblocks\n"
+ "\nDEPRECATED. Please use estimatesmartfee for more intelligent estimates."
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
"confirmation within nblocks blocks. Uses virtual transaction size of transaction\n"
"as defined in BIP 141 (witness data is discounted).\n"
@@ -809,7 +820,7 @@ UniValue estimatefee(const JSONRPCRequest& request)
if (nBlocks < 1)
nBlocks = 1;
- CFeeRate feeRate = mempool.estimateFee(nBlocks);
+ CFeeRate feeRate = ::feeEstimator.estimateFee(nBlocks);
if (feeRate == CFeeRate(0))
return -1.0;
@@ -818,16 +829,19 @@ UniValue estimatefee(const JSONRPCRequest& request)
UniValue estimatesmartfee(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "estimatesmartfee nblocks\n"
- "\nWARNING: This interface is unstable and may disappear or change!\n"
+ "estimatesmartfee nblocks (conservative)\n"
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
"confirmation within nblocks blocks if possible and return the number of blocks\n"
"for which the estimate is valid. Uses virtual transaction size as defined\n"
"in BIP 141 (witness data is discounted).\n"
"\nArguments:\n"
- "1. nblocks (numeric)\n"
+ "1. nblocks (numeric)\n"
+ "2. conservative (bool, optional, default=true) Whether to return a more conservative estimate which\n"
+ " also satisfies a longer history. A conservative estimate potentially returns a higher\n"
+ " feerate and is more likely to be sufficient for the desired target, but is not as\n"
+ " responsive to short term drops in the prevailing fee market\n"
"\nResult:\n"
"{\n"
" \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n"
@@ -844,15 +858,102 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM));
int nBlocks = request.params[0].get_int();
+ bool conservative = true;
+ if (request.params.size() > 1 && !request.params[1].isNull()) {
+ RPCTypeCheckArgument(request.params[1], UniValue::VBOOL);
+ conservative = request.params[1].get_bool();
+ }
UniValue result(UniValue::VOBJ);
int answerFound;
- CFeeRate feeRate = mempool.estimateSmartFee(nBlocks, &answerFound);
+ CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &answerFound, ::mempool, conservative);
result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK())));
result.push_back(Pair("blocks", answerFound));
return result;
}
+UniValue estimaterawfee(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() < 1|| request.params.size() > 3)
+ throw std::runtime_error(
+ "estimaterawfee nblocks (threshold horizon)\n"
+ "\nWARNING: This interface is unstable and may disappear or change!\n"
+ "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n"
+ " implementation of fee estimation. The parameters it can be called with\n"
+ " and the results it returns will change if the internal implementation changes.\n"
+ "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
+ "confirmation within nblocks blocks if possible. Uses virtual transaction size as defined\n"
+ "in BIP 141 (witness data is discounted).\n"
+ "\nArguments:\n"
+ "1. nblocks (numeric)\n"
+ "2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n"
+ " confirmed within nblocks in order to consider those feerates as high enough and proceed to check\n"
+ " lower buckets. Default: 0.95\n"
+ "3. horizon (numeric, optional) How long a history of estimates to consider. 0=short, 1=medium, 2=long.\n"
+ " Default: 1\n"
+ "\nResult:\n"
+ "{\n"
+ " \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n"
+ " \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n"
+ " \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n"
+ " \"pass\" : { (json object) information about the lowest range of feerates to succeed in meeting the threshold\n"
+ " \"startrange\" : x.x, (numeric) start of feerate range\n"
+ " \"endrange\" : x.x, (numeric) end of feerate range\n"
+ " \"withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n"
+ " \"totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n"
+ " \"inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n"
+ " \"leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n"
+ " }\n"
+ " \"fail\" : { ... } (json object) information about the highest range of feerates to fail to meet the threshold\n"
+ "}\n"
+ "\n"
+ "A negative feerate is returned if no answer can be given.\n"
+ "\nExample:\n"
+ + HelpExampleCli("estimaterawfee", "6 0.9 1")
+ );
+
+ RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)(UniValue::VNUM)(UniValue::VNUM), true);
+ RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
+ int nBlocks = request.params[0].get_int();
+ double threshold = 0.95;
+ if (!request.params[1].isNull())
+ threshold = request.params[1].get_real();
+ FeeEstimateHorizon horizon = FeeEstimateHorizon::MED_HALFLIFE;
+ if (!request.params[2].isNull()) {
+ int horizonInt = request.params[2].get_int();
+ if (horizonInt < 0 || horizonInt > 2) {
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid horizon for fee estimates");
+ } else {
+ horizon = (FeeEstimateHorizon)horizonInt;
+ }
+ }
+ UniValue result(UniValue::VOBJ);
+ CFeeRate feeRate;
+ EstimationResult buckets;
+ feeRate = ::feeEstimator.estimateRawFee(nBlocks, threshold, horizon, &buckets);
+
+ result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK())));
+ result.push_back(Pair("decay", buckets.decay));
+ result.push_back(Pair("scale", (int)buckets.scale));
+ UniValue passbucket(UniValue::VOBJ);
+ passbucket.push_back(Pair("startrange", round(buckets.pass.start)));
+ passbucket.push_back(Pair("endrange", round(buckets.pass.end)));
+ passbucket.push_back(Pair("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0));
+ passbucket.push_back(Pair("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0));
+ passbucket.push_back(Pair("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0));
+ passbucket.push_back(Pair("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0));
+ result.push_back(Pair("pass", passbucket));
+ UniValue failbucket(UniValue::VOBJ);
+ failbucket.push_back(Pair("startrange", round(buckets.fail.start)));
+ failbucket.push_back(Pair("endrange", round(buckets.fail.end)));
+ failbucket.push_back(Pair("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0));
+ failbucket.push_back(Pair("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0));
+ failbucket.push_back(Pair("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0));
+ failbucket.push_back(Pair("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0));
+ result.push_back(Pair("fail", failbucket));
+ return result;
+}
+
static const CRPCCommand commands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
@@ -866,7 +967,9 @@ static const CRPCCommand commands[] =
{ "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} },
{ "util", "estimatefee", &estimatefee, true, {"nblocks"} },
- { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks"} },
+ { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "conservative"} },
+
+ { "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold", "horizon"} },
};
void RegisterMiningRPCCommands(CRPCTable &t)
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index de1bbe62e5..1f973a0c18 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -4,11 +4,14 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
+#include "chain.h"
#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"
@@ -554,6 +557,73 @@ UniValue getmemoryinfo(const JSONRPCRequest& request)
}
}
+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)
@@ -580,7 +650,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 44c6e6d308..cde5ae723b 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -234,23 +234,43 @@ UniValue addnode(const JSONRPCRequest& request)
UniValue disconnectnode(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
+ if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3)
throw std::runtime_error(
- "disconnectnode \"node\" \n"
- "\nImmediately disconnects from the specified node.\n"
+ "disconnectnode \"[address]\" [nodeid]\n"
+ "\nImmediately disconnects from the specified peer node.\n"
+ "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
+ "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n"
"\nArguments:\n"
- "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n"
+ "1. \"address\" (string, optional) The IP address/port of the node\n"
+ "2. \"nodeid\" (number, optional) The node ID (see getpeerinfo for node IDs)\n"
"\nExamples:\n"
+ HelpExampleCli("disconnectnode", "\"192.168.0.6:8333\"")
+ + HelpExampleCli("disconnectnode", "\"\" 1")
+ HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
+ + HelpExampleRpc("disconnectnode", "\"\", 1")
);
if(!g_connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- bool ret = g_connman->DisconnectNode(request.params[0].get_str());
- if (!ret)
+ bool success;
+ const UniValue &address_arg = request.params[0];
+ const UniValue &id_arg = request.params.size() < 2 ? NullUniValue : request.params[1];
+
+ if (!address_arg.isNull() && id_arg.isNull()) {
+ /* handle disconnect-by-address */
+ success = g_connman->DisconnectNode(address_arg.get_str());
+ } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
+ /* handle disconnect-by-id */
+ NodeId nodeid = (NodeId) id_arg.get_int64();
+ success = g_connman->DisconnectNode(nodeid);
+ } else {
+ throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
+ }
+
+ if (!success) {
throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
+ }
return NullUniValue;
}
@@ -607,7 +627,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", "nodeid"} },
{ "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 2be1edb5a6..823a5775f6 100644
--- a/src/rpc/protocol.cpp
+++ b/src/rpc/protocol.cpp
@@ -66,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;
}
@@ -84,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());
@@ -103,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;
@@ -118,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 85bc4db101..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>
@@ -89,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 696f1bd781..683bb25246 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -34,77 +34,15 @@
#include <univalue.h>
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex)
-{
- txnouttype type;
- std::vector<CTxDestination> addresses;
- int nRequired;
-
- out.push_back(Pair("asm", ScriptToAsmStr(scriptPubKey)));
- if (fIncludeHex)
- out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
-
- if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
- out.push_back(Pair("type", GetTxnOutputType(type)));
- return;
- }
-
- out.push_back(Pair("reqSigs", nRequired));
- out.push_back(Pair("type", GetTxnOutputType(type)));
-
- UniValue a(UniValue::VARR);
- BOOST_FOREACH(const CTxDestination& addr, addresses)
- a.push_back(CBitcoinAddress(addr).ToString());
- out.push_back(Pair("addresses", a));
-}
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
{
- entry.push_back(Pair("txid", tx.GetHash().GetHex()));
- entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex()));
- entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
- entry.push_back(Pair("vsize", (int)::GetVirtualTransactionSize(tx)));
- entry.push_back(Pair("version", tx.nVersion));
- entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
-
- UniValue vin(UniValue::VARR);
- for (unsigned int i = 0; i < tx.vin.size(); i++) {
- const CTxIn& txin = tx.vin[i];
- UniValue in(UniValue::VOBJ);
- if (tx.IsCoinBase())
- in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
- else {
- in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
- in.push_back(Pair("vout", (int64_t)txin.prevout.n));
- UniValue o(UniValue::VOBJ);
- o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true)));
- o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
- in.push_back(Pair("scriptSig", o));
- }
- if (tx.HasWitness()) {
- UniValue txinwitness(UniValue::VARR);
- for (unsigned int j = 0; j < tx.vin[i].scriptWitness.stack.size(); j++) {
- std::vector<unsigned char> item = tx.vin[i].scriptWitness.stack[j];
- txinwitness.push_back(HexStr(item.begin(), item.end()));
- }
- in.push_back(Pair("txinwitness", txinwitness));
- }
- in.push_back(Pair("sequence", (int64_t)txin.nSequence));
- vin.push_back(in);
- }
- entry.push_back(Pair("vin", vin));
- UniValue vout(UniValue::VARR);
- for (unsigned int i = 0; i < tx.vout.size(); i++) {
- const CTxOut& txout = tx.vout[i];
- UniValue out(UniValue::VOBJ);
- out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
- out.push_back(Pair("n", (int64_t)i));
- UniValue o(UniValue::VOBJ);
- ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
- out.push_back(Pair("scriptPubKey", o));
- vout.push_back(out);
- }
- entry.push_back(Pair("vout", vout));
+ // Call into TxToUniv() in bitcoin-common to decode the transaction hex.
+ //
+ // Blockchain contextual information (confirmations and blocktime) is not
+ // available to code in bitcoin-common, so we query them here and push the
+ // data into the returned UniValue.
+ TxToUniv(tx, uint256(), entry);
if (!hashBlock.IsNull()) {
entry.push_back(Pair("blockhash", hashBlock.GetHex()));
@@ -360,7 +298,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"
@@ -369,7 +307,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"
@@ -525,7 +463,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
UniValue result(UniValue::VOBJ);
- TxToJSON(CTransaction(std::move(mtx)), uint256(), result);
+ TxToUniv(CTransaction(std::move(mtx)), uint256(), result);
return result;
}
@@ -565,7 +503,7 @@ UniValue decodescript(const JSONRPCRequest& request)
} else {
// Empty scripts are valid
}
- ScriptPubKeyToJSON(script, r, false);
+ ScriptPubKeyToUniv(script, r, false);
UniValue type;
type = find_value(r, "type");
@@ -585,6 +523,11 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("txid", txin.prevout.hash.ToString()));
entry.push_back(Pair("vout", (uint64_t)txin.prevout.n));
+ UniValue witness(UniValue::VARR);
+ for (unsigned int i = 0; i < txin.scriptWitness.stack.size(); i++) {
+ witness.push_back(HexStr(txin.scriptWitness.stack[i].begin(), txin.scriptWitness.stack[i].end()));
+ }
+ entry.push_back(Pair("witness", witness));
entry.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
entry.push_back(Pair("sequence", (uint64_t)txin.nSequence));
entry.push_back(Pair("error", strMessage));
@@ -936,7 +879,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 9b0699afcc..c5fbff0077 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,12 +17,13 @@
#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>
#include <boost/thread.hpp>
#include <boost/algorithm/string/case_conv.hpp> // for to_upper()
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
#include <memory> // for unique_ptr
#include <unordered_map>
@@ -42,17 +44,17 @@ static struct CRPCSignals
boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
} g_rpcSignals;
-void RPCServer::OnStarted(boost::function<void ()> slot)
+void RPCServer::OnStarted(std::function<void ()> slot)
{
g_rpcSignals.Started.connect(slot);
}
-void RPCServer::OnStopped(boost::function<void ()> slot)
+void RPCServer::OnStopped(std::function<void ()> slot)
{
g_rpcSignals.Stopped.connect(slot);
}
-void RPCServer::OnPreCommand(boost::function<void (const CRPCCommand&)> slot)
+void RPCServer::OnPreCommand(std::function<void (const CRPCCommand&)> slot)
{
g_rpcSignals.PreCommand.connect(boost::bind(slot, _1));
}
@@ -305,7 +307,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;
@@ -313,15 +315,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();
}
@@ -368,8 +371,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");
@@ -432,8 +434,16 @@ static inline JSONRPCRequest transformNamedArguments(const JSONRPCRequest& in, c
}
// Process expected parameters.
int hole = 0;
- for (const std::string &argName: argNames) {
- auto fr = argsIn.find(argName);
+ for (const std::string &argNamePattern: argNames) {
+ std::vector<std::string> vargNames;
+ boost::algorithm::split(vargNames, argNamePattern, boost::algorithm::is_any_of("|"));
+ auto fr = argsIn.end();
+ for (const std::string & argName : vargNames) {
+ fr = argsIn.find(argName);
+ if (fr != argsIn.end()) {
+ break;
+ }
+ }
if (fr != argsIn.end()) {
for (int i = 0; i < hole; ++i) {
// Fill hole between specified parameters with JSON nulls,
@@ -526,12 +536,12 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface)
timerInterface = NULL;
}
-void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds)
+void RPCRunLater(const std::string& name, std::function<void(void)> func, int64_t nSeconds)
{
if (!timerInterface)
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
deadlineTimers.erase(name);
- LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
+ 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 de14c7ed3e..1e984cbc0d 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -15,8 +15,6 @@
#include <stdint.h>
#include <string>
-#include <boost/function.hpp>
-
#include <univalue.h>
static const unsigned int DEFAULT_RPC_SERIALIZE_VERSION = 1;
@@ -25,9 +23,9 @@ class CRPCCommand;
namespace RPCServer
{
- void OnStarted(boost::function<void ()> slot);
- void OnStopped(boost::function<void ()> slot);
- void OnPreCommand(boost::function<void (const CRPCCommand&)> slot);
+ void OnStarted(std::function<void ()> slot);
+ void OnStopped(std::function<void ()> slot);
+ void OnPreCommand(std::function<void (const CRPCCommand&)> slot);
}
class CBlockIndex;
@@ -115,7 +113,7 @@ public:
* This is needed to cope with the case in which there is no HTTP server, but
* only GUI RPC console, and to break the dependency of pcserver on httprpc.
*/
- virtual RPCTimerBase* NewTimer(boost::function<void(void)>& func, int64_t millis) = 0;
+ virtual RPCTimerBase* NewTimer(std::function<void(void)>& func, int64_t millis) = 0;
};
/** Set the factory function for timers */
@@ -129,7 +127,7 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface);
* Run func nSeconds from now.
* Overrides previous timer <name> (if any).
*/
-void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds);
+void RPCRunLater(const std::string& name, std::function<void(void)> func, int64_t nSeconds);
typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest);
@@ -191,7 +189,6 @@ extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKe
extern CAmount AmountFromValue(const UniValue& value);
extern UniValue ValueFromAmount(const CAmount& amount);
-extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
@@ -199,7 +196,6 @@ 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();