diff options
Diffstat (limited to 'src/rpc/blockchain.cpp')
-rw-r--r-- | src/rpc/blockchain.cpp | 305 |
1 files changed, 181 insertions, 124 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c17ca2fa3a..b7895b86f7 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -3,27 +3,28 @@ // 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" -#include "checkpoints.h" -#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" -#include "streams.h" -#include "sync.h" -#include "txdb.h" -#include "txmempool.h" -#include "util.h" -#include "utilstrencodings.h" -#include "hash.h" +#include <rpc/blockchain.h> + +#include <amount.h> +#include <chain.h> +#include <chainparams.h> +#include <checkpoints.h> +#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> +#include <streams.h> +#include <sync.h> +#include <txdb.h> +#include <txmempool.h> +#include <util.h> +#include <utilstrencodings.h> +#include <hash.h> +#include <warnings.h> #include <stdint.h> @@ -48,9 +49,9 @@ extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& double GetDifficulty(const CBlockIndex* blockindex) { - if (blockindex == NULL) + if (blockindex == nullptr) { - if (chainActive.Tip() == NULL) + if (chainActive.Tip() == nullptr) return 1.0; else blockindex = chainActive.Tip(); @@ -77,6 +78,7 @@ double GetDifficulty(const CBlockIndex* blockindex) UniValue blockheaderToJSON(const CBlockIndex* blockindex) { + AssertLockHeld(cs_main); UniValue result(UniValue::VOBJ); result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); int confirmations = -1; @@ -105,6 +107,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) { + AssertLockHeld(cs_main); UniValue result(UniValue::VOBJ); result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); int confirmations = -1; @@ -125,7 +128,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx if(txDetails) { UniValue objTx(UniValue::VOBJ); - TxToUniv(*tx, uint256(), objTx); + TxToUniv(*tx, uint256(), objTx, true, RPCSerializationFlags()); txs.push_back(objTx); } else @@ -210,7 +213,7 @@ UniValue waitfornewblock(const JSONRPCRequest& request) + HelpExampleRpc("waitfornewblock", "1000") ); int timeout = 0; - if (request.params.size() > 0) + if (!request.params[0].isNull()) timeout = request.params[0].get_int(); CUpdatedBlock block; @@ -252,7 +255,7 @@ UniValue waitforblock(const JSONRPCRequest& request) uint256 hash = uint256S(request.params[0].get_str()); - if (request.params.size() > 1) + if (!request.params[1].isNull()) timeout = request.params[1].get_int(); CUpdatedBlock block; @@ -295,7 +298,7 @@ UniValue waitforblockheight(const JSONRPCRequest& request) int height = request.params[0].get_int(); - if (request.params.size() > 1) + if (!request.params[1].isNull()) timeout = request.params[1].get_int(); CUpdatedBlock block; @@ -343,6 +346,7 @@ std::string EntryDescriptionString() " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n" " \"ancestorsize\" : n, (numeric) virtual transaction size of in-mempool ancestors (including this one)\n" " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one)\n" + " \"wtxid\" : hash, (string) hash of serialized transaction, including witness data\n" " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" " \"transactionid\", (string) parent transaction id\n" " ... ]\n"; @@ -363,6 +367,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) info.push_back(Pair("ancestorcount", e.GetCountWithAncestors())); info.push_back(Pair("ancestorsize", e.GetSizeWithAncestors())); info.push_back(Pair("ancestorfees", e.GetModFeesWithAncestors())); + info.push_back(Pair("wtxid", mempool.vTxHashes[e.vTxHashesIdx].first.ToString())); const CTransaction& tx = e.GetTx(); std::set<std::string> setDepends; for (const CTxIn& txin : tx.vin) @@ -434,7 +439,7 @@ UniValue getrawmempool(const JSONRPCRequest& request) ); bool fVerbose = false; - if (request.params.size() > 0) + if (!request.params[0].isNull()) fVerbose = request.params[0].get_bool(); return mempoolToJSON(fVerbose); @@ -467,7 +472,7 @@ UniValue getmempoolancestors(const JSONRPCRequest& request) } bool fVerbose = false; - if (request.params.size() > 1) + if (!request.params[1].isNull()) fVerbose = request.params[1].get_bool(); uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -531,7 +536,7 @@ UniValue getmempooldescendants(const JSONRPCRequest& request) } bool fVerbose = false; - if (request.params.size() > 1) + if (!request.params[1].isNull()) fVerbose = request.params[1].get_bool(); uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -666,7 +671,7 @@ UniValue getblockheader(const JSONRPCRequest& request) uint256 hash(uint256S(strHash)); bool fVerbose = true; - if (request.params.size() > 1) + if (!request.params[1].isNull()) fVerbose = request.params[1].get_bool(); if (mapBlockIndex.count(hash) == 0) @@ -741,7 +746,7 @@ UniValue getblock(const JSONRPCRequest& request) uint256 hash(uint256S(strHash)); int verbosity = 1; - if (request.params.size() > 1) { + if (!request.params[1].isNull()) { if(request.params[1].isNum()) verbosity = request.params[1].get_int(); else @@ -798,7 +803,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, stats.nTransactions++; for (const auto output : outputs) { ss << VARINT(output.first + 1); - ss << *(const CScriptBase*)(&output.second.out.scriptPubKey); + ss << output.second.out.scriptPubKey; ss << VARINT(output.second.out.nValue); stats.nTransactionOutputs++; stats.nTotalAmount += output.second.out.nValue; @@ -812,6 +817,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) { std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor()); + assert(pcursor); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = pcursor->GetBestBlock(); @@ -922,7 +928,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) CCoinsStats stats; FlushStateToDisk(); - if (GetUTXOStats(pcoinsdbview, stats)) { + if (GetUTXOStats(pcoinsdbview.get(), stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); @@ -944,9 +950,10 @@ UniValue gettxout(const JSONRPCRequest& request) "gettxout \"txid\" n ( include_mempool )\n" "\nReturns details about an unspent transaction output.\n" "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id\n" - "2. n (numeric, required) vout number\n" - "3. include_mempool (boolean, optional) Whether to include the mempool\n" + "1. \"txid\" (string, required) The transaction id\n" + "2. \"n\" (numeric, required) vout number\n" + "3. \"include_mempool\" (boolean, optional) Whether to include the mempool. Default: true." + " Note that an unspent output that is spent in the mempool won't appear.\n" "\nResult:\n" "{\n" " \"bestblock\" : \"hash\", (string) the block hash\n" @@ -962,7 +969,6 @@ UniValue gettxout(const JSONRPCRequest& request) " ,...\n" " ]\n" " },\n" - " \"version\" : n, (numeric) The version\n" " \"coinbase\" : true|false (boolean) Coinbase or not\n" "}\n" @@ -984,13 +990,13 @@ UniValue gettxout(const JSONRPCRequest& request) int n = request.params[1].get_int(); COutPoint out(hash, n); bool fMempool = true; - if (request.params.size() > 2) + if (!request.params[2].isNull()) fMempool = request.params[2].get_bool(); Coin coin; if (fMempool) { LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); + CCoinsViewMemPool view(pcoinsTip.get(), mempool); if (!view.GetCoin(out, coin) || mempool.isSpent(out)) { return NullUniValue; } @@ -1019,8 +1025,8 @@ UniValue gettxout(const JSONRPCRequest& request) UniValue verifychain(const JSONRPCRequest& request) { - int nCheckLevel = GetArg("-checklevel", DEFAULT_CHECKLEVEL); - int nCheckDepth = GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); + int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); + int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); if (request.fHelp || request.params.size() > 2) throw std::runtime_error( "verifychain ( checklevel nblocks )\n" @@ -1037,12 +1043,12 @@ UniValue verifychain(const JSONRPCRequest& request) LOCK(cs_main); - if (request.params.size() > 0) + if (!request.params[0].isNull()) nCheckLevel = request.params[0].get_int(); - if (request.params.size() > 1) + if (!request.params[1].isNull()) nCheckDepth = request.params[1].get_int(); - return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth); + return CVerifyDB().VerifyDB(Params(), pcoinsTip.get(), nCheckLevel, nCheckDepth); } /** Implementation of IsSuperMajority with better feedback */ @@ -1107,13 +1113,13 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse return rv; } -void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) { // Deployments with timeout value of 0 are hidden. // A timeout value of 0 guarantees a softfork will never be activated. // This is used when softfork codes are merged without specifying the deployment schedule. if (consensusParams.vDeployments[id].nTimeout > 0) - bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id))); + bip9_softforks.push_back(Pair(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id))); } UniValue getblockchaininfo(const JSONRPCRequest& request) @@ -1124,41 +1130,46 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) "Returns an object containing various state info regarding blockchain processing.\n" "\nResult:\n" "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" + " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" + " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" + " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" + " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" + " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" - " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored\n" - " \"softforks\": [ (array) status of softforks in progress\n" + " \"initialblockdownload\": xxxx, (bool) (debug information) estimate of whether this node is in Initial Block Download mode.\n" + " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" + " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" + " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" + " \"pruneheight\": xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n" + " \"automatic_pruning\": xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n" + " \"prune_target_size\": xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n" + " \"softforks\": [ (array) status of softforks in progress\n" " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" + " \"id\": \"xxxx\", (string) name of softfork\n" + " \"version\": xx, (numeric) block version\n" + " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n" + " \"status\": xx, (boolean) true if threshold reached\n" " },\n" " }, ...\n" " ],\n" - " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" - " \"xxxx\" : { (string) name of the softfork\n" - " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" - " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" - " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" - " \"since\": xx, (numeric) height of the first block to which the status applies\n" - " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" - " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n" - " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" - " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" - " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n" - " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" + " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" + " \"xxxx\" : { (string) name of the softfork\n" + " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" + " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" + " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" + " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" + " \"since\": xx, (numeric) height of the first block to which the status applies\n" + " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" + " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n" + " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" + " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" + " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n" + " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" " }\n" " }\n" " }\n" + " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblockchaininfo", "") @@ -1175,8 +1186,26 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast())); obj.push_back(Pair("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip()))); + obj.push_back(Pair("initialblockdownload", IsInitialBlockDownload())); obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); + obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); obj.push_back(Pair("pruned", fPruneMode)); + if (fPruneMode) { + CBlockIndex* block = chainActive.Tip(); + assert(block); + while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) { + block = block->pprev; + } + + obj.push_back(Pair("pruneheight", block->nHeight)); + + // if 0, execution bypasses the whole if block. + bool automatic_pruning = (gArgs.GetArg("-prune", 0) != 1); + obj.push_back(Pair("automatic_pruning", automatic_pruning)); + if (automatic_pruning) { + obj.push_back(Pair("prune_target_size", nPruneTarget)); + } + } const Consensus::Params& consensusParams = Params().GetConsensus(); CBlockIndex* tip = chainActive.Tip(); @@ -1185,19 +1214,13 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV); - BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT); + for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) { + BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos)); + } obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); - if (fPruneMode) - { - CBlockIndex *block = chainActive.Tip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) - block = block->pprev; - - obj.push_back(Pair("pruneheight", block->nHeight)); - } + obj.push_back(Pair("warnings", GetWarnings("statusbar"))); return obj; } @@ -1325,7 +1348,7 @@ UniValue mempoolInfoToJSON() ret.push_back(Pair("size", (int64_t) mempool.size())); ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); - size_t maxmempool = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; + size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; ret.push_back(Pair("maxmempool", (int64_t) maxmempool)); ret.push_back(Pair("mempoolminfee", ValueFromAmount(mempool.GetMinFee(maxmempool).GetFeePerK()))); @@ -1344,7 +1367,7 @@ UniValue getmempoolinfo(const JSONRPCRequest& request) " \"bytes\": xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted\n" " \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n" " \"maxmempool\": xxxxx, (numeric) Maximum memory usage for the mempool\n" - " \"mempoolminfee\": xxxxx (numeric) Minimum feerate (" + CURRENCY_UNIT + " per KB) for tx to be accepted\n" + " \"mempoolminfee\": xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted\n" "}\n" "\nExamples:\n" + HelpExampleCli("getmempoolinfo", "") @@ -1478,9 +1501,12 @@ UniValue getchaintxstats(const JSONRPCRequest& request) "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" + " \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n" + " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n" + " \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n" + " \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n" + " \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n" + " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n" "}\n" "\nExamples:\n" + HelpExampleCli("getchaintxstats", "") @@ -1490,11 +1516,7 @@ UniValue getchaintxstats(const JSONRPCRequest& request) 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(); + bool havehash = !request.params[1].isNull(); uint256 hash; if (havehash) { hash = uint256S(request.params[1].get_str()); @@ -1515,9 +1537,17 @@ UniValue getchaintxstats(const JSONRPCRequest& request) pindex = chainActive.Tip(); } } + + assert(pindex != nullptr); - if (blockcount < 1 || blockcount >= pindex->nHeight) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height"); + if (request.params[0].isNull()) { + blockcount = std::max(0, std::min(blockcount, pindex->nHeight - 1)); + } else { + blockcount = request.params[0].get_int(); + + if (blockcount < 0 || (blockcount > 0 && blockcount >= pindex->nHeight)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1"); + } } const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount); @@ -1527,41 +1557,68 @@ UniValue getchaintxstats(const JSONRPCRequest& request) 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)); + ret.push_back(Pair("window_block_count", blockcount)); + if (blockcount > 0) { + ret.push_back(Pair("window_tx_count", nTxDiff)); + ret.push_back(Pair("window_interval", nTimeDiff)); + if (nTimeDiff > 0) { + ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff)); + } + } return ret; } +UniValue savemempool(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 0) { + throw std::runtime_error( + "savemempool\n" + "\nDumps the mempool to disk.\n" + "\nExamples:\n" + + HelpExampleCli("savemempool", "") + + HelpExampleRpc("savemempool", "") + ); + } + + if (!DumpMempool()) { + throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk"); + } + + return NullUniValue; +} + 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","verbosity|verbose"} }, - { "blockchain", "getblockhash", &getblockhash, true, {"height"} }, - { "blockchain", "getblockheader", &getblockheader, true, {"blockhash","verbose"} }, - { "blockchain", "getchaintips", &getchaintips, true, {} }, - { "blockchain", "getdifficulty", &getdifficulty, true, {} }, - { "blockchain", "getmempoolancestors", &getmempoolancestors, true, {"txid","verbose"} }, - { "blockchain", "getmempooldescendants", &getmempooldescendants, true, {"txid","verbose"} }, - { "blockchain", "getmempoolentry", &getmempoolentry, true, {"txid"} }, - { "blockchain", "getmempoolinfo", &getmempoolinfo, true, {} }, - { "blockchain", "getrawmempool", &getrawmempool, true, {"verbose"} }, - { "blockchain", "gettxout", &gettxout, true, {"txid","n","include_mempool"} }, - { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, {} }, - { "blockchain", "pruneblockchain", &pruneblockchain, true, {"height"} }, - { "blockchain", "verifychain", &verifychain, true, {"checklevel","nblocks"} }, - - { "blockchain", "preciousblock", &preciousblock, true, {"blockhash"} }, +{ // category name actor (function) argNames + // --------------------- ------------------------ ----------------------- ---------- + { "blockchain", "getblockchaininfo", &getblockchaininfo, {} }, + { "blockchain", "getchaintxstats", &getchaintxstats, {"nblocks", "blockhash"} }, + { "blockchain", "getbestblockhash", &getbestblockhash, {} }, + { "blockchain", "getblockcount", &getblockcount, {} }, + { "blockchain", "getblock", &getblock, {"blockhash","verbosity|verbose"} }, + { "blockchain", "getblockhash", &getblockhash, {"height"} }, + { "blockchain", "getblockheader", &getblockheader, {"blockhash","verbose"} }, + { "blockchain", "getchaintips", &getchaintips, {} }, + { "blockchain", "getdifficulty", &getdifficulty, {} }, + { "blockchain", "getmempoolancestors", &getmempoolancestors, {"txid","verbose"} }, + { "blockchain", "getmempooldescendants", &getmempooldescendants, {"txid","verbose"} }, + { "blockchain", "getmempoolentry", &getmempoolentry, {"txid"} }, + { "blockchain", "getmempoolinfo", &getmempoolinfo, {} }, + { "blockchain", "getrawmempool", &getrawmempool, {"verbose"} }, + { "blockchain", "gettxout", &gettxout, {"txid","n","include_mempool"} }, + { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, {} }, + { "blockchain", "pruneblockchain", &pruneblockchain, {"height"} }, + { "blockchain", "savemempool", &savemempool, {} }, + { "blockchain", "verifychain", &verifychain, {"checklevel","nblocks"} }, + + { "blockchain", "preciousblock", &preciousblock, {"blockhash"} }, /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true, {"blockhash"} }, - { "hidden", "reconsiderblock", &reconsiderblock, true, {"blockhash"} }, - { "hidden", "waitfornewblock", &waitfornewblock, true, {"timeout"} }, - { "hidden", "waitforblock", &waitforblock, true, {"blockhash","timeout"} }, - { "hidden", "waitforblockheight", &waitforblockheight, true, {"height","timeout"} }, + { "hidden", "invalidateblock", &invalidateblock, {"blockhash"} }, + { "hidden", "reconsiderblock", &reconsiderblock, {"blockhash"} }, + { "hidden", "waitfornewblock", &waitfornewblock, {"timeout"} }, + { "hidden", "waitforblock", &waitforblock, {"blockhash","timeout"} }, + { "hidden", "waitforblockheight", &waitforblockheight, {"height","timeout"} }, }; void RegisterBlockchainRPCCommands(CRPCTable &t) |