10#include <blockfilter.h>
12#include <chainparams.h>
75#include <versionbits.h>
111 const std::function<
void()>& interruption_point = {})
120 const fs::path& path,
121 const fs::path& temppath,
122 const std::function<
void()>& interruption_point = {});
129 const fs::path& path,
130 const fs::path& tmppath,
137 int nShift = (blockindex.
nBits >> 24) & 0xff;
139 (double)0x0000ffff / (
double)(blockindex.
nBits & 0x00ffffff);
158 if (next && next->
pprev == &blockindex) {
162 return &blockindex == &tip ? 1 : -1;
171 const int height{param.
getInt<
int>()};
175 const int current_tip{active_chain.
Height()};
176 if (height > current_tip) {
180 return active_chain[height];
202 result.
pushKV(
"confirmations", confirmations);
216 if (blockindex.
pprev)
227 const CTxIn& vin_0{coinbase_tx.
vin[0]};
231 coinbase_tx_obj.
pushKV(
"sequence", vin_0.nSequence);
232 coinbase_tx_obj.
pushKV(
"coinbase",
HexStr(vin_0.scriptSig));
233 const auto& witness_stack{vin_0.scriptWitness.stack};
234 if (!witness_stack.empty()) {
236 coinbase_tx_obj.
pushKV(
"witness",
HexStr(witness_stack[0]));
238 return coinbase_tx_obj;
265 const bool is_not_pruned{
WITH_LOCK(
::cs_main,
return !blockman.IsBlockPruned(blockindex))};
267 if (have_undo && !blockman.
ReadBlockUndo(blockUndo, blockindex)) {
268 throw JSONRPCError(
RPC_INTERNAL_ERROR,
"Undo data expected but can't be read. This could be due to disk corruption or a conflict with a pruning event.");
270 for (
size_t i = 0; i < block.
vtx.size(); ++i) {
273 const CTxUndo* txundo = (have_undo && i > 0) ? &blockUndo.
vtxundo.at(i - 1) :
nullptr;
281 result.
pushKV(
"tx", std::move(txs));
290 "Returns the height of the most-work fully-validated chain.\n"
291 "The genesis block has height 0.\n",
312 "Returns the hash of the best (tip) block in the most-work fully-validated chain.\n",
333 "Waits for any new block and returns useful info about it.\n"
334 "\nReturns the current block on timeout or exit.\n"
335 "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
353 if (!request.params[0].isNull())
354 timeout = request.params[0].
getInt<
int>();
368 uint256 tip_hash{request.params[1].isNull()
370 :
ParseHashV(request.params[1],
"current_tip")};
374 std::optional<BlockRef> block = timeout ? block_template_manager.
WaitTipChanged(tip_hash, std::chrono::milliseconds(timeout)) :
378 if (block) current_block = *block;
381 ret.pushKV(
"hash", current_block.hash.GetHex());
382 ret.pushKV(
"height", current_block.height);
392 "Waits for a specific new block and returns useful info about it.\n"
393 "\nReturns the current block on timeout or exit.\n"
394 "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
406 HelpExampleCli(
"waitforblock",
"\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000")
407 +
HelpExampleRpc(
"waitforblock",
"\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
415 if (!request.params[1].isNull())
416 timeout = request.params[1].getInt<
int>();
425 const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
426 while (current_block.hash != hash) {
427 std::optional<BlockRef> block;
429 auto now{std::chrono::steady_clock::now()};
430 if (now >= deadline)
break;
432 block = block_template_manager.
WaitTipChanged(current_block.hash, remaining);
434 block = block_template_manager.
WaitTipChanged(current_block.hash);
438 current_block = *block;
442 ret.pushKV(
"hash", current_block.hash.GetHex());
443 ret.pushKV(
"height", current_block.height);
452 "waitforblockheight",
453 "Waits for (at least) block height and returns the height and hash\n"
454 "of the current tip.\n"
455 "\nReturns the current block on timeout or exit.\n"
456 "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
475 int height = request.params[0].
getInt<
int>();
477 if (!request.params[1].isNull())
478 timeout = request.params[1].getInt<
int>();
487 const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
489 while (current_block.height < height) {
490 std::optional<BlockRef> block;
492 auto now{std::chrono::steady_clock::now()};
493 if (now >= deadline)
break;
495 block = block_template_manager.
WaitTipChanged(current_block.hash, remaining);
497 block = block_template_manager.
WaitTipChanged(current_block.hash);
501 current_block = *block;
505 ret.pushKV(
"hash", current_block.hash.GetHex());
506 ret.pushKV(
"height", current_block.height);
515 "syncwithvalidationinterfacequeue",
516 "Waits for the validation interface queue to catch up on everything that was there when we entered this function.\n",
536 "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
539 RPCResult::Type::NUM,
"",
"the proof-of-work difficulty as a multiple of the minimum difficulty."},
557 "Attempt to fetch block from a given peer.\n\n"
558 "We must have the header for this block, e.g. using submitheader.\n"
559 "The block will not have any undo data which can limit the usage of the block data in a context where the undo data is needed.\n"
560 "Subsequent calls for the same block may cause the response from the previous peer to be ignored.\n"
561 "Peers generally ignore requests for a stale block that they never fully verified, or one that is more than a month old.\n"
562 "When a peer does not respond with a block, we will disconnect.\n"
563 "Note: The block could be re-pruned as soon as it is received.\n\n"
564 "Returns an empty JSON object if the request was successfully scheduled.",
571 HelpExampleCli(
"getblockfrompeer",
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0")
572 +
HelpExampleRpc(
"getblockfrompeer", R
"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", 0)")
581 const NodeId peer_id{request.params[1].getInt<int64_t>()};
592 throw JSONRPCError(
RPC_MISC_ERROR,
"In prune mode, only blocks that the node has already synced previously can be fetched from a peer");
596 if (block_has_data) {
600 if (
const auto res{peerman.
FetchBlock(peer_id, *index)}; !res) {
612 "Returns hash of block in best-block-chain at height provided.\n",
628 int nHeight = request.params[0].getInt<
int>();
629 if (nHeight < 0 || nHeight > active_chain.
Height())
642 "If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
643 "If verbose is true, returns an Object with information about blockheader <hash>.\n",
653 {
RPCResult::Type::NUM,
"confirmations",
"The number of confirmations, or -1 if the block is not on the main chain"},
673 HelpExampleCli(
"getblockheader",
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
674 +
HelpExampleRpc(
"getblockheader",
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
680 bool fVerbose =
true;
681 if (!request.params[1].isNull())
682 fVerbose = request.params[1].get_bool();
701 std::string strHex =
HexStr(ssBlock);
714 if (!(blockindex.nStatus & flag)) {
715 if (blockman.IsBlockPruned(blockindex)) {
718 if (check_for_undo) {
733 if (!blockman.
ReadBlock(block, blockindex)) {
762 if (blockindex.
nHeight == 0)
return blockUndo;
778 auto fields = std::vector<RPCResult>{
780 {
RPCResult::Type::NUM,
"confirmations",
"The number of confirmations, or -1 if the block is not on the main chain"},
790 {
RPCResult::Type::STR_HEX,
"witness",
true,
"The coinbase input's first (and only) witness stack element, if present"},
797 fields.push_back(std::move(tx_result));
801 fields.emplace_back(
RPCResult::Type::STR_HEX,
"bits",
"nBits: compact representation of the block difficulty target");
804 fields.emplace_back(
RPCResult::Type::STR_HEX,
"chainwork",
"Expected number of hashes required to produce the chain up to this block (in hex)");
806 fields.emplace_back(
RPCResult::Type::STR_HEX,
"previousblockhash",
true,
"The hash of the previous block (if available)");
810 std::vector<RPCResult> new_fields;
811 new_fields.reserve(fields.size());
813 for (
const auto& f : fields) {
814 if (f.m_key_name ==
"tx") {
815 new_fields.push_back(f);
821 new_fields.emplace_back(f, std::move(eopts));
826 new_fields.emplace_back(f, std::move(eopts));
829 fields = std::move(new_fields);
838 "If verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
839 "If verbosity is 1, returns an Object with information about block <hash>.\n"
840 "If verbosity is 2, returns an Object with information about block <hash> and information about each transaction.\n"
841 "If verbosity is 3, returns an Object with information about block <hash> and information about each transaction, including prevout information for inputs (only for unpruned blocks in the current best chain).\n",
844 {
"verbosity|verbose",
RPCArg::Type::NUM,
RPCArg::Default{1},
"0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs",
857 .elision_summary =
"The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result",
858 .fee =
true, .hex =
true,
859 .fee_doc =
"The transaction fee in " +
CURRENCY_UNIT +
", omitted if block undo data is not available"})},
860 }},
"Same output as verbosity = 1")},
867 .prevout_optional =
true,
871 .prevout_doc =
"(Only if undo information is available)",
872 .vin_inner_elision =
"The same output as verbosity = 2"})},
873 }},
"Same output as verbosity = 2")},
876 HelpExampleCli(
"getblock",
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
877 +
HelpExampleRpc(
"getblock",
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
900 if (verbosity <= 0) {
901 return HexStr(block_data);
908 if (verbosity == 1) {
910 }
else if (verbosity == 2) {
932 if (!first_block || !chain_tip)
return std::nullopt;
937 const auto& first_unpruned{blockman.GetFirstBlock(*chain_tip,
BLOCK_HAVE_MASK, first_block)};
938 if (&first_unpruned == first_block) {
950 "Attempts to delete block and undo data up to a specified height or timestamp, if eligible for pruning.\n"
951 "Requires `-prune` to be enabled at startup. While pruned data may be re-fetched in some cases (e.g., via `getblockfrompeer`), local deletion is irreversible.\n",
954 " to prune blocks whose block time is at least 2 hours older than the provided timestamp."},
973 int heightParam = request.params[0].getInt<
int>();
974 if (heightParam < 0) {
980 if (heightParam > 1000000000) {
989 unsigned int height = (
unsigned int) heightParam;
990 unsigned int chainHeight = (
unsigned int) active_chain.
Height();
993 }
else if (height > chainHeight) {
996 LogDebug(
BCLog::RPC,
"Attempt to prune blocks close to the tip. Retaining the minimum number of blocks.\n");
1008 if (hash_type_input ==
"hash_serialized_3") {
1009 return CoinStatsHashType::HASH_SERIALIZED;
1010 }
else if (hash_type_input ==
"muhash") {
1011 return CoinStatsHashType::MUHASH;
1012 }
else if (hash_type_input ==
"none") {
1026 const std::function<
void()>& interruption_point = {},
1028 bool index_requested =
true)
1053 "Returns statistics about the unspent transaction output set.\n"
1054 "Note this call may take some time if you are not using coinstatsindex.\n",
1056 {
"hash_type",
RPCArg::Type::STR,
RPCArg::Default{
"hash_serialized_3"},
"Which UTXO set hash should be calculated. Options: 'hash_serialized_3' (the legacy algorithm), 'muhash', 'none'."},
1060 .type_str = {
"",
"string or numeric"},
1070 {
RPCResult::Type::NUM,
"bogosize",
"Database-independent, meaningless metric indicating the UTXO set size"},
1071 {
RPCResult::Type::STR_HEX,
"hash_serialized_3",
true,
"The serialized hash (only present if 'hash_serialized_3' hash_type is chosen)"},
1073 {
RPCResult::Type::NUM,
"transactions",
true,
"The number of transactions with unspent outputs (not available when coinstatsindex is used)"},
1074 {
RPCResult::Type::NUM,
"disk_size",
true,
"The estimated size of the chainstate on disk (not available when coinstatsindex is used)"},
1076 {
RPCResult::Type::STR_AMOUNT,
"total_unspendable_amount",
true,
"The total amount of coins permanently excluded from the UTXO set (only available if coinstatsindex is used)"},
1077 {
RPCResult::Type::OBJ,
"block_info",
true,
"Info on amounts in the block at this block height (only available if coinstatsindex is used)",
1096 HelpExampleCli("gettxoutsetinfo", R
"("none" 00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09)") +
1097 HelpExampleCli("-named gettxoutsetinfo", R
"(hash_type='muhash' use_index='false')") +
1101 HelpExampleRpc("gettxoutsetinfo", R
"("none", "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09")")
1108 bool index_requested = request.params[2].isNull() || request.params[2].get_bool();
1119 if (!request.params[1].isNull()) {
1124 if (hash_type == CoinStatsHashType::HASH_SERIALIZED) {
1128 if (!index_requested) {
1140 if (pindex && pindex->
nHeight > summary.best_block_height) {
1146 const std::optional<CCoinsStats> maybe_stats =
GetUTXOStats(coins_view, blockman, hash_type,
node.rpc_interruption_point, pindex, index_requested);
1147 if (maybe_stats.has_value()) {
1153 if (hash_type == CoinStatsHashType::HASH_SERIALIZED) {
1156 if (hash_type == CoinStatsHashType::MUHASH) {
1168 const std::optional<CCoinsStats> maybe_prev_stats =
GetUTXOStats(coins_view, blockman, hash_type,
node.rpc_interruption_point, block_index.
pprev, index_requested);
1169 if (!maybe_prev_stats) {
1172 prev_stats = maybe_prev_stats.value();
1179 CAmount prev_block_total_unspendable_amount = prev_stats.total_unspendables_genesis_block +
1180 prev_stats.total_unspendables_bip30 +
1181 prev_stats.total_unspendables_scripts +
1182 prev_stats.total_unspendables_unclaimed_rewards;
1184 ret.pushKV(
"total_unspendable_amount",
ValueFromAmount(block_total_unspendable_amount));
1197 block_info.
pushKV(
"unspendable",
ValueFromAmount(block_total_unspendable_amount - prev_block_total_unspendable_amount));
1204 block_info.
pushKV(
"unspendables", std::move(unspendables));
1206 ret.pushKV(
"block_info", std::move(block_info));
1220 "Returns details about an unspent transaction output.\n",
1224 {
"include_mempool",
RPCArg::Type::BOOL,
RPCArg::Default{
true},
"Whether to include the mempool. Note that an unspent output that is spent in the mempool won't appear."},
1237 {
RPCResult::Type::STR,
"address",
true,
"The Bitcoin address (only if a well-defined address exists)"},
1243 "\nGet unspent transactions\n"
1245 "\nView the details\n"
1247 "\nAs a JSON-RPC call\n"
1259 COutPoint out{hash, request.params[1].getInt<uint32_t>()};
1260 bool fMempool =
true;
1261 if (!request.params[2].isNull())
1262 fMempool = request.params[2].get_bool();
1267 std::optional<Coin> coin;
1281 ret.pushKV(
"confirmations", 0);
1283 ret.pushKV(
"confirmations", pindex->
nHeight - coin->nHeight + 1);
1288 ret.pushKV(
"scriptPubKey", std::move(o));
1289 ret.pushKV(
"coinbase", coin->IsCoinBase());
1300 "Verifies blockchain database.\n",
1307 RPCResult::Type::BOOL,
"",
"Verification finished successfully. If false, check debug log for reason."},
1315 const int check_depth{request.params[1].isNull() ?
DEFAULT_CHECKBLOCKS : request.params[1].getInt<
int>()};
1334 rv.
pushKV(
"type",
"buried");
1346 if (blockindex ==
nullptr)
return;
1353 if (info.stats.has_value()) {
1354 bip9.
pushKV(
"bit", depparams.bit);
1356 bip9.
pushKV(
"start_time", depparams.nStartTime);
1357 bip9.
pushKV(
"timeout", depparams.nTimeout);
1358 bip9.
pushKV(
"min_activation_height", depparams.min_activation_height);
1361 bip9.
pushKV(
"status", info.current_state);
1362 bip9.
pushKV(
"since", info.since);
1363 bip9.
pushKV(
"status_next", info.next_state);
1366 if (info.stats.has_value()) {
1368 statsUV.
pushKV(
"period", info.stats->period);
1369 statsUV.
pushKV(
"elapsed", info.stats->elapsed);
1370 statsUV.
pushKV(
"count", info.stats->count);
1371 if (info.stats->threshold > 0 || info.stats->possible) {
1372 statsUV.
pushKV(
"threshold", info.stats->threshold);
1373 statsUV.
pushKV(
"possible", info.stats->possible);
1375 bip9.
pushKV(
"statistics", std::move(statsUV));
1378 sig.reserve(info.signalling_blocks.size());
1379 for (
const bool s : info.signalling_blocks) {
1380 sig.push_back(
s ?
'#' :
'-');
1382 bip9.
pushKV(
"signalling", sig);
1386 rv.
pushKV(
"type",
"bip9");
1387 bool is_active =
false;
1388 if (info.active_since.has_value()) {
1389 rv.
pushKV(
"height", *info.active_since);
1390 is_active = (*info.active_since <= blockindex->
nHeight + 1);
1392 rv.
pushKV(
"active", is_active);
1401 "Returns an object containing various state info regarding blockchain processing.\n",
1407 {
RPCResult::Type::NUM,
"blocks",
"the height of the most-work fully-validated chain. The genesis block has height 0"},
1416 {
RPCResult::Type::BOOL,
"initialblockdownload",
"(debug information) estimate of whether this node is in Initial Block Download mode"},
1417 {
RPCResult::Type::OBJ,
"backgroundvalidation",
true,
"state info regarding background validation process",
1419 {
RPCResult::Type::NUM,
"snapshotheight",
"the height of the snapshot block. Background validation verifies the chain from genesis up to this height"},
1420 {
RPCResult::Type::NUM,
"blocks",
"the height of the most-work background fully-validated chain. The genesis block has height 0"},
1421 {
RPCResult::Type::STR,
"bestblockhash",
"the hash of the currently best block validated in the background"},
1423 {
RPCResult::Type::NUM,
"verificationprogress",
"estimate of background verification progress [0..1]"},
1427 {
RPCResult::Type::NUM,
"size_on_disk",
"the estimated size of the block and undo files on disk"},
1429 {
RPCResult::Type::NUM,
"pruneheight",
true,
"the first block unpruned, all previous blocks were pruned (only present if pruning is enabled)"},
1430 {
RPCResult::Type::BOOL,
"automatic_pruning",
true,
"whether automatic pruning is enabled (only present if pruning is enabled)"},
1431 {
RPCResult::Type::NUM,
"prune_target_size",
true,
"the target size used by pruning (only present if automatic pruning is enabled)"},
1432 {
RPCResult::Type::STR_HEX,
"signet_challenge",
true,
"the block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)"},
1435 RPCResult{
RPCResult::Type::ARR,
"warnings",
"any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)",
1453 const int height{tip.
nHeight};
1456 obj.
pushKV(
"blocks", height);
1457 obj.
pushKV(
"headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
1466 auto historical_blocks{chainman.GetHistoricalBlockRange()};
1467 if (historical_blocks) {
1471 background_validation.
pushKV(
"snapshotheight", btarget.nHeight);
1472 background_validation.
pushKV(
"blocks", btip.nHeight);
1473 background_validation.
pushKV(
"bestblockhash", btip.GetBlockHash().GetHex());
1474 background_validation.
pushKV(
"mediantime", btip.GetMedianTimePast());
1475 background_validation.
pushKV(
"chainwork", btip.nChainWork.GetHex());
1477 obj.
pushKV(
"backgroundvalidation", std::move(background_validation));
1484 obj.
pushKV(
"pruneheight", prune_height ? prune_height.value() + 1 : 0);
1487 obj.
pushKV(
"automatic_pruning", automatic_pruning);
1488 if (automatic_pruning) {
1493 const std::vector<uint8_t>& signet_challenge =
1495 obj.
pushKV(
"signet_challenge",
HexStr(signet_challenge));
1506const std::vector<RPCResult> RPCHelpForDeployment{
1508 {
RPCResult::Type::NUM,
"height",
true,
"height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"},
1509 {
RPCResult::Type::BOOL,
"active",
"true if the rules are enforced for the mempool and the next block"},
1512 {
RPCResult::Type::NUM,
"bit",
true,
"the bit (0-28) in the block version field used to signal this softfork (only for \"started\" and \"locked_in\" status)"},
1513 {
RPCResult::Type::NUM_TIME,
"start_time",
"the minimum median time past of a block at which the bit gains its meaning"},
1514 {
RPCResult::Type::NUM_TIME,
"timeout",
"the median time past of a block at which the deployment is considered failed if not yet locked in"},
1515 {
RPCResult::Type::NUM,
"min_activation_height",
"minimum height of blocks for which the rules may be enforced"},
1516 {
RPCResult::Type::STR,
"status",
"status of deployment at specified block (one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\")"},
1519 {
RPCResult::Type::OBJ,
"statistics",
true,
"numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)",
1522 {
RPCResult::Type::NUM,
"threshold",
true,
"the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"},
1523 {
RPCResult::Type::NUM,
"elapsed",
"the number of blocks elapsed since the beginning of the current period"},
1524 {
RPCResult::Type::NUM,
"count",
"the number of blocks with the version bit set in the current period"},
1525 {
RPCResult::Type::BOOL,
"possible",
true,
"returns false if there are not enough blocks left in this period to pass activation threshold (only for \"started\" status)"},
1527 {
RPCResult::Type::STR,
"signalling",
true,
"indicates blocks that signalled with a # and blocks that did not with a -"},
1547 "Returns an object containing various state info regarding deployments of consensus changes.\n"
1548 "Consensus changes for which the new rules are enforced from genesis are not listed in \"deployments\".",
1572 if (request.params[0].isNull()) {
1588 uv_flagnames.
push_backV(flagnames.begin(), flagnames.end());
1589 deploymentinfo.
pushKV(
"script_flags", uv_flagnames);
1591 deploymentinfo.
pushKV(
"deployments", DeploymentInfo(blockindex, chainman));
1592 return deploymentinfo;
1615 "Return information about all known tips in the block tree,"
1616 " including the main chain as well as orphaned branches.\n",
1624 {
RPCResult::Type::NUM,
"branchlen",
"zero for main chain, otherwise length of branch connecting the tip to the main chain"},
1626 "Possible values for status:\n"
1627 "1. \"invalid\" This branch contains at least one invalid block\n"
1628 "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
1629 "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
1630 "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
1631 "5. \"active\" This is the tip of the active main chain, which is certainly valid"},
1650 std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
1651 std::set<const CBlockIndex*> setOrphans;
1652 std::set<const CBlockIndex*> setPrevs;
1654 for (
const auto& [
_, block_index] : chainman.
BlockIndex()) {
1655 if (!active_chain.
Contains(block_index)) {
1656 setOrphans.insert(&block_index);
1657 setPrevs.insert(block_index.pprev);
1661 for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it) {
1662 if (setPrevs.erase(*it) == 0) {
1663 setTips.insert(*it);
1668 setTips.insert(active_chain.
Tip());
1675 obj.
pushKV(
"height", block->nHeight);
1676 obj.
pushKV(
"hash", block->phashBlock->GetHex());
1678 const int branchLen = block->nHeight - active_chain.
FindFork(*block)->
nHeight;
1679 obj.
pushKV(
"branchlen", branchLen);
1682 if (active_chain.
Contains(*block)) {
1688 }
else if (!block->HaveNumChainTxs()) {
1690 status =
"headers-only";
1693 status =
"valid-fork";
1696 status =
"valid-headers";
1701 obj.
pushKV(
"status", status);
1715 "Treats a block as if it were received before others with the same work.\n"
1716 "\nThis only breaks ties between chains with equal work. If the specified block has the same work as the current tip, "
1717 "the node switches its active chain to it. If the specified block has less work than the current tip (including any "
1718 "ancestor of the tip), the call has no effect. If another chain later gains more work, the node switches to it as usual.\n"
1719 "\nA later preciousblock call can override the effect of an earlier one.\n"
1720 "\nThe effects of preciousblock are not retained across restarts.\n",
1780 "Permanently marks a block as invalid, as if it violated a consensus rule.\n",
1810 chainman.RecalculateBestHeader();
1825 "Removes invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n"
1826 "This can be used to undo the effects of invalidateblock.\n",
1851 "Compute statistics about the total number and rate of transactions in the chain.\n",
1861 "The total number of transactions in the chain up to that point, if known. "
1862 "It may be unknown when using assumeutxo."},
1864 {
RPCResult::Type::NUM,
"window_final_block_height",
"The height of the final block in the window."},
1866 {
RPCResult::Type::NUM,
"window_interval",
true,
"The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0"},
1868 "The number of transactions in the window. "
1869 "Only returned if \"window_block_count\" is > 0 and if txcount exists for the start and end of the window."},
1871 "The average rate of transactions per second in the window. "
1872 "Only returned if \"window_interval\" is > 0 and if window_tx_count exists."},
1884 if (request.params[1].isNull()) {
1901 if (request.params[0].isNull()) {
1902 blockcount = std::max(0, std::min(blockcount, pindex->
nHeight - 1));
1904 blockcount = request.params[0].getInt<
int>();
1906 if (blockcount < 0 || (blockcount > 0 && blockcount >= pindex->
nHeight)) {
1912 const int64_t nTimeDiff{pindex->
GetMedianTimePast() - past_block.GetMedianTimePast()};
1920 ret.pushKV(
"window_final_block_height", pindex->
nHeight);
1921 ret.pushKV(
"window_block_count", blockcount);
1922 if (blockcount > 0) {
1923 ret.pushKV(
"window_interval", nTimeDiff);
1925 const auto window_tx_count = pindex->
m_chain_tx_count - past_block.m_chain_tx_count;
1926 ret.pushKV(
"window_tx_count", window_tx_count);
1927 if (nTimeDiff > 0) {
1928 ret.pushKV(
"txrate",
double(window_tx_count) / nTimeDiff);
1941 size_t size = scores.size();
1946 std::sort(scores.begin(), scores.end());
1947 if (size % 2 == 0) {
1948 return (scores[size / 2 - 1] + scores[size / 2]) / 2;
1950 return scores[size / 2];
1956 if (scores.empty()) {
1960 std::sort(scores.begin(), scores.end());
1964 total_weight / 10.0, total_weight / 4.0, total_weight / 2.0, (total_weight * 3.0) / 4.0, (total_weight * 9.0) / 10.0
1967 int64_t next_percentile_index = 0;
1968 int64_t cumulative_weight = 0;
1969 for (
const auto& element : scores) {
1970 cumulative_weight += element.second;
1971 while (next_percentile_index < NUM_GETBLOCKSTATS_PERCENTILES && cumulative_weight >= weights[next_percentile_index]) {
1972 result[next_percentile_index] = element.first;
1973 ++next_percentile_index;
1979 result[i] = scores.back().first;
1984static inline bool SetHasKeys(
const std::set<T>& set) {
return false;}
1985template<
typename T,
typename Tk,
typename... Args>
1986static inline bool SetHasKeys(
const std::set<T>& set,
const Tk& key,
const Args&...
args)
1998 "Compute per block statistics for a given window. All amounts are in satoshis.\n"
1999 "It won't work for some heights with pruning.\n",
2004 .type_str = {
"",
"string or numeric"},
2020 {
RPCResult::Type::ARR_FIXED,
"feerate_percentiles",
true,
"Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)",
2045 {
RPCResult::Type::NUM,
"total_out",
true,
"Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"},
2050 {
RPCResult::Type::NUM,
"utxo_increase",
true,
"The increase/decrease in the number of unspent outputs (not discounting op_return and similar)"},
2051 {
RPCResult::Type::NUM,
"utxo_size_inc",
true,
"The increase/decrease in size for the utxo index (not discounting op_return and similar)"},
2052 {
RPCResult::Type::NUM,
"utxo_increase_actual",
true,
"The increase/decrease in the number of unspent outputs, not counting unspendables"},
2053 {
RPCResult::Type::NUM,
"utxo_size_inc_actual",
true,
"The increase/decrease in size for the utxo index, not counting unspendables"},
2056 HelpExampleCli(
"getblockstats", R
"(00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09 '["minfeerate","avgfeerate"]')") +
2057 HelpExampleCli("getblockstats", R
"(1000 '["minfeerate","avgfeerate"]')") +
2058 HelpExampleRpc("getblockstats", R
"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") +
2059 HelpExampleRpc("getblockstats", R
"(1000, ["minfeerate","avgfeerate"])")
2066 std::set<std::string> stats;
2067 if (!request.params[1].isNull()) {
2069 for (
unsigned int i = 0; i < stats_univalue.
size(); i++) {
2070 const std::string stat = stats_univalue[i].
get_str();
2078 const bool do_all = stats.size() == 0;
2079 const bool do_mediantxsize = do_all || stats.contains(
"mediantxsize");
2080 const bool do_medianfee = do_all || stats.contains(
"medianfee");
2081 const bool do_feerate_percentiles = do_all || stats.contains(
"feerate_percentiles");
2082 const bool loop_inputs = do_all || do_medianfee || do_feerate_percentiles ||
2083 SetHasKeys(stats,
"utxo_increase",
"utxo_increase_actual",
"utxo_size_inc",
"utxo_size_inc_actual",
"totalfee",
"avgfee",
"avgfeerate",
"minfee",
"maxfee",
"minfeerate",
"maxfeerate");
2084 const bool loop_outputs = do_all || loop_inputs || stats.contains(
"total_out");
2085 const bool do_calculate_size = do_mediantxsize ||
2086 SetHasKeys(stats,
"total_size",
"avgtxsize",
"mintxsize",
"maxtxsize",
"swtotal_size");
2087 const bool do_calculate_weight = do_all ||
SetHasKeys(stats,
"total_weight",
"avgfeerate",
"swtotal_weight",
"avgfeerate",
"feerate_percentiles",
"minfeerate",
"maxfeerate");
2088 const bool do_calculate_sw = do_all ||
SetHasKeys(stats,
"swtxs",
"swtotal_size",
"swtotal_weight");
2097 int64_t maxtxsize = 0;
2099 int64_t outputs = 0;
2100 int64_t swtotal_size = 0;
2101 int64_t swtotal_weight = 0;
2103 int64_t total_size = 0;
2104 int64_t total_weight = 0;
2106 int64_t utxo_size_inc = 0;
2107 int64_t utxo_size_inc_actual = 0;
2108 std::vector<CAmount> fee_array;
2109 std::vector<std::pair<CAmount, int64_t>> feerate_array;
2110 std::vector<int64_t> txsize_array;
2112 for (
size_t i = 0; i < block.
vtx.size(); ++i) {
2113 const auto& tx = block.
vtx.at(i);
2114 outputs += tx->vout.size();
2119 tx_total_out +=
out.nValue;
2122 utxo_size_inc += out_size;
2128 if (
out.scriptPubKey.IsUnspendable())
continue;
2131 utxo_size_inc_actual += out_size;
2135 if (tx->IsCoinBase()) {
2139 inputs += tx->vin.size();
2140 total_out += tx_total_out;
2142 int64_t tx_size = 0;
2143 if (do_calculate_size) {
2145 tx_size = tx->ComputeTotalSize();
2146 if (do_mediantxsize) {
2147 txsize_array.push_back(tx_size);
2149 maxtxsize = std::max(maxtxsize, tx_size);
2150 mintxsize = std::min(mintxsize, tx_size);
2151 total_size += tx_size;
2155 if (do_calculate_weight) {
2157 total_weight += weight;
2160 if (do_calculate_sw && tx->HasWitness()) {
2162 swtotal_size += tx_size;
2163 swtotal_weight += weight;
2168 const auto& txundo = blockUndo.
vtxundo.at(i - 1);
2169 for (
const Coin& coin: txundo.vprevout) {
2172 tx_total_in += prevoutput.
nValue;
2174 utxo_size_inc -= prevout_size;
2175 utxo_size_inc_actual -= prevout_size;
2178 CAmount txfee = tx_total_in - tx_total_out;
2181 fee_array.push_back(txfee);
2183 maxfee = std::max(maxfee, txfee);
2184 minfee = std::min(minfee, txfee);
2189 if (do_feerate_percentiles) {
2190 feerate_array.emplace_back(feerate, weight);
2192 maxfeerate = std::max(maxfeerate, feerate);
2193 minfeerate = std::min(minfeerate, feerate);
2202 feerates_res.
push_back(feerate_percentiles[i]);
2206 ret_all.
pushKV(
"avgfee", (block.
vtx.size() > 1) ? totalfee / (block.
vtx.size() - 1) : 0);
2208 ret_all.
pushKV(
"avgtxsize", (block.
vtx.size() > 1) ? total_size / (block.
vtx.size() - 1) : 0);
2210 ret_all.
pushKV(
"feerate_percentiles", std::move(feerates_res));
2212 ret_all.
pushKV(
"ins", inputs);
2213 ret_all.
pushKV(
"maxfee", maxfee);
2214 ret_all.
pushKV(
"maxfeerate", maxfeerate);
2215 ret_all.
pushKV(
"maxtxsize", maxtxsize);
2220 ret_all.
pushKV(
"minfeerate", (minfeerate ==
MAX_MONEY) ? 0 : minfeerate);
2222 ret_all.
pushKV(
"outs", outputs);
2224 ret_all.
pushKV(
"swtotal_size", swtotal_size);
2225 ret_all.
pushKV(
"swtotal_weight", swtotal_weight);
2226 ret_all.
pushKV(
"swtxs", swtxs);
2228 ret_all.
pushKV(
"total_out", total_out);
2229 ret_all.
pushKV(
"total_size", total_size);
2230 ret_all.
pushKV(
"total_weight", total_weight);
2231 ret_all.
pushKV(
"totalfee", totalfee);
2232 ret_all.
pushKV(
"txs", block.
vtx.size());
2233 ret_all.
pushKV(
"utxo_increase", outputs - inputs);
2234 ret_all.
pushKV(
"utxo_size_inc", utxo_size_inc);
2235 ret_all.
pushKV(
"utxo_increase_actual", utxos - inputs);
2236 ret_all.
pushKV(
"utxo_size_inc_actual", utxo_size_inc_actual);
2243 for (
const std::string& stat : stats) {
2244 const UniValue& value = ret_all[stat];
2248 ret.pushKVEnd(stat, value);
2257bool FindScriptPubKey(std::atomic<int>& scan_progress,
const std::atomic<bool>& should_abort, int64_t&
count,
CCoinsViewCursor* cursor,
const std::set<CScript>& needles, std::map<COutPoint, Coin>& out_results, std::function<
void()>& interruption_point)
2261 while (cursor->
Valid()) {
2264 if (!cursor->
GetKey(key) || !cursor->
GetValue(coin))
return false;
2265 if (++
count % 8192 == 0) {
2266 interruption_point();
2272 if (
count % 256 == 0) {
2275 scan_progress = (int)(high * 100.0 / 65536.0 + 0.5);
2278 out_results.emplace(key, coin);
2282 scan_progress = 100;
2318 "\"start\" for starting a scan\n"
2319 "\"abort\" for aborting the current scan (returns true when abort was successful)\n"
2320 "\"status\" for progress report (in %) of the current scan"
2333 "Every scan object is either a string descriptor or an object:",
2343 "True if scan will be aborted (not necessarily before this RPC returns), or false if there is no scan to abort"
2346 "when action=='status' and no scan is in progress - possibly already completed",
RPCResult::Type::NONE,
"",
""
2357 const std::string EXAMPLE_DESCRIPTOR_RAW =
"raw(76a91411b366edfc0a8b66feebae5c2e25a7b6a5d1cf3188ac)#fm24fxxy";
2361 "Scans the unspent transaction output set for entries that match certain output descriptors.\n"
2362 "Examples of output descriptors are:\n"
2363 " addr(<address>) Outputs whose output script corresponds to the specified address (does not include P2PK)\n"
2364 " raw(<hex script>) Outputs whose output script equals the specified hex-encoded bytes\n"
2365 " combo(<pubkey>) P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH outputs for the given pubkey\n"
2366 " pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
2367 " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
2368 " tr(<pubkey>) P2TR\n"
2369 " tr(<pubkey>,{pk(<pubkey>)}) P2TR with single fallback pubkey in tapscript\n"
2370 " rawtr(<pubkey>) P2TR with the specified key as output key rather than inner\n"
2371 " wsh(and_v(v:pk(<pubkey>),after(2))) P2WSH miniscript with mandatory pubkey and a timelock\n"
2372 "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
2373 "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
2374 "unhardened or hardened child keys.\n"
2375 "In the latter case, a range needs to be specified by below if different from 1000.\n"
2376 "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n",
2399 {
RPCResult::Type::NUM,
"confirmations",
"Number of confirmations of the unspent transaction output when the scan was done"},
2409 HelpExampleCli(
"scantxoutset",
"start \'[\"" + EXAMPLE_DESCRIPTOR_RAW +
"\"]\'") +
2412 HelpExampleRpc(
"scantxoutset",
"\"start\", [\"" + EXAMPLE_DESCRIPTOR_RAW +
"\"]") +
2419 const auto action{self.
Arg<std::string_view>(
"action")};
2420 if (action ==
"status") {
2428 }
else if (action ==
"abort") {
2437 }
else if (action ==
"start") {
2448 std::set<CScript> needles;
2449 std::map<CScript, std::string> descriptors;
2459 descriptors.emplace(std::move(
script), std::move(inferred));
2465 std::vector<CTxOut> input_txos;
2466 std::map<COutPoint, Coin> coins;
2469 std::unique_ptr<CCoinsViewCursor> pcursor;
2481 result.
pushKV(
"success", res);
2486 for (
const auto& it : coins) {
2488 const Coin& coin = it.second;
2491 input_txos.push_back(txo);
2496 unspent.
pushKV(
"vout", outpoint.
n);
2502 unspent.
pushKV(
"blockhash", coinb_block.GetBlockHash().GetHex());
2507 result.
pushKV(
"unspents", std::move(unspents));
2551 for (
const auto& tx : block.vtx) {
2552 if (std::any_of(tx->vout.cbegin(), tx->vout.cend(), [&](
const auto& txout) {
2553 return needles.contains(std::vector<unsigned char>(txout.scriptPubKey.begin(), txout.scriptPubKey.end()));
2559 for (
const auto& txundo : block_undo.vtxundo) {
2560 if (std::any_of(txundo.vprevout.cbegin(), txundo.vprevout.cend(), [&](
const auto& coin) {
2561 return needles.contains(std::vector<unsigned char>(coin.out.scriptPubKey.begin(), coin.out.scriptPubKey.end()));
2574 "Return relevant blockhashes for given descriptors (requires blockfilterindex).\n"
2575 "This call may take several minutes. Make sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
2584 {
"filter_false_positives",
RPCArg::Type::BOOL,
RPCArg::Default{
false},
"Filter false positives (slower and may fail on pruned nodes). Otherwise they may occur at a rate of 1/M"},
2606 HelpExampleCli(
"scanblocks",
"start '[\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"]' 300000") +
2607 HelpExampleCli(
"scanblocks",
"start '[\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"]' 100 150 basic") +
2609 HelpExampleRpc(
"scanblocks",
"\"start\", [\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"], 300000") +
2610 HelpExampleRpc(
"scanblocks",
"\"start\", [\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"], 100, 150, \"basic\"") +
2616 auto action{self.
Arg<std::string_view>(
"action")};
2617 if (action ==
"status") {
2626 }
else if (action ==
"abort") {
2635 }
else if (action ==
"start") {
2644 auto filtertype_name{self.
Arg<std::string_view>(
"filtertype")};
2652 bool filter_false_positives{options.exists(
"filter_false_positives") ? options[
"filter_false_positives"].get_bool() :
false};
2668 start_index = active_chain.
Genesis();
2669 stop_block = active_chain.
Tip();
2670 if (!request.params[2].isNull()) {
2671 start_index = active_chain[request.params[2].getInt<
int>()];
2676 if (!request.params[3].isNull()) {
2677 stop_block = active_chain[request.params[3].getInt<
int>()];
2696 const int amount_per_chunk = 10000;
2697 std::vector<BlockFilter> filters;
2698 int start_block_height = start_index->
nHeight;
2699 const int total_blocks_to_process = stop_block->
nHeight - start_block_height;
2704 bool completed =
true;
2708 node.rpc_interruption_point();
2715 int start_block = !end_range ? start_index->
nHeight : start_index->
nHeight + 1;
2716 end_range = (start_block + amount_per_chunk < stop_block->
nHeight) ?
2723 if (filter.GetFilter().MatchAny(needle_set)) {
2724 if (filter_false_positives) {
2733 blocks.
push_back(filter.GetBlockHash().GetHex());
2737 start_index = end_range;
2740 int blocks_processed = end_range->
nHeight - start_block_height;
2741 if (total_blocks_to_process > 0) {
2749 }
while (start_index != stop_block);
2751 ret.pushKV(
"from_height", start_block_height);
2752 ret.pushKV(
"to_height", start_index->
nHeight);
2753 ret.pushKV(
"relevant_blocks", std::move(blocks));
2754 ret.pushKV(
"completed", completed);
2766 "getdescriptoractivity",
2767 "Get spend and receive activity associated with a set of descriptors for a set of blocks. "
2768 "This command pairs well with the `relevant_blocks` output of `scanblocks()`.\n"
2769 "This call may take several minutes. If you encounter timeouts, try specifying no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
2807 }, {.skip_type_check=
true}, },
2811 HelpExampleCli(
"getdescriptoractivity",
"'[\"000000000000000000001347062c12fded7c528943c8ce133987e2e2f5a840ee\"]' '[\"addr(bc1qzl6nsgqzu89a66l50cvwapnkw5shh23zarqkw9)\"]'")
2820 struct CompareByHeightAscending {
2826 std::set<const CBlockIndex*, CompareByHeightAscending> blockindexes_sorted;
2840 blockindexes_sorted.insert(pindex);
2844 std::set<CScript> scripts_to_watch;
2852 scripts_to_watch.insert(
script);
2856 const auto AddSpend = [&](
2868 event.pushKV(
"type",
"spend");
2871 event.pushKV(
"blockhash", index->GetBlockHash().ToString());
2872 event.pushKV(
"height", index->nHeight);
2874 event.pushKV(
"spend_txid", tx->GetHash().ToString());
2875 event.pushKV(
"spend_vin", vin);
2876 event.pushKV(
"prevout_txid", txin.prevout.hash.ToString());
2877 event.pushKV(
"prevout_vout", txin.prevout.n);
2878 event.pushKV(
"prevout_spk", spkUv);
2888 event.pushKV(
"type",
"receive");
2891 event.pushKV(
"blockhash", index->GetBlockHash().ToString());
2892 event.pushKV(
"height", index->nHeight);
2894 event.pushKV(
"txid", tx->GetHash().ToString());
2895 event.pushKV(
"vout", vout);
2896 event.pushKV(
"output_spk", spkUv);
2908 for (
const CBlockIndex* blockindex : blockindexes_sorted) {
2912 for (
size_t i = 0; i < block.vtx.size(); ++i) {
2913 const auto& tx = block.vtx.at(i);
2915 if (!tx->IsCoinBase()) {
2917 const auto& txundo = block_undo.
vtxundo.at(i - 1);
2919 for (
size_t vin_idx = 0; vin_idx < tx->vin.size(); ++vin_idx) {
2920 const auto& coin = txundo.vprevout.at(vin_idx);
2921 const auto& txin = tx->vin.at(vin_idx);
2929 for (
size_t vout_idx = 0; vout_idx < tx->vout.size(); ++vout_idx) {
2930 const auto& vout = tx->vout.at(vout_idx);
2931 if (scripts_to_watch.contains(vout.scriptPubKey)) {
2932 activity.
push_back(AddReceive(vout, blockindex, vout_idx, tx));
2938 bool search_mempool =
true;
2939 if (!request.params[2].isNull()) {
2940 search_mempool = request.params[2].get_bool();
2943 if (search_mempool) {
2950 const auto& tx = e.GetSharedTx();
2952 for (
size_t vin_idx = 0; vin_idx < tx->vin.size(); ++vin_idx) {
2955 const auto& txin = tx->vin.at(vin_idx);
2956 std::optional<Coin> coin = coins_view.
GetCoin(txin.prevout);
2964 if (txin.prevout.n >= prev_tx->vout.size()) {
2965 throw std::runtime_error(
"Invalid output index");
2967 const CTxOut&
out = prev_tx->vout[txin.prevout.n];
2968 scriptPubKey =
out.scriptPubKey;
2973 scriptPubKey =
out.scriptPubKey;
2977 if (scripts_to_watch.contains(scriptPubKey)) {
2980 scriptPubKey, value, tx, vin_idx, txin,
nullptr));
2984 for (
size_t vout_idx = 0; vout_idx < tx->vout.size(); ++vout_idx) {
2985 const auto& vout = tx->vout.at(vout_idx);
2986 if (scripts_to_watch.contains(vout.scriptPubKey)) {
2987 activity.
push_back(AddReceive(vout,
nullptr, vout_idx, tx));
2993 ret.pushKV(
"activity", activity);
3003 "Retrieve a BIP 157 content filter for a particular block.\n",
3015 HelpExampleCli(
"getblockfilter",
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") +
3016 HelpExampleRpc(
"getblockfilter",
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\", \"basic\"")
3021 auto filtertype_name{self.
Arg<std::string_view>(
"filtertype")};
3034 bool block_was_connected;
3045 bool index_ready = index->BlockUntilSyncedToCurrentChain();
3052 std::string errmsg =
"Filter not found.";
3054 if (!block_was_connected) {
3056 errmsg +=
" Block was not connected to active chain.";
3057 }
else if (!index_ready) {
3059 errmsg +=
" Block filters are still in the process of being indexed.";
3062 errmsg +=
" This error is unexpected and indicates index corruption.";
3070 ret.pushKV(
"header", filter_header.
GetHex());
3082 static constexpr const char*
LOCK_NAME{
"dumptxoutset-rollback"};
3108 "Write the serialized UTXO set to a file. This can be used in loadtxoutset afterwards if this snapshot height is supported in the chainparams as well.\n"
3109 "This creates a temporary UTXO database when rolling back, keeping the main chain intact. Should the node experience an unclean shutdown the temporary database may need to be removed from the datadir manually.\n"
3110 "For deep rollbacks, make sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0) as it may take several minutes.",
3113 {
"type",
RPCArg::Type::STR,
RPCArg::Default(
""),
"The type of snapshot to create. Can be \"latest\" to create a snapshot of the current UTXO set or \"rollback\" to temporarily roll back the state of the node to a historical block before creating the snapshot of a historical UTXO set. This parameter can be omitted if a separate \"rollback\" named parameter is specified indicating the height or hash of a specific historical block. If \"rollback\" is specified and separate \"rollback\" named parameter is not specified, this will roll back to the latest valid snapshot block that can currently be loaded with loadtxoutset."},
3117 "Height or hash of the block to roll back to before creating the snapshot. Note: The further this number is from the tip, the longer this process will take. Consider setting a higher -rpcclienttimeout value in this case.",
3119 {
"in_memory",
RPCArg::Type::BOOL,
RPCArg::Default{
false},
"If true, the temporary UTXO-set database used during rollback is kept entirely in memory. This can significantly speed up the process but requires sufficient free RAM (over 10 GB on mainnet)."},
3131 {
RPCResult::Type::NUM,
"nchaintx",
"the number of transactions in the chain up to and including the base block"},
3135 HelpExampleCli(
"-rpcclienttimeout=0 dumptxoutset",
"utxo.dat latest") +
3136 HelpExampleCli(
"-rpcclienttimeout=0 dumptxoutset",
"utxo.dat rollback") +
3137 HelpExampleCli(
"-rpcclienttimeout=0 -named dumptxoutset", R
"(utxo.dat rollback=853456)") +
3138 HelpExampleCli("-rpcclienttimeout=0 -named dumptxoutset", R
"(utxo.dat rollback=853456 in_memory=true)")
3145 const auto snapshot_type{self.
Arg<std::string_view>(
"type")};
3147 if (options.exists(
"rollback")) {
3148 if (!snapshot_type.empty() && snapshot_type !=
"rollback") {
3152 }
else if (snapshot_type ==
"rollback") {
3153 auto snapshot_heights =
node.chainman->GetParams().GetAvailableSnapshotHeights();
3155 auto max_height = std::max_element(snapshot_heights.begin(), snapshot_heights.end());
3157 }
else if (snapshot_type ==
"latest") {
3165 const auto path_info{fs::status(path)};
3168 const fs::path temppath = fs::is_fifo(path_info) ? path : path +
".incomplete";
3170 if (
fs::exists(path_info) && !fs::is_fifo(path_info)) {
3173 path.utf8string() +
" already exists. If you are sure this is what you want, "
3174 "move it out of the way first");
3179 if (afile.IsNull()) {
3182 "Couldn't open file " + temppath.utf8string() +
" for writing.");
3187 if (target_index == tip) {
3193 std::optional<TemporaryPruneLock> temp_prune_lock;
3194 if (
node.chainman->m_blockman.IsPruneMode()) {
3198 if (first_block.nHeight > target_index->nHeight) {
3201 temp_prune_lock.emplace(
node.chainman->m_blockman, target_index->nHeight);
3204 const bool in_memory{options.exists(
"in_memory") ? options[
"in_memory"].get_bool() :
false};
3214 if (!fs::is_fifo(path_info)) {
3215 fs::rename(temppath, path);
3232 fs::create_directories(
m_path);
3236 LogInfo(
"Failed to clean up temporary UTXO database at %s, please remove it manually.",
3247 const fs::path& path,
3248 const fs::path& tmppath,
3249 const bool in_memory)
3256 std::optional<TemporaryUTXODatabase> temp_db_cleaner;
3258 temp_db_cleaner.emplace(temp_db_path);
3260 LogInfo(
"Using in-memory database for UTXO-set rollback (this may require significant RAM).");
3265 .
path = temp_db_path,
3267 .memory_only = in_memory,
3273 std::unique_ptr<CCoinsViewDB> temp_db = std::make_unique<CCoinsViewDB>(
3274 std::move(db_params),
3279 LogInfo(
"Copying current UTXO set to temporary database.");
3282 std::unique_ptr<CCoinsViewCursor> cursor;
3291 size_t coins_count = 0;
3292 while (cursor->Valid()) {
3293 node.rpc_interruption_point();
3297 if (cursor->GetKey(key) && cursor->GetValue(coin)) {
3298 temp_cache.
AddCoin(key, std::move(coin),
false);
3302 if (coins_count % 10'000'000 == 0) {
3303 LogInfo(
"Copying UTXO set: %uM coins copied.", coins_count / 1'000'000);
3307 if (coins_count % 100'000 == 0) {
3315 LogInfo(
"UTXO set copy complete: %u coins total", coins_count);
3318 LogInfo(
"Rolling back from height %d to %d", tip->nHeight, target->
nHeight);
3321 const size_t total_blocks{
static_cast<size_t>(block_index->nHeight - target->
nHeight)};
3323 rollback_cache.
SetBestBlock(block_index->GetBlockHash());
3324 size_t blocks_processed = 0;
3325 int last_progress{0};
3328 while (block_index->nHeight > target->
nHeight) {
3329 node.rpc_interruption_point();
3332 if (!
node.chainman->m_blockman.ReadBlock(block, *block_index)) {
3334 strprintf(
"Failed to read block at height %d", block_index->nHeight));
3337 WITH_LOCK(
::cs_main, res = chainstate.DisconnectBlock(block, block_index, rollback_cache));
3340 strprintf(
"Failed to roll back block at height %d", block_index->nHeight));
3344 int progress{
static_cast<int>(blocks_processed * 100 / total_blocks)};
3345 if (progress >= last_progress + 5) {
3346 LogInfo(
"Rolled back %d%% of blocks.", progress);
3347 last_progress = progress;
3348 rollback_cache.
Flush();
3351 block_index = block_index->pprev;
3355 rollback_cache.
Flush();
3357 LogInfo(
"Rollback complete. Computing UTXO statistics for created txoutset dump.");
3358 std::optional<CCoinsStats> maybe_stats =
GetUTXOStats(*temp_db,
3360 CoinStatsHashType::HASH_SERIALIZED,
3361 node.rpc_interruption_point);
3367 std::unique_ptr<CCoinsViewCursor> pcursor{temp_db->Cursor()};
3369 LogInfo(
"Writing snapshot to disk.");
3377 node.rpc_interruption_point);
3383 const std::function<
void()>& interruption_point)
3385 std::unique_ptr<CCoinsViewCursor> pcursor;
3386 std::optional<CCoinsStats> maybe_stats;
3424 const fs::path& path,
3425 const fs::path& temppath,
3426 const std::function<
void()>& interruption_point)
3439 unsigned int iter{0};
3440 size_t written_coins_count{0};
3441 std::vector<std::pair<uint32_t, Coin>> coins;
3450 auto write_coins_to_file = [&](
AutoFile& afile,
const Txid& last_hash,
const std::vector<std::pair<uint32_t, Coin>>& coins,
size_t& written_coins_count) {
3453 for (
const auto& [n, coin] : coins) {
3456 ++written_coins_count;
3461 last_hash = key.
hash;
3462 while (pcursor->
Valid()) {
3463 if (iter % 5000 == 0) interruption_point();
3466 if (key.
hash != last_hash) {
3467 write_coins_to_file(afile, last_hash, coins, written_coins_count);
3468 last_hash = key.
hash;
3471 coins.emplace_back(key.
n, coin);
3476 if (!coins.empty()) {
3477 write_coins_to_file(afile, last_hash, coins, written_coins_count);
3482 if (afile.
fclose() != 0) {
3483 throw std::ios_base::failure(
3488 result.
pushKV(
"coins_written", written_coins_count);
3491 result.
pushKV(
"path", path.utf8string());
3501 const fs::path& path,
3502 const fs::path& tmppath)
3512 node.rpc_interruption_point);
3519 "Load the serialized UTXO set from a file.\n"
3520 "Once this snapshot is loaded, its contents will be "
3521 "deserialized into a second chainstate data structure, which is then used to sync to "
3522 "the network's tip. "
3523 "Meanwhile, the original chainstate will complete the initial block download process in "
3524 "the background, eventually validating up to the block that the snapshot is based upon.\n\n"
3526 "The result is a usable bitcoind instance that is current with the network tip in a "
3527 "matter of minutes rather than hours. UTXO snapshot are typically obtained from "
3528 "third-party sources (HTTP, torrent, etc.) which is reasonable since their "
3529 "contents are always checked by hash.\n\n"
3531 "You can find more information on this process in the `assumeutxo` design "
3532 "document (<https://github.com/bitcoin/bitcoin/blob/master/doc/design/assumeutxo.md>).",
3537 "path to the snapshot file. If relative, will be prefixed by datadir."},
3559 if (afile.IsNull()) {
3562 "Couldn't open file " + path.utf8string() +
" for reading.");
3568 }
catch (
const std::ios_base::failure& e) {
3573 if (!activation_result) {
3587 result.
pushKV(
"coins_loaded", metadata.m_coins_count);
3588 result.
pushKV(
"tip_hash", snapshot_index.GetBlockHash().ToString());
3589 result.
pushKV(
"base_height", snapshot_index.nHeight);
3603 {
RPCResult::Type::STR_HEX,
"snapshot_blockhash",
true,
"the base block of the snapshot this chainstate is based on, if any"},
3606 {
RPCResult::Type::BOOL,
"validated",
"whether the chainstate is fully validated. True if all blocks in the chainstate were validated, false if the chain is based on a snapshot and the snapshot has not yet been validated."},
3613 "Return information about chainstates.\n",
3635 if (!
cs.m_chain.Tip()) {
3647 data.pushKV(
"coins_db_cache_bytes",
cs.m_coinsdb_cache_size_bytes);
3648 data.pushKV(
"coins_tip_cache_bytes",
cs.m_coinstip_cache_size_bytes);
3649 if (
cs.m_from_snapshot_blockhash) {
3650 data.pushKV(
"snapshot_blockhash",
cs.m_from_snapshot_blockhash->ToString());
3656 obj.
pushKV(
"headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
3659 obj_chainstates.push_back(make_chain_data(*
cs));
3662 obj.
pushKV(
"chainstates", std::move(obj_chainstates));
3703 for (
const auto& c : commands) {
3704 t.appendCommand(c.name, &c);
constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
fs::path AbsPathForConfigVal(const ArgsManager &args, const fs::path &path, bool net_specific=true)
Most paths passed as configuration arguments are treated as relative to the datadir if they are not a...
static std::vector< RPCResult > GetBlockFields(RPCResult tx_result, std::optional< std::string > elision_msg=std::nullopt)
static const auto scan_result_abort
static std::atomic< bool > g_scan_in_progress
static bool SetHasKeys(const std::set< T > &set)
static T CalculateTruncatedMedian(std::vector< T > &scores)
static int ComputeNextBlockAndDepth(const CBlockIndex &tip, const CBlockIndex &blockindex, const CBlockIndex *&next)
CoinStatsHashType ParseHashType(std::string_view hash_type_input)
static RPCMethod getdifficulty()
static CBlockUndo GetUndoChecked(BlockManager &blockman, const CBlockIndex &blockindex)
static std::vector< std::byte > GetRawBlockChecked(BlockManager &blockman, const CBlockIndex &blockindex)
static RPCMethod getblockheader()
std::tuple< std::unique_ptr< CCoinsViewCursor >, CCoinsStats, const CBlockIndex * > PrepareUTXOSnapshot(Chainstate &chainstate, const std::function< void()> &interruption_point={}) EXCLUSIVE_LOCKS_REQUIRED(UniValue WriteUTXOSnapshot(Chainstate &chainstate, CCoinsViewCursor *pcursor, CCoinsStats *maybe_stats, const CBlockIndex *tip, AutoFile &&afile, const fs::path &path, const fs::path &temppath, const std::function< void()> &interruption_point={})
static RPCMethod reconsiderblock()
static RPCMethod getblockfilter()
static RPCMethod pruneblockchain()
static RPCMethod scanblocks()
std::tuple< std::unique_ptr< CCoinsViewCursor >, CCoinsStats, const CBlockIndex * > PrepareUTXOSnapshot(Chainstate &chainstate, const std::function< void()> &interruption_point)
static std::atomic< int > g_scanfilter_progress_height
static const auto output_descriptor_obj
static RPCMethod getbestblockhash()
void CheckBlockDataAvailability(BlockManager &blockman, const CBlockIndex &blockindex, bool check_for_undo)
static std::atomic< bool > g_scanfilter_should_abort_scan
static std::atomic< int > g_scanfilter_progress
RAII object to prevent concurrency issue when scanning blockfilters.
static RPCMethod preciousblock()
static RPCMethod getdescriptoractivity()
static void SoftForkDescPushBack(const CBlockIndex *blockindex, UniValue &softforks, const ChainstateManager &chainman, Consensus::BuriedDeployment dep)
UniValue coinbaseTxToJSON(const CTransaction &coinbase_tx)
Serialize coinbase transaction metadata.
static constexpr size_t PER_UTXO_OVERHEAD
static RPCMethod getblockcount()
double GetDifficulty(const CBlockIndex &blockindex)
Get the difficulty of the net wrt to the given block index.
static const auto scan_objects_arg_desc
static RPCMethod scantxoutset()
static RPCMethod waitforblock()
static bool CheckBlockFilterMatches(BlockManager &blockman, const CBlockIndex &blockindex, const GCSFilter::ElementSet &needles)
void InvalidateBlock(ChainstateManager &chainman, const uint256 block_hash)
static RPCMethod getblockfrompeer()
static RPCMethod invalidateblock()
UniValue CreateUTXOSnapshot(node::NodeContext &node, Chainstate &chainstate, AutoFile &&afile, const fs::path &path, const fs::path &tmppath)
Helper to create UTXO snapshots given a chainstate and a file handle.
static RPCMethod waitfornewblock()
static std::atomic< int > g_scan_progress
RAII object to prevent concurrency issue when scanning the txout set.
static CBlock GetBlockChecked(BlockManager &blockman, const CBlockIndex &blockindex)
std::optional< int > GetPruneHeight(const BlockManager &blockman, const CChain &chain)
Return height of highest block that has been pruned, or std::nullopt if no blocks have been pruned.
UniValue blockToJSON(BlockManager &blockman, const CBlock &block, const CBlockIndex &tip, const CBlockIndex &blockindex, TxVerbosity verbosity, const uint256 pow_limit)
Block description to JSON.
static RPCMethod getchainstates()
static RPCMethod verifychain()
static RPCMethod gettxout()
static RPCMethod syncwithvalidationinterfacequeue()
static RPCMethod getblockhash()
void ReconsiderBlock(ChainstateManager &chainman, uint256 block_hash)
static RPCMethod getchaintips()
UniValue blockheaderToJSON(const CBlockIndex &tip, const CBlockIndex &blockindex, const uint256 pow_limit)
Block header to JSON.
static RPCMethod getchaintxstats()
static const auto scan_result_status_some
static RPCMethod getblockstats()
static std::optional< kernel::CCoinsStats > GetUTXOStats(const CCoinsViewDB &view, node::BlockManager &blockman, kernel::CoinStatsHashType hash_type, const std::function< void()> &interruption_point={}, const CBlockIndex *pindex=nullptr, bool index_requested=true)
Calculate statistics about the unspent transaction output set.
void RegisterBlockchainRPCCommands(CRPCTable &t)
void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector< std::pair< CAmount, int64_t > > &scores, int64_t total_weight)
Used by getblockstats to get feerates at different percentiles by weight
static std::atomic< bool > g_should_abort_scan
const std::vector< RPCResult > RPCHelpForChainstate
static const auto scan_action_arg_desc
static const CBlockIndex * ParseHashOrHeight(const UniValue ¶m, ChainstateManager &chainman)
RPCMethod getblockchaininfo()
static RPCMethod waitforblockheight()
static RPCMethod dumptxoutset()
Serialize the UTXO set to a file for loading elsewhere.
RPCMethod getdeploymentinfo()
static RPCMethod loadtxoutset()
static std::atomic< bool > g_scanfilter_in_progress
UniValue CreateRolledBackUTXOSnapshot(NodeContext &node, Chainstate &chainstate, const CBlockIndex *target, AutoFile &&afile, const fs::path &path, const fs::path &tmppath, bool in_memory)
static RPCMethod getblock()
static const auto scan_result_status_none
static RPCMethod gettxoutsetinfo()
constexpr int NUM_GETBLOCKSTATS_PERCENTILES
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
bool BlockFilterTypeByName(std::string_view name, BlockFilterType &filter_type)
Find a filter type by its human-readable name.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous.
@ BLOCK_HAVE_UNDO
undo data available in rev*.dat
@ BLOCK_HAVE_DATA
full block available in blk*.dat
@ BLOCK_FAILED_VALID
stage after last reached validness failed
constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
#define LIST_CHAIN_NAMES
List of possible chain / network names
#define CHECK_NONFATAL(condition)
Identity function.
fs::path GetDataDirNet() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Get data directory path with appended network identifier.
Non-refcounted RAII wrapper for FILE*.
int64_t size()
Return the size of the file.
Complete block filter struct as defined in BIP 157.
const std::vector< unsigned char > & GetEncodedFilter() const LIFETIMEBOUND
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilter(const CBlockIndex *block_index, BlockFilter &filter_out) const
Get a single filter by block.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
BlockFiltersScanReserver()=default
~BlockFiltersScanReserver()
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
uint64_t m_chain_tx_count
(memory only) Number of transactions in the chain up to and including this block.
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
int64_t GetMedianTimePast() const
unsigned int nTx
Number of transactions in this block.
int32_t nVersion
block header
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Undo information for a CBlock.
std::vector< CTxUndo > vtxundo
An in-memory indexed chain of blocks.
bool Contains(const CBlockIndex &index) const
Efficiently check whether a block is present in this chain.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
const CBlockIndex * FindFork(const CBlockIndex &index) const
Find the last common block between this chain and a block index entry.
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
CBlockIndex * FindEarliestAtLeast(int64_t nTime, int height) const
Find the earliest block with timestamp equal or greater than the given time and height equal or great...
int Height() const
Return the maximal height in the chain.
std::string GetChainTypeString() const
Return the chain type string.
const MessageStartChars & MessageStart() const
const Consensus::Params & GetConsensus() const
uint64_t PruneAfterHeight() const
ChainType GetChainType() const
Return the chain type.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void AddCoin(const COutPoint &outpoint, Coin &&coin, bool possible_overwrite)
Add a coin.
virtual void Flush(bool reallocate_cache=true)
Push the modifications applied to this cache to its base and wipe local state.
void SetBestBlock(const uint256 &block_hash)
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Cursor for iterating over CoinsView state.
virtual bool Valid() const =0
virtual bool GetKey(COutPoint &key) const =0
virtual bool GetValue(Coin &coin) const =0
CCoinsView backed by the coin database (chainstate/)
std::unique_ptr< CCoinsViewCursor > Cursor() const
Get a cursor to iterate over the whole state.
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
CCoinsView that brings transactions from a mempool into view.
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
GetCoin, returning whether it exists and is not spent.
An outpoint - a combination of a transaction hash and an index n into its vout.
Serialized script, used inside transaction inputs and outputs.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxIn > vin
An input of a transaction.
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
CTransactionRef get(const Txid &hash) const
Return a mempool transaction with a given hash.
std::vector< CTxMemPoolEntryRef > entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs)
bool isSpent(const COutPoint &outpoint) const
An output of a transaction.
Undo information for a CTransaction.
RAII wrapper for VerifyDB: Verify consistency of the block and coin databases.
VerifyDBResult VerifyDB(Chainstate &chainstate, const Consensus::Params &consensus_params, CCoinsView &coinsview, int nCheckLevel, int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Chainstate stores and provides an API to update our local knowledge of the current best chain.
CChain m_chain
The current chain of blockheaders we consult and build on.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
bool PreciousBlock(BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(bool InvalidateBlock(BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(void SetBlockFailureFlags(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(voi ResetBlockFailureFlags)(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Mark a block as precious and reorganize.
CCoinsViewDB & CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(
ChainstateManager & m_chainman
The chainstate manager that owns this chainstate.
node::BlockManager & m_blockman
Reference to a BlockManager instance which itself is shared across all Chainstate instances.
void ForceFlushStateToDisk(bool wipe_cache=true)
Flush all changes to disk.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
Chainstate * HistoricalChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Return historical chainstate targeting a specific block, if any.
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
double GetBackgroundVerificationProgress(const CBlockIndex &pindex) const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Guess background verification progress in case assume-utxo was used (as a fraction between 0....
double GuessVerificationProgress(const CBlockIndex *pindex) const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip).
bool IsInitialBlockDownload() const noexcept
Check whether we are doing an initial block download (synchronizing from disk or network)
kernel::Notifications & GetNotifications() const
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Chainstate & ActiveChainstate() const
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
SnapshotCompletionResult MaybeValidateSnapshot(Chainstate &validated_cs, Chainstate &unvalidated_cs) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & CurrentChainstate() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Try to validate an assumeutxo snapshot by using a validated historical chainstate targeted at the sna...
VersionBitsCache m_versionbitscache
Track versionbit status.
const CChainParams & GetParams() const
const Consensus::Params & GetConsensus() const
Chainstate &InitializeChainstate(CTxMemPool *mempool) EXCLUSIVE_LOCKS_REQUIRED(util::Result< CBlockIndex * ActivateSnapshot)(AutoFile &coins_file, const node::SnapshotMetadata &metadata, bool in_memory)
Instantiate a new chainstate.
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
CTxOut out
unspent transaction output
uint32_t nHeight
at which height this containing transaction was included in the active block chain
CoinsViewScanReserver()=default
Double ended buffer combining vector and stream-like interfaces.
std::unordered_set< Element, ByteVectorHash > ElementSet
virtual util::Expected< void, std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
auto MaybeArg(std::string_view key) const
Helper to get an optional request argument.
auto Arg(std::string_view key) const
Helper to get a required or default-valued request argument.
Minimal stream for reading from an existing byte array by std::span.
RAII class that registers a prune lock in its constructor to prevent block data from being pruned,...
BlockManager & m_blockman
static constexpr const char * LOCK_NAME
TemporaryPruneLock(BlockManager &blockman, int height)
RAII class that creates a temporary database directory in its constructor and removes it in its destr...
TemporaryUTXODatabase(const fs::path &path)
void push_back(UniValue val)
const std::string & get_str() const
const std::vector< UniValue > & getValues() const
const UniValue & get_array() const
void reserve(size_t new_cap)
void pushKV(std::string key, UniValue val)
void push_backV(const std::vector< UniValue > &vec)
std::string ToString() const
BIP9Info Info(const CBlockIndex &block_index, const Consensus::Params ¶ms, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
256-bit unsigned big integer.
std::string ToString() const
std::string GetHex() const
uint64_t GetLow64() const
std::string GetHex() const
Hex encoding of the number (with the most significant digits first).
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool ReadBlockUndo(CBlockUndo &blockundo, const CBlockIndex &index) const
CBlockFileInfo *GetBlockFileInfo(size_t n) EXCLUSIVE_LOCKS_REQUIRED(bool WriteBlockUndo(const CBlockUndo &blockundo, BlockValidationState &state, CBlockIndex &block) EXCLUSIVE_LOCKS_REQUIRED(FlatFilePos WriteBlock(const CBlock &block, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(void UpdateBlockInfo(const CBlock &block, unsigned int nHeight, const FlatFilePos &pos) EXCLUSIVE_LOCKS_REQUIRED(bool IsPruneMode() const
Get block file info entry for one block file.
uint64_t GetPruneTarget() const
Attempt to stay below this number of bytes of block files.
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t > > block_part=std::nullopt) const
bool ReadBlock(CBlock &block, const FlatFilePos &pos, const std::optional< uint256 > &expected_hash) const
Functions for disk access for blocks.
Creates block templates, submits solved blocks, and provides tip-waiting helpers for mining code.
std::optional< interfaces::BlockRef > WaitTipChanged(const uint256 ¤t_tip, MillisecondsDouble &timeout, bool &interrupt)
Wait for the tip to differ from current_tip or timeout.
std::optional< interfaces::BlockRef > GetTip()
Locks cs_main.
constexpr const std::byte * begin() const
std::string GetHex() const
static transaction_identifier FromUint256(const uint256 &id)
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
std::unique_ptr< CoinStatsIndex > g_coin_stats_index
The global UTXO set hash object.
static int64_t GetBlockWeight(const CBlock &block)
static int32_t GetTransactionWeight(const CTransaction &tx)
constexpr unsigned int MAX_BLOCK_SERIALIZED_SIZE
The maximum allowed size for a serialized block, in bytes (only for buffer size limits)
constexpr int WITNESS_SCALE_FACTOR
void ScriptToUniv(const CScript &script, UniValue &out, bool include_hex, bool include_address, const SigningProvider *provider)
void TxToUniv(const CTransaction &tx, const uint256 &block_hash, UniValue &entry, bool include_hex, const CTxUndo *txundo, TxVerbosity verbosity, std::function< bool(const CTxOut &)> is_change_func)
UniValue ValueFromAmount(const CAmount amount)
TxVerbosity
Verbose level for block's transaction.
@ SHOW_DETAILS_AND_PREVOUT
The same as previous option with information about prevouts if available.
@ SHOW_TXID
Only TXID for each block's transaction.
@ SHOW_DETAILS
Include TXID, inputs, outputs, and other common block's transaction information.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DestroyDB(const std::string &path_str)
std::string DeploymentName(Consensus::BuriedDeployment dep)
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentEnabled(const Consensus::Params ¶ms, Consensus::BuriedDeployment dep)
Determine if a deployment is enabled (can ever be active)
const std::string CURRENCY_UNIT
static path u8path(std::string_view utf8_str)
static bool exists(const path &p)
static std::string PathToString(const path &path)
Convert path object to a byte string.
#define T(expected, seed, data)
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< std::string > GetScriptFlagNames(script_verify_flags flags)
#define LogDebug(category,...)
BuriedDeployment
A buried deployment is one where the height of the activation has been hardcoded into the client impl...
FILE * fopen(const fs::path &p, const char *mode)
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
static std::optional< CCoinsStats > ComputeUTXOStats(T hash_obj, const CCoinsViewDB &view, node::BlockManager &blockman, const std::function< void()> &interruption_point)
Calculate statistics about the unspent transaction output set.
UniValue GetWarningsForRpc(const Warnings &warnings, bool use_deprecated)
RPC helper function that wraps warnings.GetMessages().
bilingual_str ErrorString(const Result< T > &result)
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
constexpr TransactionSerParams TX_NO_WITNESS
constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
std::vector< RPCResult > TxDoc(const TxDocOptions &opts)
Explain the UniValue "decoded" transaction object, may include extra fields if processed by wallet.
@ WithSummary
first field carries elision_summary as "...", rest skipped
@ Silent
all top-level fields skipped silently (no "..." line)
UniValue JSONRPCError(int code, const std::string &message)
@ RPC_MISC_ERROR
General application defined errors.
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
@ RPC_DATABASE_ERROR
Database error.
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
std::vector< CScript > EvalDescriptorStringOrObject(const UniValue &scanobject, FlatSigningProvider &provider, const bool expand_priv)
Evaluate a descriptor given as a string, or as a {"desc":...,"range":...} object, with default range ...
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
uint256 GetTarget(const CBlockIndex &blockindex, const uint256 pow_limit)
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency.
int ParseVerbosity(const UniValue &arg, int default_verbosity, bool allow_bool)
Parses verbosity from provided UniValue.
uint256 ParseHashV(const UniValue &v, std::string_view name)
Utilities: convert hex-encoded Values (throws error if not hex).
std::vector< RPCResult > ScriptPubKeyDoc()
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
uint64_t GetSerializeSize(const T &t)
bool IsDeprecatedRPCEnabled(const std::string &method)
ChainstateManager & EnsureAnyChainman(const std::any &context)
NodeContext & EnsureAnyNodeContext(const std::any &context)
CTxMemPool & EnsureMemPool(const NodeContext &node)
PeerManager & EnsurePeerman(const NodeContext &node)
ChainstateManager & EnsureChainman(const NodeContext &node)
node::BlockTemplateManager & EnsureBlockTemplateManager(const NodeContext &node)
ArgsManager & EnsureArgsman(const NodeContext &node)
ArgsManager & EnsureAnyArgsman(const std::any &context)
unsigned char * UCharCast(char *c)
Detailed status of an enabled BIP9 deployment.
User-controlled performance and debug options.
Comparison function for sorting the getchaintips heads.
bool operator()(const CBlockIndex *a, const CBlockIndex *b) const
std::vector< uint8_t > signet_challenge
uint256 powLimit
Proof of work parameters.
int DeploymentHeight(BuriedDeployment dep) const
std::array< BIP9Deployment, MAX_VERSION_BITS_DEPLOYMENTS > vDeployments
int64_t nPowTargetSpacing
User-controlled performance and debug options.
Application-specific storage settings.
fs::path path
Location in the filesystem where leveldb data will be stored.
@ RANGE
Special type that is a NUM or [NUM,NUM].
@ STR_HEX
Special type that is a STR with only hex chars.
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
std::string DefaultHint
Hint for default value.
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
UniValue Default
Default constant value.
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
@ NUM_TIME
Special numeric to denote unix epoch time.
@ ARR_FIXED
Special array that has a fixed number of entries.
@ OBJ_DYN
Special dictionary with keys that are not literals.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
HelpElision print_elision
Hash/height pair to help track and identify blocks.
arith_uint256 total_prevout_spent_amount
Total cumulative amount of prevouts spent up to and including this block.
std::optional< CAmount > total_amount
The total amount, or nullopt if an overflow occurred calculating it.
CAmount total_unspendables_scripts
Total cumulative amount of outputs sent to unspendable scripts (OP_RETURN for example) up to and incl...
uint64_t coins_count
The number of coins contained.
arith_uint256 total_coinbase_amount
Total cumulative amount of coinbase outputs up to and including this block.
uint64_t nTransactionOutputs
bool index_used
Signals if the coinstatsindex was used to retrieve the statistics.
CAmount total_unspendables_bip30
The two unspendable coinbase outputs total amount caused by BIP30.
CAmount total_unspendables_genesis_block
The unspendable coinbase amount from the genesis block.
arith_uint256 total_new_outputs_ex_coinbase_amount
Total cumulative amount of outputs created up to and including this block.
CAmount total_unspendables_unclaimed_rewards
Total cumulative amount of coins lost due to unclaimed miner rewards up to and including this block.
NodeContext struct containing references to chain state and connection state.
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
std::string SysErrorString(int err)
Return system error string from errno value.
FuzzedDataProvider provider
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOG_TIME_SECONDS(end_msg)
consteval auto _(util::TranslatedLiteral str)
constexpr uint32_t MEMPOOL_HEIGHT
Fake height value used in Coin to signify they are only in the memory pool (since 0....
const UniValue NullUniValue
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
script_verify_flags GetBlockScriptFlags(const CBlockIndex &block_index, const ChainstateManager &chainman)
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
const std::vector< std::string > CHECKLEVEL_DOC
Documentation for argument 'checklevel'.
void PruneBlockFilesManual(Chainstate &active_chainstate, int nManualPruneHeight)
Prune block files up to a given height.
bool IsBIP30Repeat(const CBlockIndex &block_index)
Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30)
constexpr signed int DEFAULT_CHECKBLOCKS
constexpr int DEFAULT_CHECKLEVEL
@ VALIDATED
Every block in the chain has been validated.
constexpr unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...