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.cpp282
1 files changed, 158 insertions, 124 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index bd11d76866..050d9dd980 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -19,6 +19,8 @@
#include <hash.h>
#include <index/blockfilterindex.h>
#include <index/coinstatsindex.h>
+#include <net.h>
+#include <net_processing.h>
#include <node/blockstorage.h>
#include <logging/timer.h>
#include <node/coinstats.h>
@@ -30,6 +32,7 @@
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <rpc/server.h>
+#include <rpc/server_util.h>
#include <rpc/util.h>
#include <script/descriptor.h>
#include <streams.h>
@@ -39,7 +42,6 @@
#include <undo.h>
#include <util/strencodings.h>
#include <util/string.h>
-#include <util/system.h>
#include <util/translation.h>
#include <validation.h>
#include <validationinterface.h>
@@ -64,54 +66,6 @@ static Mutex cs_blockchange;
static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange);
-NodeContext& EnsureAnyNodeContext(const std::any& context)
-{
- auto node_context = util::AnyPtr<NodeContext>(context);
- if (!node_context) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Node context not found");
- }
- return *node_context;
-}
-
-CTxMemPool& EnsureMemPool(const NodeContext& node)
-{
- if (!node.mempool) {
- throw JSONRPCError(RPC_CLIENT_MEMPOOL_DISABLED, "Mempool disabled or instance not found");
- }
- return *node.mempool;
-}
-
-CTxMemPool& EnsureAnyMemPool(const std::any& context)
-{
- return EnsureMemPool(EnsureAnyNodeContext(context));
-}
-
-ChainstateManager& EnsureChainman(const NodeContext& node)
-{
- if (!node.chainman) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Node chainman not found");
- }
- return *node.chainman;
-}
-
-ChainstateManager& EnsureAnyChainman(const std::any& context)
-{
- return EnsureChainman(EnsureAnyNodeContext(context));
-}
-
-CBlockPolicyEstimator& EnsureFeeEstimator(const NodeContext& node)
-{
- if (!node.fee_estimator) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
- }
- return *node.fee_estimator;
-}
-
-CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context)
-{
- return EnsureFeeEstimator(EnsureAnyNodeContext(context));
-}
-
/* Calculate the difficulty for a given block index.
*/
double GetDifficulty(const CBlockIndex* blockindex)
@@ -464,23 +418,30 @@ static RPCHelpMan getdifficulty()
static std::vector<RPCResult> MempoolEntryDescription() { return {
RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},
RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."},
- RPCResult{RPCResult::Type::STR_AMOUNT, "fee", "transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)"},
- RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", "transaction fee with fee deltas used for mining priority (DEPRECATED)"},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true,
+ "transaction fee, denominated in " + CURRENCY_UNIT + " (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", /*optional=*/true,
+ "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT +
+ " (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"},
RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"},
RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"},
RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"},
- RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", "modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)"},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", /*optional=*/true,
+ "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " +
+ CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},
RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"},
- RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", "modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)"},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", /*optional=*/true,
+ "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " +
+ CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"},
RPCResult{RPCResult::Type::OBJ, "fees", "",
{
- RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
- RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT},
- RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT},
- RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
+ RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
}},
RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",
{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
@@ -494,26 +455,35 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool
{
AssertLockHeld(pool.cs);
- UniValue fees(UniValue::VOBJ);
- fees.pushKV("base", ValueFromAmount(e.GetFee()));
- fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee()));
- fees.pushKV("ancestor", ValueFromAmount(e.GetModFeesWithAncestors()));
- fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants()));
- info.pushKV("fees", fees);
-
info.pushKV("vsize", (int)e.GetTxSize());
info.pushKV("weight", (int)e.GetTxWeight());
- info.pushKV("fee", ValueFromAmount(e.GetFee()));
- info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
+ // TODO: top-level fee fields are deprecated. deprecated_fee_fields_enabled blocks should be removed in v24
+ const bool deprecated_fee_fields_enabled{IsDeprecatedRPCEnabled("fees")};
+ if (deprecated_fee_fields_enabled) {
+ info.pushKV("fee", ValueFromAmount(e.GetFee()));
+ info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
+ }
info.pushKV("time", count_seconds(e.GetTime()));
info.pushKV("height", (int)e.GetHeight());
info.pushKV("descendantcount", e.GetCountWithDescendants());
info.pushKV("descendantsize", e.GetSizeWithDescendants());
- info.pushKV("descendantfees", e.GetModFeesWithDescendants());
+ if (deprecated_fee_fields_enabled) {
+ info.pushKV("descendantfees", e.GetModFeesWithDescendants());
+ }
info.pushKV("ancestorcount", e.GetCountWithAncestors());
info.pushKV("ancestorsize", e.GetSizeWithAncestors());
- info.pushKV("ancestorfees", e.GetModFeesWithAncestors());
+ if (deprecated_fee_fields_enabled) {
+ info.pushKV("ancestorfees", e.GetModFeesWithAncestors());
+ }
info.pushKV("wtxid", pool.vTxHashes[e.vTxHashesIdx].first.ToString());
+
+ UniValue fees(UniValue::VOBJ);
+ fees.pushKV("base", ValueFromAmount(e.GetFee()));
+ fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee()));
+ fees.pushKV("ancestor", ValueFromAmount(e.GetModFeesWithAncestors()));
+ fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants()));
+ info.pushKV("fees", fees);
+
const CTransaction& tx = e.GetTx();
std::set<std::string> setDepends;
for (const CTxIn& txin : tx.vin)
@@ -805,6 +775,59 @@ static RPCHelpMan getmempoolentry()
};
}
+static RPCHelpMan getblockfrompeer()
+{
+ return RPCHelpMan{
+ "getblockfrompeer",
+ "\nAttempt to fetch block from a given peer.\n"
+ "\nWe must have the header for this block, e.g. using submitheader.\n"
+ "\nReturns {} if a block-request was successfully scheduled\n",
+ {
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
+ {"nodeid", RPCArg::Type::NUM, RPCArg::Optional::NO, "The node ID (see getpeerinfo for node IDs)"},
+ },
+ RPCResult{RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "warnings", /*optional=*/true, "any warnings"},
+ }},
+ RPCExamples{
+ HelpExampleCli("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0")
+ + HelpExampleRpc("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+{
+ const NodeContext& node = EnsureAnyNodeContext(request.context);
+ ChainstateManager& chainman = EnsureChainman(node);
+ PeerManager& peerman = EnsurePeerman(node);
+ CConnman& connman = EnsureConnman(node);
+
+ uint256 hash(ParseHashV(request.params[0], "hash"));
+
+ const NodeId nodeid = static_cast<NodeId>(request.params[1].get_int64());
+
+ // Check that the peer with nodeid exists
+ if (!connman.ForNode(nodeid, [](CNode* node) {return true;})) {
+ throw JSONRPCError(RPC_MISC_ERROR, strprintf("Peer nodeid %d does not exist", nodeid));
+ }
+
+ const CBlockIndex* const index = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(hash););
+
+ if (!index) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Block header missing");
+ }
+
+ UniValue result = UniValue::VOBJ;
+
+ if (index->nStatus & BLOCK_HAVE_DATA) {
+ result.pushKV("warnings", "Block already downloaded");
+ } else if (!peerman.FetchBlock(nodeid, hash, *index)) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Failed to fetch block from peer");
+ }
+ return result;
+},
+ };
+}
+
static RPCHelpMan getblockhash()
{
return RPCHelpMan{"getblockhash",
@@ -860,8 +883,8 @@ static RPCHelpMan getblockheader()
{RPCResult::Type::NUM, "difficulty", "The difficulty"},
{RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain"},
{RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
- {RPCResult::Type::STR_HEX, "previousblockhash", /* optional */ true, "The hash of the previous block (if available)"},
- {RPCResult::Type::STR_HEX, "nextblockhash", /* optional */ true, "The hash of the next block (if available)"},
+ {RPCResult::Type::STR_HEX, "previousblockhash", /*optional=*/true, "The hash of the previous block (if available)"},
+ {RPCResult::Type::STR_HEX, "nextblockhash", /*optional=*/true, "The hash of the next block (if available)"},
}},
RPCResult{"for verbose=false",
RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"},
@@ -970,8 +993,8 @@ static RPCHelpMan getblock()
{RPCResult::Type::NUM, "difficulty", "The difficulty"},
{RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the chain up to this block (in hex)"},
{RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
- {RPCResult::Type::STR_HEX, "previousblockhash", /* optional */ true, "The hash of the previous block (if available)"},
- {RPCResult::Type::STR_HEX, "nextblockhash", /* optional */ true, "The hash of the next block (if available)"},
+ {RPCResult::Type::STR_HEX, "previousblockhash", /*optional=*/true, "The hash of the previous block (if available)"},
+ {RPCResult::Type::STR_HEX, "nextblockhash", /*optional=*/true, "The hash of the next block (if available)"},
}},
RPCResult{"for verbosity = 2",
RPCResult::Type::OBJ, "", "",
@@ -1111,7 +1134,7 @@ CoinStatsHashType ParseHashType(const std::string& hash_type_input)
} else if (hash_type_input == "none") {
return CoinStatsHashType::NONE;
} else {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s is not a valid hash_type", hash_type_input));
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("'%s' is not a valid hash_type", hash_type_input));
}
}
@@ -1132,13 +1155,13 @@ static RPCHelpMan gettxoutsetinfo()
{RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at which these statistics are calculated"},
{RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
{RPCResult::Type::NUM, "bogosize", "Database-independent, meaningless metric indicating the UTXO set size"},
- {RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
- {RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
- {RPCResult::Type::NUM, "transactions", /* optional */ true, "The number of transactions with unspent outputs (not available when coinstatsindex is used)"},
- {RPCResult::Type::NUM, "disk_size", /* optional */ true, "The estimated size of the chainstate on disk (not available when coinstatsindex is used)"},
+ {RPCResult::Type::STR_HEX, "hash_serialized_2", /*optional=*/true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
+ {RPCResult::Type::STR_HEX, "muhash", /*optional=*/true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
+ {RPCResult::Type::NUM, "transactions", /*optional=*/true, "The number of transactions with unspent outputs (not available when coinstatsindex is used)"},
+ {RPCResult::Type::NUM, "disk_size", /*optional=*/true, "The estimated size of the chainstate on disk (not available when coinstatsindex is used)"},
{RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of coins in the UTXO set"},
- {RPCResult::Type::STR_AMOUNT, "total_unspendable_amount", /* optional */ true, "The total amount of coins permanently excluded from the UTXO set (only available if coinstatsindex is used)"},
- {RPCResult::Type::OBJ, "block_info", /* optional */ true, "Info on amounts in the block at this block height (only available if coinstatsindex is used)",
+ {RPCResult::Type::STR_AMOUNT, "total_unspendable_amount", /*optional=*/true, "The total amount of coins permanently excluded from the UTXO set (only available if coinstatsindex is used)"},
+ {RPCResult::Type::OBJ, "block_info", /*optional=*/true, "Info on amounts in the block at this block height (only available if coinstatsindex is used)",
{
{RPCResult::Type::STR_AMOUNT, "prevout_spent", "Total amount of all prevouts spent in this block"},
{RPCResult::Type::STR_AMOUNT, "coinbase", "Coinbase subsidy amount of this block"},
@@ -1276,7 +1299,7 @@ static RPCHelpMan gettxout()
{RPCResult::Type::STR, "asm", ""},
{RPCResult::Type::STR_HEX, "hex", ""},
{RPCResult::Type::STR, "type", "The type, eg pubkeyhash"},
- {RPCResult::Type::STR, "address", /* optional */ true, "The Bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
}},
{RPCResult::Type::BOOL, "coinbase", "Coinbase or not"},
}},
@@ -1364,7 +1387,7 @@ static RPCHelpMan verifychain()
CChainState& active_chainstate = chainman.ActiveChainstate();
return CVerifyDB().VerifyDB(
- active_chainstate, Params(), active_chainstate.CoinsTip(), check_level, check_depth);
+ active_chainstate, Params().GetConsensus(), active_chainstate.CoinsTip(), check_level, check_depth);
},
};
}
@@ -1452,32 +1475,32 @@ RPCHelpMan getblockchaininfo()
{RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"},
{RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"},
{RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"},
- {RPCResult::Type::NUM, "pruneheight", /* optional */ true, "lowest-height complete block stored (only present if pruning is enabled)"},
- {RPCResult::Type::BOOL, "automatic_pruning", /* optional */ true, "whether automatic pruning is enabled (only present if pruning is enabled)"},
- {RPCResult::Type::NUM, "prune_target_size", /* optional */ true, "the target size used by pruning (only present if automatic pruning is enabled)"},
+ {RPCResult::Type::NUM, "pruneheight", /*optional=*/true, "lowest-height complete block stored (only present if pruning is enabled)"},
+ {RPCResult::Type::BOOL, "automatic_pruning", /*optional=*/true, "whether automatic pruning is enabled (only present if pruning is enabled)"},
+ {RPCResult::Type::NUM, "prune_target_size", /*optional=*/true, "the target size used by pruning (only present if automatic pruning is enabled)"},
{RPCResult::Type::OBJ_DYN, "softforks", "status of softforks",
{
{RPCResult::Type::OBJ, "xxxx", "name of the softfork",
{
{RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""},
- {RPCResult::Type::OBJ, "bip9", /* optional */ true, "status of bip9 softforks (only for \"bip9\" type)",
+ {RPCResult::Type::OBJ, "bip9", /*optional=*/true, "status of bip9 softforks (only for \"bip9\" type)",
{
{RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""},
- {RPCResult::Type::NUM, "bit", /* optional */ true, "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"},
+ {RPCResult::Type::NUM, "bit", /*optional=*/true, "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"},
{RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"},
{RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"},
{RPCResult::Type::NUM, "since", "height of the first block to which the status applies"},
{RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"},
- {RPCResult::Type::OBJ, "statistics", /* optional */ true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)",
+ {RPCResult::Type::OBJ, "statistics", /*optional=*/true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)",
{
{RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"},
- {RPCResult::Type::NUM, "threshold", /* optional */ true, "the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"},
+ {RPCResult::Type::NUM, "threshold", /*optional=*/true, "the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"},
{RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"},
{RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"},
- {RPCResult::Type::BOOL, "possible", /* optional */ true, "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"},
+ {RPCResult::Type::BOOL, "possible", /*optional=*/true, "returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"},
}},
}},
- {RPCResult::Type::NUM, "height", /* optional */ true, "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"},
+ {RPCResult::Type::NUM, "height", /*optional=*/true, "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"},
{RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"},
}},
}},
@@ -1840,9 +1863,9 @@ static RPCHelpMan getchaintxstats()
{RPCResult::Type::STR_HEX, "window_final_block_hash", "The hash of the final block in the window"},
{RPCResult::Type::NUM, "window_final_block_height", "The height of the final block in the window."},
{RPCResult::Type::NUM, "window_block_count", "Size of the window in number of blocks"},
- {RPCResult::Type::NUM, "window_tx_count", /* optional */ true, "The number of transactions in the window. Only returned if \"window_block_count\" is > 0"},
- {RPCResult::Type::NUM, "window_interval", /* optional */ true, "The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0"},
- {RPCResult::Type::NUM, "txrate", /* optional */ true, "The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0"},
+ {RPCResult::Type::NUM, "window_tx_count", /*optional=*/true, "The number of transactions in the window. Only returned if \"window_block_count\" is > 0"},
+ {RPCResult::Type::NUM, "window_interval", /*optional=*/true, "The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0"},
+ {RPCResult::Type::NUM, "txrate", /*optional=*/true, "The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0"},
}},
RPCExamples{
HelpExampleCli("getchaintxstats", "")
@@ -1977,11 +2000,11 @@ static RPCHelpMan getblockstats()
RPCResult{
RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::NUM, "avgfee", /* optional */ true, "Average fee in the block"},
- {RPCResult::Type::NUM, "avgfeerate", /* optional */ true, "Average feerate (in satoshis per virtual byte)"},
- {RPCResult::Type::NUM, "avgtxsize", /* optional */ true, "Average transaction size"},
- {RPCResult::Type::STR_HEX, "blockhash", /* optional */ true, "The block hash (to check for potential reorgs)"},
- {RPCResult::Type::ARR_FIXED, "feerate_percentiles", /* optional */ true, "Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)",
+ {RPCResult::Type::NUM, "avgfee", /*optional=*/true, "Average fee in the block"},
+ {RPCResult::Type::NUM, "avgfeerate", /*optional=*/true, "Average feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "avgtxsize", /*optional=*/true, "Average transaction size"},
+ {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block hash (to check for potential reorgs)"},
+ {RPCResult::Type::ARR_FIXED, "feerate_percentiles", /*optional=*/true, "Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)",
{
{RPCResult::Type::NUM, "10th_percentile_feerate", "The 10th percentile feerate"},
{RPCResult::Type::NUM, "25th_percentile_feerate", "The 25th percentile feerate"},
@@ -1989,30 +2012,30 @@ static RPCHelpMan getblockstats()
{RPCResult::Type::NUM, "75th_percentile_feerate", "The 75th percentile feerate"},
{RPCResult::Type::NUM, "90th_percentile_feerate", "The 90th percentile feerate"},
}},
- {RPCResult::Type::NUM, "height", /* optional */ true, "The height of the block"},
- {RPCResult::Type::NUM, "ins", /* optional */ true, "The number of inputs (excluding coinbase)"},
- {RPCResult::Type::NUM, "maxfee", /* optional */ true, "Maximum fee in the block"},
- {RPCResult::Type::NUM, "maxfeerate", /* optional */ true, "Maximum feerate (in satoshis per virtual byte)"},
- {RPCResult::Type::NUM, "maxtxsize", /* optional */ true, "Maximum transaction size"},
- {RPCResult::Type::NUM, "medianfee", /* optional */ true, "Truncated median fee in the block"},
- {RPCResult::Type::NUM, "mediantime", /* optional */ true, "The block median time past"},
- {RPCResult::Type::NUM, "mediantxsize", /* optional */ true, "Truncated median transaction size"},
- {RPCResult::Type::NUM, "minfee", /* optional */ true, "Minimum fee in the block"},
- {RPCResult::Type::NUM, "minfeerate", /* optional */ true, "Minimum feerate (in satoshis per virtual byte)"},
- {RPCResult::Type::NUM, "mintxsize", /* optional */ true, "Minimum transaction size"},
- {RPCResult::Type::NUM, "outs", /* optional */ true, "The number of outputs"},
- {RPCResult::Type::NUM, "subsidy", /* optional */ true, "The block subsidy"},
- {RPCResult::Type::NUM, "swtotal_size", /* optional */ true, "Total size of all segwit transactions"},
- {RPCResult::Type::NUM, "swtotal_weight", /* optional */ true, "Total weight of all segwit transactions"},
- {RPCResult::Type::NUM, "swtxs", /* optional */ true, "The number of segwit transactions"},
- {RPCResult::Type::NUM, "time", /* optional */ true, "The block time"},
- {RPCResult::Type::NUM, "total_out", /* optional */ true, "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"},
- {RPCResult::Type::NUM, "total_size", /* optional */ true, "Total size of all non-coinbase transactions"},
- {RPCResult::Type::NUM, "total_weight", /* optional */ true, "Total weight of all non-coinbase transactions"},
- {RPCResult::Type::NUM, "totalfee", /* optional */ true, "The fee total"},
- {RPCResult::Type::NUM, "txs", /* optional */ true, "The number of transactions (including coinbase)"},
- {RPCResult::Type::NUM, "utxo_increase", /* optional */ true, "The increase/decrease in the number of unspent outputs"},
- {RPCResult::Type::NUM, "utxo_size_inc", /* optional */ true, "The increase/decrease in size for the utxo index (not discounting op_return and similar)"},
+ {RPCResult::Type::NUM, "height", /*optional=*/true, "The height of the block"},
+ {RPCResult::Type::NUM, "ins", /*optional=*/true, "The number of inputs (excluding coinbase)"},
+ {RPCResult::Type::NUM, "maxfee", /*optional=*/true, "Maximum fee in the block"},
+ {RPCResult::Type::NUM, "maxfeerate", /*optional=*/true, "Maximum feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "maxtxsize", /*optional=*/true, "Maximum transaction size"},
+ {RPCResult::Type::NUM, "medianfee", /*optional=*/true, "Truncated median fee in the block"},
+ {RPCResult::Type::NUM, "mediantime", /*optional=*/true, "The block median time past"},
+ {RPCResult::Type::NUM, "mediantxsize", /*optional=*/true, "Truncated median transaction size"},
+ {RPCResult::Type::NUM, "minfee", /*optional=*/true, "Minimum fee in the block"},
+ {RPCResult::Type::NUM, "minfeerate", /*optional=*/true, "Minimum feerate (in satoshis per virtual byte)"},
+ {RPCResult::Type::NUM, "mintxsize", /*optional=*/true, "Minimum transaction size"},
+ {RPCResult::Type::NUM, "outs", /*optional=*/true, "The number of outputs"},
+ {RPCResult::Type::NUM, "subsidy", /*optional=*/true, "The block subsidy"},
+ {RPCResult::Type::NUM, "swtotal_size", /*optional=*/true, "Total size of all segwit transactions"},
+ {RPCResult::Type::NUM, "swtotal_weight", /*optional=*/true, "Total weight of all segwit transactions"},
+ {RPCResult::Type::NUM, "swtxs", /*optional=*/true, "The number of segwit transactions"},
+ {RPCResult::Type::NUM, "time", /*optional=*/true, "The block time"},
+ {RPCResult::Type::NUM, "total_out", /*optional=*/true, "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"},
+ {RPCResult::Type::NUM, "total_size", /*optional=*/true, "Total size of all non-coinbase transactions"},
+ {RPCResult::Type::NUM, "total_weight", /*optional=*/true, "Total weight of all non-coinbase transactions"},
+ {RPCResult::Type::NUM, "totalfee", /*optional=*/true, "The fee total"},
+ {RPCResult::Type::NUM, "txs", /*optional=*/true, "The number of transactions (including coinbase)"},
+ {RPCResult::Type::NUM, "utxo_increase", /*optional=*/true, "The increase/decrease in the number of unspent outputs"},
+ {RPCResult::Type::NUM, "utxo_size_inc", /*optional=*/true, "The increase/decrease in size for the utxo index (not discounting op_return and similar)"},
}},
RPCExamples{
HelpExampleCli("getblockstats", R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") +
@@ -2190,7 +2213,7 @@ static RPCHelpMan getblockstats()
for (const std::string& stat : stats) {
const UniValue& value = ret_all[stat];
if (value.isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid selected statistic %s", stat));
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid selected statistic '%s'", stat));
}
ret.pushKV(stat, value);
}
@@ -2298,6 +2321,9 @@ public:
static RPCHelpMan scantxoutset()
{
+ // scriptPubKey corresponding to mainnet address 12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S
+ const std::string EXAMPLE_DESCRIPTOR_RAW = "raw(76a91411b366edfc0a8b66feebae5c2e25a7b6a5d1cf3188ac)#fm24fxxy";
+
return RPCHelpMan{"scantxoutset",
"\nScans the unspent transaction output set for entries that match certain output descriptors.\n"
"Examples of output descriptors are:\n"
@@ -2355,7 +2381,14 @@ static RPCHelpMan scantxoutset()
{RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT},
}},
},
- RPCExamples{""},
+ RPCExamples{
+ HelpExampleCli("scantxoutset", "start \'[\"" + EXAMPLE_DESCRIPTOR_RAW + "\"]\'") +
+ HelpExampleCli("scantxoutset", "status") +
+ HelpExampleCli("scantxoutset", "abort") +
+ HelpExampleRpc("scantxoutset", "\"start\", [\"" + EXAMPLE_DESCRIPTOR_RAW + "\"]") +
+ HelpExampleRpc("scantxoutset", "\"status\"") +
+ HelpExampleRpc("scantxoutset", "\"abort\"")
+ },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
@@ -2678,6 +2711,7 @@ static const CRPCCommand commands[] =
{ "blockchain", &getbestblockhash, },
{ "blockchain", &getblockcount, },
{ "blockchain", &getblock, },
+ { "blockchain", &getblockfrompeer, },
{ "blockchain", &getblockhash, },
{ "blockchain", &getblockheader, },
{ "blockchain", &getchaintips, },