aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/blockchain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc/blockchain.cpp')
-rw-r--r--src/rpc/blockchain.cpp465
1 files changed, 154 insertions, 311 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 56018caf24..9513c2b9ac 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -6,17 +6,15 @@
#include <rpc/blockchain.h>
#include <amount.h>
-#include <base58.h>
#include <blockfilter.h>
#include <chain.h>
#include <chainparams.h>
#include <coins.h>
+#include <node/coinstats.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <hash.h>
#include <index/blockfilterindex.h>
-#include <index/txindex.h>
-#include <key_io.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -44,9 +42,9 @@
#include <boost/thread/thread.hpp> // boost::thread::interrupt
+#include <condition_variable>
#include <memory>
#include <mutex>
-#include <condition_variable>
struct CUpdatedBlock
{
@@ -168,10 +166,9 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn
static UniValue getblockcount(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
RPCHelpMan{"getblockcount",
- "\nReturns the number of blocks in the longest blockchain.\n",
+ "\nReturns the height of the most-work fully-validated chain.\n"
+ "The genesis block has height 0.\n",
{},
RPCResult{
"n (numeric) The current block count\n"
@@ -180,7 +177,7 @@ static UniValue getblockcount(const JSONRPCRequest& request)
HelpExampleCli("getblockcount", "")
+ HelpExampleRpc("getblockcount", "")
},
- }.ToString());
+ }.Check(request);
LOCK(cs_main);
return ::ChainActive().Height();
@@ -188,10 +185,8 @@ static UniValue getblockcount(const JSONRPCRequest& request)
static UniValue getbestblockhash(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
RPCHelpMan{"getbestblockhash",
- "\nReturns the hash of the best (tip) block in the longest blockchain.\n",
+ "\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n",
{},
RPCResult{
"\"hex\" (string) the block hash, hex-encoded\n"
@@ -200,7 +195,7 @@ static UniValue getbestblockhash(const JSONRPCRequest& request)
HelpExampleCli("getbestblockhash", "")
+ HelpExampleRpc("getbestblockhash", "")
},
- }.ToString());
+ }.Check(request);
LOCK(cs_main);
return ::ChainActive().Tip()->GetBlockHash().GetHex();
@@ -218,8 +213,6 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex)
static UniValue waitfornewblock(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() > 1)
- throw std::runtime_error(
RPCHelpMan{"waitfornewblock",
"\nWaits for a specific new block and returns useful info about it.\n"
"\nReturns the current block on timeout or exit.\n",
@@ -236,7 +229,7 @@ static UniValue waitfornewblock(const JSONRPCRequest& request)
HelpExampleCli("waitfornewblock", "1000")
+ HelpExampleRpc("waitfornewblock", "1000")
},
- }.ToString());
+ }.Check(request);
int timeout = 0;
if (!request.params[0].isNull())
timeout = request.params[0].get_int();
@@ -259,8 +252,6 @@ static UniValue waitfornewblock(const JSONRPCRequest& request)
static UniValue waitforblock(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- throw std::runtime_error(
RPCHelpMan{"waitforblock",
"\nWaits for a specific new block and returns useful info about it.\n"
"\nReturns the current block on timeout or exit.\n",
@@ -278,7 +269,7 @@ static UniValue waitforblock(const JSONRPCRequest& request)
HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
+ HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
},
- }.ToString());
+ }.Check(request);
int timeout = 0;
uint256 hash(ParseHashV(request.params[0], "blockhash"));
@@ -304,8 +295,6 @@ static UniValue waitforblock(const JSONRPCRequest& request)
static UniValue waitforblockheight(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- throw std::runtime_error(
RPCHelpMan{"waitforblockheight",
"\nWaits for (at least) block height and returns the height and hash\n"
"of the current tip.\n"
@@ -324,7 +313,7 @@ static UniValue waitforblockheight(const JSONRPCRequest& request)
HelpExampleCli("waitforblockheight", "\"100\", 1000")
+ HelpExampleRpc("waitforblockheight", "\"100\", 1000")
},
- }.ToString());
+ }.Check(request);
int timeout = 0;
int height = request.params[0].get_int();
@@ -349,8 +338,6 @@ static UniValue waitforblockheight(const JSONRPCRequest& request)
static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() > 0) {
- throw std::runtime_error(
RPCHelpMan{"syncwithvalidationinterfacequeue",
"\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n",
{},
@@ -359,16 +346,14 @@ static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
HelpExampleCli("syncwithvalidationinterfacequeue","")
+ HelpExampleRpc("syncwithvalidationinterfacequeue","")
},
- }.ToString());
- }
+ }.Check(request);
+
SyncWithValidationInterfaceQueue();
return NullUniValue;
}
static UniValue getdifficulty(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
RPCHelpMan{"getdifficulty",
"\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
{},
@@ -379,7 +364,7 @@ static UniValue getdifficulty(const JSONRPCRequest& request)
HelpExampleCli("getdifficulty", "")
+ HelpExampleRpc("getdifficulty", "")
},
- }.ToString());
+ }.Check(request);
LOCK(cs_main);
return GetDifficulty(::ChainActive().Tip());
@@ -390,6 +375,7 @@ static std::string EntryDescriptionString()
return " \"vsize\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n"
" \"size\" : n, (numeric) (DEPRECATED) same as vsize. Only returned if bitcoind is started with -deprecatedrpc=size\n"
" size will be completely removed in v0.20.\n"
+ " \"weight\" : n, (numeric) transaction weight as defined in BIP 141.\n"
" \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n"
" \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority (DEPRECATED)\n"
" \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
@@ -429,6 +415,7 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool
info.pushKV("vsize", (int)e.GetTxSize());
if (IsDeprecatedRPCEnabled("size")) info.pushKV("size", (int)e.GetTxSize());
+ info.pushKV("weight", (int)e.GetTxWeight());
info.pushKV("fee", ValueFromAmount(e.GetFee()));
info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
info.pushKV("time", e.GetTime());
@@ -506,8 +493,6 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose)
static UniValue getrawmempool(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() > 1)
- throw std::runtime_error(
RPCHelpMan{"getrawmempool",
"\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",
@@ -530,7 +515,7 @@ static UniValue getrawmempool(const JSONRPCRequest& request)
HelpExampleCli("getrawmempool", "true")
+ HelpExampleRpc("getrawmempool", "true")
},
- }.ToString());
+ }.Check(request);
bool fVerbose = false;
if (!request.params[0].isNull())
@@ -541,8 +526,6 @@ static UniValue getrawmempool(const JSONRPCRequest& request)
static UniValue getmempoolancestors(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
- throw std::runtime_error(
RPCHelpMan{"getmempoolancestors",
"\nIf txid is in the mempool, returns all in-mempool ancestors.\n",
{
@@ -568,8 +551,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
HelpExampleCli("getmempoolancestors", "\"mytxid\"")
+ HelpExampleRpc("getmempoolancestors", "\"mytxid\"")
},
- }.ToString());
- }
+ }.Check(request);
bool fVerbose = false;
if (!request.params[1].isNull())
@@ -611,8 +593,6 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
static UniValue getmempooldescendants(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
- throw std::runtime_error(
RPCHelpMan{"getmempooldescendants",
"\nIf txid is in the mempool, returns all in-mempool descendants.\n",
{
@@ -638,8 +618,7 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
HelpExampleCli("getmempooldescendants", "\"mytxid\"")
+ HelpExampleRpc("getmempooldescendants", "\"mytxid\"")
},
- }.ToString());
- }
+ }.Check(request);
bool fVerbose = false;
if (!request.params[1].isNull())
@@ -681,8 +660,6 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
static UniValue getmempoolentry(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1) {
- throw std::runtime_error(
RPCHelpMan{"getmempoolentry",
"\nReturns mempool data for given transaction\n",
{
@@ -697,8 +674,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request)
HelpExampleCli("getmempoolentry", "\"mytxid\"")
+ HelpExampleRpc("getmempoolentry", "\"mytxid\"")
},
- }.ToString());
- }
+ }.Check(request);
uint256 hash = ParseHashV(request.params[0], "parameter 1");
@@ -717,8 +693,6 @@ static UniValue getmempoolentry(const JSONRPCRequest& request)
static UniValue getblockhash(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
RPCHelpMan{"getblockhash",
"\nReturns hash of block in best-block-chain at height provided.\n",
{
@@ -731,7 +705,7 @@ static UniValue getblockhash(const JSONRPCRequest& request)
HelpExampleCli("getblockhash", "1000")
+ HelpExampleRpc("getblockhash", "1000")
},
- }.ToString());
+ }.Check(request);
LOCK(cs_main);
@@ -745,8 +719,6 @@ static UniValue getblockhash(const JSONRPCRequest& request)
static UniValue getblockheader(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- throw std::runtime_error(
RPCHelpMan{"getblockheader",
"\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",
@@ -782,7 +754,7 @@ static UniValue getblockheader(const JSONRPCRequest& request)
HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
},
- }.ToString());
+ }.Check(request);
uint256 hash(ParseHashV(request.params[0], "hash"));
@@ -848,7 +820,7 @@ static CBlockUndo GetUndoChecked(const CBlockIndex* pblockindex)
static UniValue getblock(const JSONRPCRequest& request)
{
- const RPCHelpMan help{"getblock",
+ RPCHelpMan{"getblock",
"\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",
@@ -900,11 +872,7 @@ static UniValue getblock(const JSONRPCRequest& request)
HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
},
- };
-
- if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
- throw std::runtime_error(help.ToString());
- }
+ }.Check(request);
uint256 hash(ParseHashV(request.params[0], "blockhash"));
@@ -942,81 +910,8 @@ static UniValue getblock(const JSONRPCRequest& request)
return blockToJSON(block, tip, pblockindex, verbosity >= 2);
}
-struct CCoinsStats
-{
- int nHeight;
- uint256 hashBlock;
- uint64_t nTransactions;
- uint64_t nTransactionOutputs;
- uint64_t nBogoSize;
- uint256 hashSerialized;
- uint64_t nDiskSize;
- CAmount nTotalAmount;
-
- CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nBogoSize(0), nDiskSize(0), nTotalAmount(0) {}
-};
-
-static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
-{
- assert(!outputs.empty());
- ss << hash;
- ss << VARINT(outputs.begin()->second.nHeight * 2 + outputs.begin()->second.fCoinBase ? 1u : 0u);
- stats.nTransactions++;
- for (const auto& output : outputs) {
- ss << VARINT(output.first + 1);
- ss << output.second.out.scriptPubKey;
- ss << VARINT(output.second.out.nValue, VarIntMode::NONNEGATIVE_SIGNED);
- stats.nTransactionOutputs++;
- stats.nTotalAmount += output.second.out.nValue;
- stats.nBogoSize += 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ +
- 2 /* scriptPubKey len */ + output.second.out.scriptPubKey.size() /* scriptPubKey */;
- }
- ss << VARINT(0u);
-}
-
-//! Calculate statistics about the unspent transaction output set
-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();
- {
- LOCK(cs_main);
- stats.nHeight = LookupBlockIndex(stats.hashBlock)->nHeight;
- }
- ss << stats.hashBlock;
- uint256 prevkey;
- std::map<uint32_t, Coin> outputs;
- while (pcursor->Valid()) {
- boost::this_thread::interruption_point();
- COutPoint key;
- Coin coin;
- if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
- if (!outputs.empty() && key.hash != prevkey) {
- ApplyStats(stats, ss, prevkey, outputs);
- outputs.clear();
- }
- prevkey = key.hash;
- outputs[key.n] = std::move(coin);
- } else {
- return error("%s: unable to read value", __func__);
- }
- pcursor->Next();
- }
- if (!outputs.empty()) {
- ApplyStats(stats, ss, prevkey, outputs);
- }
- stats.hashSerialized = ss.GetHash();
- stats.nDiskSize = view->EstimateSize();
- return true;
-}
-
static UniValue pruneblockchain(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
RPCHelpMan{"pruneblockchain", "",
{
{"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or a unix timestamp\n"
@@ -1029,7 +924,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
HelpExampleCli("pruneblockchain", "1000")
+ HelpExampleRpc("pruneblockchain", "1000")
},
- }.ToString());
+ }.Check(request);
if (!fPruneMode)
throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode.");
@@ -1063,13 +958,16 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
}
PruneBlockFilesManual(height);
- return uint64_t(height);
+ const CBlockIndex* block = ::ChainActive().Tip();
+ assert(block);
+ while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
+ block = block->pprev;
+ }
+ return uint64_t(block->nHeight);
}
static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
RPCHelpMan{"gettxoutsetinfo",
"\nReturns statistics about the unspent transaction output set.\n"
"Note this call may take some time.\n",
@@ -1090,13 +988,15 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
HelpExampleCli("gettxoutsetinfo", "")
+ HelpExampleRpc("gettxoutsetinfo", "")
},
- }.ToString());
+ }.Check(request);
UniValue ret(UniValue::VOBJ);
CCoinsStats stats;
- FlushStateToDisk();
- if (GetUTXOStats(pcoinsdbview.get(), stats)) {
+ ::ChainstateActive().ForceFlushStateToDisk();
+
+ CCoinsView* coins_view = WITH_LOCK(cs_main, return &ChainstateActive().CoinsDB());
+ if (GetUTXOStats(coins_view, stats)) {
ret.pushKV("height", (int64_t)stats.nHeight);
ret.pushKV("bestblock", stats.hashBlock.GetHex());
ret.pushKV("transactions", (int64_t)stats.nTransactions);
@@ -1113,8 +1013,6 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
UniValue gettxout(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
- throw std::runtime_error(
RPCHelpMan{"gettxout",
"\nReturns details about an unspent transaction output.\n",
{
@@ -1148,7 +1046,7 @@ UniValue gettxout(const JSONRPCRequest& request)
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("gettxout", "\"txid\", 1")
},
- }.ToString());
+ }.Check(request);
LOCK(cs_main);
@@ -1162,19 +1060,21 @@ UniValue gettxout(const JSONRPCRequest& request)
fMempool = request.params[2].get_bool();
Coin coin;
+ CCoinsViewCache* coins_view = &::ChainstateActive().CoinsTip();
+
if (fMempool) {
LOCK(mempool.cs);
- CCoinsViewMemPool view(pcoinsTip.get(), mempool);
+ CCoinsViewMemPool view(coins_view, mempool);
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
return NullUniValue;
}
} else {
- if (!pcoinsTip->GetCoin(out, coin)) {
+ if (!coins_view->GetCoin(out, coin)) {
return NullUniValue;
}
}
- const CBlockIndex* pindex = LookupBlockIndex(pcoinsTip->GetBestBlock());
+ const CBlockIndex* pindex = LookupBlockIndex(coins_view->GetBestBlock());
ret.pushKV("bestblock", pindex->GetBlockHash().GetHex());
if (coin.nHeight == MEMPOOL_HEIGHT) {
ret.pushKV("confirmations", 0);
@@ -1194,8 +1094,6 @@ static UniValue verifychain(const JSONRPCRequest& request)
{
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(
RPCHelpMan{"verifychain",
"\nVerifies blockchain database.\n",
{
@@ -1209,7 +1107,7 @@ static UniValue verifychain(const JSONRPCRequest& request)
HelpExampleCli("verifychain", "")
+ HelpExampleRpc("verifychain", "")
},
- }.ToString());
+ }.Check(request);
LOCK(cs_main);
@@ -1218,57 +1116,53 @@ static UniValue verifychain(const JSONRPCRequest& request)
if (!request.params[1].isNull())
nCheckDepth = request.params[1].get_int();
- return CVerifyDB().VerifyDB(Params(), pcoinsTip.get(), nCheckLevel, nCheckDepth);
+ return CVerifyDB().VerifyDB(
+ Params(), &::ChainstateActive().CoinsTip(), nCheckLevel, nCheckDepth);
}
-/** Implementation of IsSuperMajority with better feedback */
-static UniValue SoftForkMajorityDesc(int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
+static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int height) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- UniValue rv(UniValue::VOBJ);
- bool activated = false;
- switch(version)
- {
- case 2:
- activated = pindex->nHeight >= consensusParams.BIP34Height;
- break;
- case 3:
- activated = pindex->nHeight >= consensusParams.BIP66Height;
- break;
- case 4:
- activated = pindex->nHeight >= consensusParams.BIP65Height;
- break;
- }
- rv.pushKV("status", activated);
- return rv;
-}
+ // For buried deployments.
+ // A buried deployment is one where the height of the activation has been hardcoded into
+ // the client implementation long after the consensus change has activated. See BIP 90.
+ // Buried deployments with activation height value of
+ // std::numeric_limits<int>::max() are disabled and thus hidden.
+ if (height == std::numeric_limits<int>::max()) return;
-static UniValue SoftForkDesc(const std::string &name, int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
-{
UniValue rv(UniValue::VOBJ);
- rv.pushKV("id", name);
- rv.pushKV("version", version);
- rv.pushKV("reject", SoftForkMajorityDesc(version, pindex, consensusParams));
- return rv;
+ rv.pushKV("type", "buried");
+ // getblockchaininfo reports the softfork as active from when the chain height is
+ // one below the activation height
+ rv.pushKV("active", ::ChainActive().Tip()->nHeight + 1 >= height);
+ rv.pushKV("height", height);
+ softforks.pushKV(name, rv);
}
-static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
+static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
- UniValue rv(UniValue::VOBJ);
+ // For BIP9 deployments.
+ // Deployments (e.g. testdummy) with timeout value before Jan 1, 2009 are hidden.
+ // A timeout value of 0 guarantees a softfork will never be activated.
+ // This is used when merging logic to implement a proposed softfork without a specified deployment schedule.
+ if (consensusParams.vDeployments[id].nTimeout <= 1230768000) return;
+
+ UniValue bip9(UniValue::VOBJ);
const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
switch (thresholdState) {
- case ThresholdState::DEFINED: rv.pushKV("status", "defined"); break;
- case ThresholdState::STARTED: rv.pushKV("status", "started"); break;
- case ThresholdState::LOCKED_IN: rv.pushKV("status", "locked_in"); break;
- case ThresholdState::ACTIVE: rv.pushKV("status", "active"); break;
- case ThresholdState::FAILED: rv.pushKV("status", "failed"); break;
+ case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
+ case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
+ case ThresholdState::LOCKED_IN: bip9.pushKV("status", "locked_in"); break;
+ case ThresholdState::ACTIVE: bip9.pushKV("status", "active"); break;
+ case ThresholdState::FAILED: bip9.pushKV("status", "failed"); break;
}
if (ThresholdState::STARTED == thresholdState)
{
- rv.pushKV("bit", consensusParams.vDeployments[id].bit);
+ bip9.pushKV("bit", consensusParams.vDeployments[id].bit);
}
- rv.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
- rv.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
- rv.pushKV("since", VersionBitsTipStateSinceHeight(consensusParams, id));
+ bip9.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
+ bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
+ int64_t since_height = VersionBitsTipStateSinceHeight(consensusParams, id);
+ bip9.pushKV("since", since_height);
if (ThresholdState::STARTED == thresholdState)
{
UniValue statsUV(UniValue::VOBJ);
@@ -1278,31 +1172,29 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse
statsUV.pushKV("elapsed", statsStruct.elapsed);
statsUV.pushKV("count", statsStruct.count);
statsUV.pushKV("possible", statsStruct.possible);
- rv.pushKV("statistics", statsUV);
+ bip9.pushKV("statistics", statsUV);
}
- return rv;
-}
-static 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.pushKV(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id));
+ UniValue rv(UniValue::VOBJ);
+ rv.pushKV("type", "bip9");
+ rv.pushKV("bip9", bip9);
+ if (ThresholdState::ACTIVE == thresholdState) {
+ rv.pushKV("height", since_height);
+ }
+ rv.pushKV("active", ThresholdState::ACTIVE == thresholdState);
+
+ softforks.pushKV(name, rv);
}
UniValue getblockchaininfo(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
RPCHelpMan{"getblockchaininfo",
"Returns an object containing various state info regarding blockchain processing.\n",
{},
RPCResult{
"{\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"
+ " \"blocks\": xxxxxx, (numeric) the height of the most-work fully-validated chain. The genesis block has height 0\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"
@@ -1315,29 +1207,25 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
" \"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"
- " },\n"
- " }, ...\n"
- " ],\n"
- " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
+ " \"softforks\": { (object) status of softforks\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"
+ " \"type\": \"xxxx\", (string) one of \"buried\", \"bip9\"\n"
+ " \"bip9\": { (object) status of bip9 softforks (only for \"bip9\" type)\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\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"
+ " \"height\": \"xxxxxx\", (numeric) height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)\n"
+ " \"active\": xx, (boolean) true if the rules are enforced for the mempool and the next block\n"
" }\n"
" }\n"
" \"warnings\" : \"...\", (string) any network and blockchain warnings.\n"
@@ -1347,7 +1235,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
HelpExampleCli("getblockchaininfo", "")
+ HelpExampleRpc("getblockchaininfo", "")
},
- }.ToString());
+ }.Check(request);
LOCK(cs_main);
@@ -1360,7 +1248,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
obj.pushKV("difficulty", (double)GetDifficulty(tip));
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
- obj.pushKV("initialblockdownload", IsInitialBlockDownload());
+ obj.pushKV("initialblockdownload", ::ChainstateActive().IsInitialBlockDownload());
obj.pushKV("chainwork", tip->nChainWork.GetHex());
obj.pushKV("size_on_disk", CalculateCurrentUsage());
obj.pushKV("pruned", fPruneMode);
@@ -1382,16 +1270,14 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
}
const Consensus::Params& consensusParams = Params().GetConsensus();
- UniValue softforks(UniValue::VARR);
- UniValue bip9_softforks(UniValue::VOBJ);
- softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
- softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
- softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
- for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) {
- BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos));
- }
+ UniValue softforks(UniValue::VOBJ);
+ BuriedForkDescPushBack(softforks, "bip34", consensusParams.BIP34Height);
+ BuriedForkDescPushBack(softforks, "bip66", consensusParams.BIP66Height);
+ BuriedForkDescPushBack(softforks, "bip65", consensusParams.BIP65Height);
+ BuriedForkDescPushBack(softforks, "csv", consensusParams.CSVHeight);
+ BuriedForkDescPushBack(softforks, "segwit", consensusParams.SegwitHeight);
+ BIP9SoftForkDescPushBack(softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
obj.pushKV("softforks", softforks);
- obj.pushKV("bip9_softforks", bip9_softforks);
obj.pushKV("warnings", GetWarnings("statusbar"));
return obj;
@@ -1414,8 +1300,6 @@ struct CompareBlocksByHeight
static UniValue getchaintips(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
RPCHelpMan{"getchaintips",
"Return information about all known tips in the block tree,"
" including the main chain as well as orphaned branches.\n",
@@ -1446,14 +1330,14 @@ static UniValue getchaintips(const JSONRPCRequest& request)
HelpExampleCli("getchaintips", "")
+ HelpExampleRpc("getchaintips", "")
},
- }.ToString());
+ }.Check(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.
* Algorithm:
- * - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
+ * - Make one pass through g_blockman.m_block_index, 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.
* - add ::ChainActive().Tip()
*/
@@ -1461,7 +1345,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
std::set<const CBlockIndex*> setOrphans;
std::set<const CBlockIndex*> setPrevs;
- for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
+ for (const std::pair<const uint256, CBlockIndex*>& item : ::BlockIndex())
{
if (!::ChainActive().Contains(item.second)) {
setOrphans.insert(item.second);
@@ -1537,8 +1421,6 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool)
static UniValue getmempoolinfo(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0)
- throw std::runtime_error(
RPCHelpMan{"getmempoolinfo",
"\nReturns details on the active state of the TX memory pool.\n",
{},
@@ -1557,15 +1439,13 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request)
HelpExampleCli("getmempoolinfo", "")
+ HelpExampleRpc("getmempoolinfo", "")
},
- }.ToString());
+ }.Check(request);
return MempoolInfoToJSON(::mempool);
}
static UniValue preciousblock(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
RPCHelpMan{"preciousblock",
"\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"
@@ -1578,7 +1458,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
HelpExampleCli("preciousblock", "\"blockhash\"")
+ HelpExampleRpc("preciousblock", "\"blockhash\"")
},
- }.ToString());
+ }.Check(request);
uint256 hash(ParseHashV(request.params[0], "blockhash"));
CBlockIndex* pblockindex;
@@ -1603,8 +1483,6 @@ static UniValue preciousblock(const JSONRPCRequest& request)
static UniValue invalidateblock(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
RPCHelpMan{"invalidateblock",
"\nPermanently marks a block as invalid, as if it violated a consensus rule.\n",
{
@@ -1615,7 +1493,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
HelpExampleCli("invalidateblock", "\"blockhash\"")
+ HelpExampleRpc("invalidateblock", "\"blockhash\"")
},
- }.ToString());
+ }.Check(request);
uint256 hash(ParseHashV(request.params[0], "blockhash"));
CValidationState state;
@@ -1643,8 +1521,6 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
static UniValue reconsiderblock(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
RPCHelpMan{"reconsiderblock",
"\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n"
"This can be used to undo the effects of invalidateblock.\n",
@@ -1656,7 +1532,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
HelpExampleCli("reconsiderblock", "\"blockhash\"")
+ HelpExampleRpc("reconsiderblock", "\"blockhash\"")
},
- }.ToString());
+ }.Check(request);
uint256 hash(ParseHashV(request.params[0], "blockhash"));
@@ -1682,8 +1558,6 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
static UniValue getchaintxstats(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() > 2)
- throw std::runtime_error(
RPCHelpMan{"getchaintxstats",
"\nCompute statistics about the total number and rate of transactions in the chain.\n",
{
@@ -1695,6 +1569,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
" \"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_final_block_hash\": \"...\", (string) The hash of the final block in the window.\n"
+ " \"window_final_block_height\": xxxxx, (numeric) The height of the final block in the window.\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"
@@ -1705,7 +1580,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
HelpExampleCli("getchaintxstats", "")
+ HelpExampleRpc("getchaintxstats", "2016")
},
- }.ToString());
+ }.Check(request);
const CBlockIndex* pindex;
int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
@@ -1745,6 +1620,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
ret.pushKV("time", (int64_t)pindex->nTime);
ret.pushKV("txcount", (int64_t)pindex->nChainTx);
ret.pushKV("window_final_block_hash", pindex->GetBlockHash().GetHex());
+ ret.pushKV("window_final_block_height", pindex->nHeight);
ret.pushKV("window_block_count", blockcount);
if (blockcount > 0) {
ret.pushKV("window_tx_count", nTxDiff);
@@ -1815,7 +1691,7 @@ static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t)
static UniValue getblockstats(const JSONRPCRequest& request)
{
- const RPCHelpMan help{"getblockstats",
+ RPCHelpMan{"getblockstats",
"\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
"It won't work for some heights with pruning.\n",
{
@@ -1870,10 +1746,7 @@ static UniValue getblockstats(const JSONRPCRequest& request)
HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
+ HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
},
- };
- if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
- throw std::runtime_error(help.ToString());
- }
+ }.Check(request);
LOCK(cs_main);
@@ -2074,8 +1947,6 @@ static UniValue getblockstats(const JSONRPCRequest& request)
static UniValue savemempool(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 0) {
- throw std::runtime_error(
RPCHelpMan{"savemempool",
"\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n",
{},
@@ -2084,8 +1955,7 @@ static UniValue savemempool(const JSONRPCRequest& request)
HelpExampleCli("savemempool", "")
+ HelpExampleRpc("savemempool", "")
},
- }.ToString());
- }
+ }.Check(request);
if (!::mempool.IsLoaded()) {
throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
@@ -2160,8 +2030,6 @@ public:
UniValue scantxoutset(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
- throw std::runtime_error(
RPCHelpMan{"scantxoutset",
"\nEXPERIMENTAL warning: this call may be removed or changed in future releases.\n"
"\nScans the unspent transaction output set for entries that match certain output descriptors.\n"
@@ -2196,22 +2064,25 @@ UniValue scantxoutset(const JSONRPCRequest& request)
},
RPCResult{
"{\n"
+ " \"success\": true|false, (boolean) Whether the scan was completed\n"
+ " \"txouts\": n, (numeric) The number of unspent transaction outputs scanned\n"
+ " \"height\": n, (numeric) The current block height (index)\n"
+ " \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n"
" \"unspents\": [\n"
- " {\n"
- " \"txid\" : \"transactionid\", (string) The transaction id\n"
- " \"vout\": n, (numeric) the vout value\n"
- " \"scriptPubKey\" : \"script\", (string) the script key\n"
- " \"desc\" : \"descriptor\", (string) A specialized descriptor for the matched scriptPubKey\n"
- " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " of the unspent output\n"
- " \"height\" : n, (numeric) Height of the unspent transaction output\n"
+ " {\n"
+ " \"txid\": \"hash\", (string) The transaction id\n"
+ " \"vout\": n, (numeric) The vout value\n"
+ " \"scriptPubKey\": \"script\", (string) The script key\n"
+ " \"desc\": \"descriptor\", (string) A specialized descriptor for the matched scriptPubKey\n"
+ " \"amount\": x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " of the unspent output\n"
+ " \"height\": n, (numeric) Height of the unspent transaction output\n"
" }\n"
- " ,...], \n"
- " \"total_amount\" : x.xxx, (numeric) The total amount of all found unspent outputs in " + CURRENCY_UNIT + "\n"
+ " ,...],\n"
+ " \"total_amount\": x.xxx, (numeric) The total amount of all found unspent outputs in " + CURRENCY_UNIT + "\n"
"]\n"
},
RPCExamples{""},
- }.ToString()
- );
+ }.Check(request);
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
@@ -2244,41 +2115,12 @@ UniValue scantxoutset(const JSONRPCRequest& request)
// loop through the scan objects
for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
- std::string desc_str;
- std::pair<int64_t, int64_t> range = {0, 1000};
- if (scanobject.isStr()) {
- desc_str = scanobject.get_str();
- } else if (scanobject.isObject()) {
- UniValue desc_uni = find_value(scanobject, "desc");
- if (desc_uni.isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor needs to be provided in scan object");
- desc_str = desc_uni.get_str();
- UniValue range_uni = find_value(scanobject, "range");
- if (!range_uni.isNull()) {
- range = ParseDescriptorRange(range_uni);
- }
- } else {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan object needs to be either a string or an object");
- }
-
FlatSigningProvider provider;
- auto desc = Parse(desc_str, provider);
- if (!desc) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor '%s'", desc_str));
- }
- if (!desc->IsRange()) {
- range.first = 0;
- range.second = 0;
- }
- for (int i = range.first; i <= range.second; ++i) {
- std::vector<CScript> scripts;
- if (!desc->Expand(i, provider, scripts, provider)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys: '%s'", desc_str));
- }
- for (const auto& script : scripts) {
- std::string inferred = InferDescriptor(script, provider)->ToString();
- needles.emplace(script);
- descriptors.emplace(std::move(script), std::move(inferred));
- }
+ auto scripts = EvalDescriptorStringOrObject(scanobject, provider);
+ for (const auto& script : scripts) {
+ std::string inferred = InferDescriptor(script, provider)->ToString();
+ needles.emplace(script);
+ descriptors.emplace(std::move(script), std::move(inferred));
}
}
@@ -2290,15 +2132,20 @@ UniValue scantxoutset(const JSONRPCRequest& request)
g_scan_progress = 0;
int64_t count = 0;
std::unique_ptr<CCoinsViewCursor> pcursor;
+ CBlockIndex* tip;
{
LOCK(cs_main);
- FlushStateToDisk();
- pcursor = std::unique_ptr<CCoinsViewCursor>(pcoinsdbview->Cursor());
+ ::ChainstateActive().ForceFlushStateToDisk();
+ pcursor = std::unique_ptr<CCoinsViewCursor>(::ChainstateActive().CoinsDB().Cursor());
assert(pcursor);
+ tip = ::ChainActive().Tip();
+ assert(tip);
}
bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins);
result.pushKV("success", res);
- result.pushKV("searched_items", count);
+ result.pushKV("txouts", count);
+ result.pushKV("height", tip->nHeight);
+ result.pushKV("bestblock", tip->GetBlockHash().GetHex());
for (const auto& it : coins) {
const COutPoint& outpoint = it.first;
@@ -2327,8 +2174,6 @@ UniValue scantxoutset(const JSONRPCRequest& request)
static UniValue getblockfilter(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
- throw std::runtime_error(
RPCHelpMan{"getblockfilter",
"\nRetrieve a BIP 157 content filter for a particular block.\n",
{
@@ -2344,9 +2189,7 @@ static UniValue getblockfilter(const JSONRPCRequest& request)
RPCExamples{
HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"")
}
- }.ToString()
- );
- }
+ }.Check(request);
uint256 block_hash = ParseHashV(request.params[0], "blockhash");
std::string filtertype_name = "basic";