Bitcoin Core  29.1.0
P2P Digital Currency
blockchain.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <rpc/blockchain.h>
7 
8 #include <blockfilter.h>
9 #include <chain.h>
10 #include <chainparams.h>
11 #include <chainparamsbase.h>
12 #include <clientversion.h>
13 #include <coins.h>
14 #include <common/args.h>
15 #include <consensus/amount.h>
16 #include <consensus/params.h>
17 #include <consensus/validation.h>
18 #include <core_io.h>
19 #include <deploymentinfo.h>
20 #include <deploymentstatus.h>
21 #include <flatfile.h>
22 #include <hash.h>
23 #include <index/blockfilterindex.h>
24 #include <index/coinstatsindex.h>
25 #include <interfaces/mining.h>
26 #include <kernel/coinstats.h>
27 #include <logging/timer.h>
28 #include <net.h>
29 #include <net_processing.h>
30 #include <node/blockstorage.h>
31 #include <node/context.h>
32 #include <node/transaction.h>
33 #include <node/utxo_snapshot.h>
34 #include <node/warnings.h>
35 #include <primitives/transaction.h>
36 #include <rpc/server.h>
37 #include <rpc/server_util.h>
38 #include <rpc/util.h>
39 #include <script/descriptor.h>
40 #include <serialize.h>
41 #include <streams.h>
42 #include <sync.h>
43 #include <txdb.h>
44 #include <txmempool.h>
45 #include <undo.h>
46 #include <univalue.h>
47 #include <util/check.h>
48 #include <util/fs.h>
49 #include <util/strencodings.h>
50 #include <util/translation.h>
51 #include <validation.h>
52 #include <validationinterface.h>
53 #include <versionbits.h>
54 
55 #include <stdint.h>
56 
57 #include <condition_variable>
58 #include <iterator>
59 #include <memory>
60 #include <mutex>
61 #include <optional>
62 #include <vector>
63 
66 
67 using interfaces::Mining;
68 using node::BlockManager;
69 using node::NodeContext;
72 
73 std::tuple<std::unique_ptr<CCoinsViewCursor>, CCoinsStats, const CBlockIndex*>
75  Chainstate& chainstate,
76  const std::function<void()>& interruption_point = {})
78 
80  Chainstate& chainstate,
81  CCoinsViewCursor* pcursor,
82  CCoinsStats* maybe_stats,
83  const CBlockIndex* tip,
84  AutoFile& afile,
85  const fs::path& path,
86  const fs::path& temppath,
87  const std::function<void()>& interruption_point = {});
88 
89 /* Calculate the difficulty for a given block index.
90  */
91 double GetDifficulty(const CBlockIndex& blockindex)
92 {
93  int nShift = (blockindex.nBits >> 24) & 0xff;
94  double dDiff =
95  (double)0x0000ffff / (double)(blockindex.nBits & 0x00ffffff);
96 
97  while (nShift < 29)
98  {
99  dDiff *= 256.0;
100  nShift++;
101  }
102  while (nShift > 29)
103  {
104  dDiff /= 256.0;
105  nShift--;
106  }
107 
108  return dDiff;
109 }
110 
111 static int ComputeNextBlockAndDepth(const CBlockIndex& tip, const CBlockIndex& blockindex, const CBlockIndex*& next)
112 {
113  next = tip.GetAncestor(blockindex.nHeight + 1);
114  if (next && next->pprev == &blockindex) {
115  return tip.nHeight - blockindex.nHeight + 1;
116  }
117  next = nullptr;
118  return &blockindex == &tip ? 1 : -1;
119 }
120 
121 static const CBlockIndex* ParseHashOrHeight(const UniValue& param, ChainstateManager& chainman)
122 {
123  LOCK(::cs_main);
124  CChain& active_chain = chainman.ActiveChain();
125 
126  if (param.isNum()) {
127  const int height{param.getInt<int>()};
128  if (height < 0) {
129  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d is negative", height));
130  }
131  const int current_tip{active_chain.Height()};
132  if (height > current_tip) {
133  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d after current tip %d", height, current_tip));
134  }
135 
136  return active_chain[height];
137  } else {
138  const uint256 hash{ParseHashV(param, "hash_or_height")};
139  const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
140 
141  if (!pindex) {
142  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
143  }
144 
145  return pindex;
146  }
147 }
148 
149 UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex, const uint256 pow_limit)
150 {
151  // Serialize passed information without accessing chain state of the active chain!
152  AssertLockNotHeld(cs_main); // For performance reasons
153 
155  result.pushKV("hash", blockindex.GetBlockHash().GetHex());
156  const CBlockIndex* pnext;
157  int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
158  result.pushKV("confirmations", confirmations);
159  result.pushKV("height", blockindex.nHeight);
160  result.pushKV("version", blockindex.nVersion);
161  result.pushKV("versionHex", strprintf("%08x", blockindex.nVersion));
162  result.pushKV("merkleroot", blockindex.hashMerkleRoot.GetHex());
163  result.pushKV("time", blockindex.nTime);
164  result.pushKV("mediantime", blockindex.GetMedianTimePast());
165  result.pushKV("nonce", blockindex.nNonce);
166  result.pushKV("bits", strprintf("%08x", blockindex.nBits));
167  result.pushKV("target", GetTarget(tip, pow_limit).GetHex());
168  result.pushKV("difficulty", GetDifficulty(blockindex));
169  result.pushKV("chainwork", blockindex.nChainWork.GetHex());
170  result.pushKV("nTx", blockindex.nTx);
171 
172  if (blockindex.pprev)
173  result.pushKV("previousblockhash", blockindex.pprev->GetBlockHash().GetHex());
174  if (pnext)
175  result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
176  return result;
177 }
178 
179 UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity, const uint256 pow_limit)
180 {
181  UniValue result = blockheaderToJSON(tip, blockindex, pow_limit);
182 
183  result.pushKV("strippedsize", (int)::GetSerializeSize(TX_NO_WITNESS(block)));
184  result.pushKV("size", (int)::GetSerializeSize(TX_WITH_WITNESS(block)));
185  result.pushKV("weight", (int)::GetBlockWeight(block));
187 
188  switch (verbosity) {
190  for (const CTransactionRef& tx : block.vtx) {
191  txs.push_back(tx->GetHash().GetHex());
192  }
193  break;
194 
197  CBlockUndo blockUndo;
198  const bool is_not_pruned{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex))};
199  bool have_undo{is_not_pruned && WITH_LOCK(::cs_main, return blockindex.nStatus & BLOCK_HAVE_UNDO)};
200  if (have_undo && !blockman.ReadBlockUndo(blockUndo, blockindex)) {
201  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.");
202  }
203  for (size_t i = 0; i < block.vtx.size(); ++i) {
204  const CTransactionRef& tx = block.vtx.at(i);
205  // coinbase transaction (i.e. i == 0) doesn't have undo data
206  const CTxUndo* txundo = (have_undo && i > 0) ? &blockUndo.vtxundo.at(i - 1) : nullptr;
207  UniValue objTx(UniValue::VOBJ);
208  TxToUniv(*tx, /*block_hash=*/uint256(), /*entry=*/objTx, /*include_hex=*/true, txundo, verbosity);
209  txs.push_back(std::move(objTx));
210  }
211  break;
212  }
213 
214  result.pushKV("tx", std::move(txs));
215 
216  return result;
217 }
218 
220 {
221  return RPCHelpMan{"getblockcount",
222  "\nReturns the height of the most-work fully-validated chain.\n"
223  "The genesis block has height 0.\n",
224  {},
225  RPCResult{
226  RPCResult::Type::NUM, "", "The current block count"},
227  RPCExamples{
228  HelpExampleCli("getblockcount", "")
229  + HelpExampleRpc("getblockcount", "")
230  },
231  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
232 {
233  ChainstateManager& chainman = EnsureAnyChainman(request.context);
234  LOCK(cs_main);
235  return chainman.ActiveChain().Height();
236 },
237  };
238 }
239 
241 {
242  return RPCHelpMan{"getbestblockhash",
243  "\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n",
244  {},
245  RPCResult{
246  RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"},
247  RPCExamples{
248  HelpExampleCli("getbestblockhash", "")
249  + HelpExampleRpc("getbestblockhash", "")
250  },
251  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
252 {
253  ChainstateManager& chainman = EnsureAnyChainman(request.context);
254  LOCK(cs_main);
255  return chainman.ActiveChain().Tip()->GetBlockHash().GetHex();
256 },
257  };
258 }
259 
261 {
262  return RPCHelpMan{"waitfornewblock",
263  "\nWaits for any new block and returns useful info about it.\n"
264  "\nReturns the current block on timeout or exit.\n"
265  "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
266  {
267  {"timeout", RPCArg::Type::NUM, RPCArg::Default{0}, "Time in milliseconds to wait for a response. 0 indicates no timeout."},
268  },
269  RPCResult{
270  RPCResult::Type::OBJ, "", "",
271  {
272  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
273  {RPCResult::Type::NUM, "height", "Block height"},
274  }},
275  RPCExamples{
276  HelpExampleCli("waitfornewblock", "1000")
277  + HelpExampleRpc("waitfornewblock", "1000")
278  },
279  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
280 {
281  int timeout = 0;
282  if (!request.params[0].isNull())
283  timeout = request.params[0].getInt<int>();
284  if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
285 
286  NodeContext& node = EnsureAnyNodeContext(request.context);
287  Mining& miner = EnsureMining(node);
288 
289  auto block{CHECK_NONFATAL(miner.getTip()).value()};
290  if (IsRPCRunning()) {
291  block = timeout ? miner.waitTipChanged(block.hash, std::chrono::milliseconds(timeout)) : miner.waitTipChanged(block.hash);
292  }
293 
295  ret.pushKV("hash", block.hash.GetHex());
296  ret.pushKV("height", block.height);
297  return ret;
298 },
299  };
300 }
301 
303 {
304  return RPCHelpMan{"waitforblock",
305  "\nWaits for a specific new block and returns useful info about it.\n"
306  "\nReturns the current block on timeout or exit.\n"
307  "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
308  {
309  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Block hash to wait for."},
310  {"timeout", RPCArg::Type::NUM, RPCArg::Default{0}, "Time in milliseconds to wait for a response. 0 indicates no timeout."},
311  },
312  RPCResult{
313  RPCResult::Type::OBJ, "", "",
314  {
315  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
316  {RPCResult::Type::NUM, "height", "Block height"},
317  }},
318  RPCExamples{
319  HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000")
320  + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
321  },
322  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
323 {
324  int timeout = 0;
325 
326  uint256 hash(ParseHashV(request.params[0], "blockhash"));
327 
328  if (!request.params[1].isNull())
329  timeout = request.params[1].getInt<int>();
330  if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
331 
332  NodeContext& node = EnsureAnyNodeContext(request.context);
333  Mining& miner = EnsureMining(node);
334 
335  auto block{CHECK_NONFATAL(miner.getTip()).value()};
336  const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
337  while (IsRPCRunning() && block.hash != hash) {
338  if (timeout) {
339  auto now{std::chrono::steady_clock::now()};
340  if (now >= deadline) break;
341  const MillisecondsDouble remaining{deadline - now};
342  block = miner.waitTipChanged(block.hash, remaining);
343  } else {
344  block = miner.waitTipChanged(block.hash);
345  }
346  }
347 
349  ret.pushKV("hash", block.hash.GetHex());
350  ret.pushKV("height", block.height);
351  return ret;
352 },
353  };
354 }
355 
357 {
358  return RPCHelpMan{"waitforblockheight",
359  "\nWaits for (at least) block height and returns the height and hash\n"
360  "of the current tip.\n"
361  "\nReturns the current block on timeout or exit.\n"
362  "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
363  {
364  {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "Block height to wait for."},
365  {"timeout", RPCArg::Type::NUM, RPCArg::Default{0}, "Time in milliseconds to wait for a response. 0 indicates no timeout."},
366  },
367  RPCResult{
368  RPCResult::Type::OBJ, "", "",
369  {
370  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
371  {RPCResult::Type::NUM, "height", "Block height"},
372  }},
373  RPCExamples{
374  HelpExampleCli("waitforblockheight", "100 1000")
375  + HelpExampleRpc("waitforblockheight", "100, 1000")
376  },
377  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
378 {
379  int timeout = 0;
380 
381  int height = request.params[0].getInt<int>();
382 
383  if (!request.params[1].isNull())
384  timeout = request.params[1].getInt<int>();
385  if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
386 
387  NodeContext& node = EnsureAnyNodeContext(request.context);
388  Mining& miner = EnsureMining(node);
389 
390  auto block{CHECK_NONFATAL(miner.getTip()).value()};
391  const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
392 
393  while (IsRPCRunning() && block.height < height) {
394  if (timeout) {
395  auto now{std::chrono::steady_clock::now()};
396  if (now >= deadline) break;
397  const MillisecondsDouble remaining{deadline - now};
398  block = miner.waitTipChanged(block.hash, remaining);
399  } else {
400  block = miner.waitTipChanged(block.hash);
401  }
402  }
403 
405  ret.pushKV("hash", block.hash.GetHex());
406  ret.pushKV("height", block.height);
407  return ret;
408 },
409  };
410 }
411 
413 {
414  return RPCHelpMan{"syncwithvalidationinterfacequeue",
415  "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n",
416  {},
418  RPCExamples{
419  HelpExampleCli("syncwithvalidationinterfacequeue","")
420  + HelpExampleRpc("syncwithvalidationinterfacequeue","")
421  },
422  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
423 {
424  NodeContext& node = EnsureAnyNodeContext(request.context);
425  CHECK_NONFATAL(node.validation_signals)->SyncWithValidationInterfaceQueue();
426  return UniValue::VNULL;
427 },
428  };
429 }
430 
432 {
433  return RPCHelpMan{"getdifficulty",
434  "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
435  {},
436  RPCResult{
437  RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."},
438  RPCExamples{
439  HelpExampleCli("getdifficulty", "")
440  + HelpExampleRpc("getdifficulty", "")
441  },
442  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
443 {
444  ChainstateManager& chainman = EnsureAnyChainman(request.context);
445  LOCK(cs_main);
446  return GetDifficulty(*CHECK_NONFATAL(chainman.ActiveChain().Tip()));
447 },
448  };
449 }
450 
452 {
453  return RPCHelpMan{
454  "getblockfrompeer",
455  "Attempt to fetch block from a given peer.\n\n"
456  "We must have the header for this block, e.g. using submitheader.\n"
457  "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"
458  "Subsequent calls for the same block may cause the response from the previous peer to be ignored.\n"
459  "Peers generally ignore requests for a stale block that they never fully verified, or one that is more than a month old.\n"
460  "When a peer does not respond with a block, we will disconnect.\n"
461  "Note: The block could be re-pruned as soon as it is received.\n\n"
462  "Returns an empty JSON object if the request was successfully scheduled.",
463  {
464  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash to try to fetch"},
465  {"peer_id", RPCArg::Type::NUM, RPCArg::Optional::NO, "The peer to fetch it from (see getpeerinfo for peer IDs)"},
466  },
467  RPCResult{RPCResult::Type::OBJ, "", /*optional=*/false, "", {}},
468  RPCExamples{
469  HelpExampleCli("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0")
470  + HelpExampleRpc("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0")
471  },
472  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
473 {
474  const NodeContext& node = EnsureAnyNodeContext(request.context);
476  PeerManager& peerman = EnsurePeerman(node);
477 
478  const uint256& block_hash{ParseHashV(request.params[0], "blockhash")};
479  const NodeId peer_id{request.params[1].getInt<int64_t>()};
480 
481  const CBlockIndex* const index = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(block_hash););
482 
483  if (!index) {
484  throw JSONRPCError(RPC_MISC_ERROR, "Block header missing");
485  }
486 
487  // Fetching blocks before the node has syncing past their height can prevent block files from
488  // being pruned, so we avoid it if the node is in prune mode.
489  if (chainman.m_blockman.IsPruneMode() && index->nHeight > WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip()->nHeight)) {
490  throw JSONRPCError(RPC_MISC_ERROR, "In prune mode, only blocks that the node has already synced previously can be fetched from a peer");
491  }
492 
493  const bool block_has_data = WITH_LOCK(::cs_main, return index->nStatus & BLOCK_HAVE_DATA);
494  if (block_has_data) {
495  throw JSONRPCError(RPC_MISC_ERROR, "Block already downloaded");
496  }
497 
498  if (const auto err{peerman.FetchBlock(peer_id, *index)}) {
499  throw JSONRPCError(RPC_MISC_ERROR, err.value());
500  }
501  return UniValue::VOBJ;
502 },
503  };
504 }
505 
507 {
508  return RPCHelpMan{"getblockhash",
509  "\nReturns hash of block in best-block-chain at height provided.\n",
510  {
511  {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"},
512  },
513  RPCResult{
514  RPCResult::Type::STR_HEX, "", "The block hash"},
515  RPCExamples{
516  HelpExampleCli("getblockhash", "1000")
517  + HelpExampleRpc("getblockhash", "1000")
518  },
519  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
520 {
521  ChainstateManager& chainman = EnsureAnyChainman(request.context);
522  LOCK(cs_main);
523  const CChain& active_chain = chainman.ActiveChain();
524 
525  int nHeight = request.params[0].getInt<int>();
526  if (nHeight < 0 || nHeight > active_chain.Height())
527  throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
528 
529  const CBlockIndex* pblockindex = active_chain[nHeight];
530  return pblockindex->GetBlockHash().GetHex();
531 },
532  };
533 }
534 
536 {
537  return RPCHelpMan{"getblockheader",
538  "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
539  "If verbose is true, returns an Object with information about blockheader <hash>.\n",
540  {
541  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
542  {"verbose", RPCArg::Type::BOOL, RPCArg::Default{true}, "true for a json object, false for the hex-encoded data"},
543  },
544  {
545  RPCResult{"for verbose = true",
546  RPCResult::Type::OBJ, "", "",
547  {
548  {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"},
549  {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"},
550  {RPCResult::Type::NUM, "height", "The block height or index"},
551  {RPCResult::Type::NUM, "version", "The block version"},
552  {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"},
553  {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
554  {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME},
555  {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
556  {RPCResult::Type::NUM, "nonce", "The nonce"},
557  {RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},
558  {RPCResult::Type::STR_HEX, "target", "The difficulty target"},
559  {RPCResult::Type::NUM, "difficulty", "The difficulty"},
560  {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain"},
561  {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
562  {RPCResult::Type::STR_HEX, "previousblockhash", /*optional=*/true, "The hash of the previous block (if available)"},
563  {RPCResult::Type::STR_HEX, "nextblockhash", /*optional=*/true, "The hash of the next block (if available)"},
564  }},
565  RPCResult{"for verbose=false",
566  RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"},
567  },
568  RPCExamples{
569  HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
570  + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
571  },
572  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
573 {
574  uint256 hash(ParseHashV(request.params[0], "hash"));
575 
576  bool fVerbose = true;
577  if (!request.params[1].isNull())
578  fVerbose = request.params[1].get_bool();
579 
580  const CBlockIndex* pblockindex;
581  const CBlockIndex* tip;
582  ChainstateManager& chainman = EnsureAnyChainman(request.context);
583  {
584  LOCK(cs_main);
585  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
586  tip = chainman.ActiveChain().Tip();
587  }
588 
589  if (!pblockindex) {
590  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
591  }
592 
593  if (!fVerbose)
594  {
595  DataStream ssBlock{};
596  ssBlock << pblockindex->GetBlockHeader();
597  std::string strHex = HexStr(ssBlock);
598  return strHex;
599  }
600 
601  return blockheaderToJSON(*tip, *pblockindex, chainman.GetConsensus().powLimit);
602 },
603  };
604 }
605 
606 void CheckBlockDataAvailability(BlockManager& blockman, const CBlockIndex& blockindex, bool check_for_undo)
607 {
609  uint32_t flag = check_for_undo ? BLOCK_HAVE_UNDO : BLOCK_HAVE_DATA;
610  if (!(blockindex.nStatus & flag)) {
611  if (blockman.IsBlockPruned(blockindex)) {
612  throw JSONRPCError(RPC_MISC_ERROR, strprintf("%s not available (pruned data)", check_for_undo ? "Undo data" : "Block"));
613  }
614  if (check_for_undo) {
615  throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available");
616  }
617  throw JSONRPCError(RPC_MISC_ERROR, "Block not available (not fully downloaded)");
618  }
619 }
620 
621 static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex& blockindex)
622 {
623  CBlock block;
624  {
625  LOCK(cs_main);
626  CheckBlockDataAvailability(blockman, blockindex, /*check_for_undo=*/false);
627  }
628 
629  if (!blockman.ReadBlock(block, blockindex)) {
630  // Block not found on disk. This shouldn't normally happen unless the block was
631  // pruned right after we released the lock above.
632  throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
633  }
634 
635  return block;
636 }
637 
638 static std::vector<uint8_t> GetRawBlockChecked(BlockManager& blockman, const CBlockIndex& blockindex)
639 {
640  std::vector<uint8_t> data{};
641  FlatFilePos pos{};
642  {
643  LOCK(cs_main);
644  CheckBlockDataAvailability(blockman, blockindex, /*check_for_undo=*/false);
645  pos = blockindex.GetBlockPos();
646  }
647 
648  if (!blockman.ReadRawBlock(data, pos)) {
649  // Block not found on disk. This shouldn't normally happen unless the block was
650  // pruned right after we released the lock above.
651  throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
652  }
653 
654  return data;
655 }
656 
657 static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex& blockindex)
658 {
659  CBlockUndo blockUndo;
660 
661  // The Genesis block does not have undo data
662  if (blockindex.nHeight == 0) return blockUndo;
663 
664  {
665  LOCK(cs_main);
666  CheckBlockDataAvailability(blockman, blockindex, /*check_for_undo=*/true);
667  }
668 
669  if (!blockman.ReadBlockUndo(blockUndo, blockindex)) {
670  throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk");
671  }
672 
673  return blockUndo;
674 }
675 
677  RPCResult::Type::ARR, "vin", "",
678  {
679  {RPCResult::Type::OBJ, "", "",
680  {
681  {RPCResult::Type::ELISION, "", "The same output as verbosity = 2"},
682  {RPCResult::Type::OBJ, "prevout", "(Only if undo information is available)",
683  {
684  {RPCResult::Type::BOOL, "generated", "Coinbase or not"},
685  {RPCResult::Type::NUM, "height", "The height of the prevout"},
686  {RPCResult::Type::STR_AMOUNT, "value", "The value in " + CURRENCY_UNIT},
687  {RPCResult::Type::OBJ, "scriptPubKey", "",
688  {
689  {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
690  {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
691  {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
692  {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
693  {RPCResult::Type::STR, "type", "The type (one of: " + GetAllOutputTypes() + ")"},
694  }},
695  }},
696  }},
697  }
698 };
699 
701 {
702  return RPCHelpMan{"getblock",
703  "\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
704  "If verbosity is 1, returns an Object with information about block <hash>.\n"
705  "If verbosity is 2, returns an Object with information about block <hash> and information about each transaction.\n"
706  "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",
707  {
708  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
709  {"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",
710  RPCArgOptions{.skip_type_check = true}},
711  },
712  {
713  RPCResult{"for verbosity = 0",
714  RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"},
715  RPCResult{"for verbosity = 1",
716  RPCResult::Type::OBJ, "", "",
717  {
718  {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"},
719  {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"},
720  {RPCResult::Type::NUM, "size", "The block size"},
721  {RPCResult::Type::NUM, "strippedsize", "The block size excluding witness data"},
722  {RPCResult::Type::NUM, "weight", "The block weight as defined in BIP 141"},
723  {RPCResult::Type::NUM, "height", "The block height or index"},
724  {RPCResult::Type::NUM, "version", "The block version"},
725  {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"},
726  {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
727  {RPCResult::Type::ARR, "tx", "The transaction ids",
728  {{RPCResult::Type::STR_HEX, "", "The transaction id"}}},
729  {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME},
730  {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
731  {RPCResult::Type::NUM, "nonce", "The nonce"},
732  {RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},
733  {RPCResult::Type::STR_HEX, "target", "The difficulty target"},
734  {RPCResult::Type::NUM, "difficulty", "The difficulty"},
735  {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the chain up to this block (in hex)"},
736  {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
737  {RPCResult::Type::STR_HEX, "previousblockhash", /*optional=*/true, "The hash of the previous block (if available)"},
738  {RPCResult::Type::STR_HEX, "nextblockhash", /*optional=*/true, "The hash of the next block (if available)"},
739  }},
740  RPCResult{"for verbosity = 2",
741  RPCResult::Type::OBJ, "", "",
742  {
743  {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"},
744  {RPCResult::Type::ARR, "tx", "",
745  {
746  {RPCResult::Type::OBJ, "", "",
747  {
748  {RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result"},
749  {RPCResult::Type::NUM, "fee", "The transaction fee in " + CURRENCY_UNIT + ", omitted if block undo data is not available"},
750  }},
751  }},
752  }},
753  RPCResult{"for verbosity = 3",
754  RPCResult::Type::OBJ, "", "",
755  {
756  {RPCResult::Type::ELISION, "", "Same output as verbosity = 2"},
757  {RPCResult::Type::ARR, "tx", "",
758  {
759  {RPCResult::Type::OBJ, "", "",
760  {
761  getblock_vin,
762  }},
763  }},
764  }},
765  },
766  RPCExamples{
767  HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
768  + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
769  },
770  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
771 {
772  uint256 hash(ParseHashV(request.params[0], "blockhash"));
773 
774  int verbosity{ParseVerbosity(request.params[1], /*default_verbosity=*/1, /*allow_bool=*/true)};
775 
776  const CBlockIndex* pblockindex;
777  const CBlockIndex* tip;
778  ChainstateManager& chainman = EnsureAnyChainman(request.context);
779  {
780  LOCK(cs_main);
781  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
782  tip = chainman.ActiveChain().Tip();
783 
784  if (!pblockindex) {
785  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
786  }
787  }
788 
789  const std::vector<uint8_t> block_data{GetRawBlockChecked(chainman.m_blockman, *pblockindex)};
790 
791  if (verbosity <= 0) {
792  return HexStr(block_data);
793  }
794 
795  DataStream block_stream{block_data};
796  CBlock block{};
797  block_stream >> TX_WITH_WITNESS(block);
798 
799  TxVerbosity tx_verbosity;
800  if (verbosity == 1) {
801  tx_verbosity = TxVerbosity::SHOW_TXID;
802  } else if (verbosity == 2) {
803  tx_verbosity = TxVerbosity::SHOW_DETAILS;
804  } else {
806  }
807 
808  return blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity, chainman.GetConsensus().powLimit);
809 },
810  };
811 }
812 
814 std::optional<int> GetPruneHeight(const BlockManager& blockman, const CChain& chain) {
816 
817  // Search for the last block missing block data or undo data. Don't let the
818  // search consider the genesis block, because the genesis block does not
819  // have undo data, but should not be considered pruned.
820  const CBlockIndex* first_block{chain[1]};
821  const CBlockIndex* chain_tip{chain.Tip()};
822 
823  // If there are no blocks after the genesis block, or no blocks at all, nothing is pruned.
824  if (!first_block || !chain_tip) return std::nullopt;
825 
826  // If the chain tip is pruned, everything is pruned.
827  if (!((chain_tip->nStatus & BLOCK_HAVE_MASK) == BLOCK_HAVE_MASK)) return chain_tip->nHeight;
828 
829  const auto& first_unpruned{*CHECK_NONFATAL(blockman.GetFirstBlock(*chain_tip, /*status_mask=*/BLOCK_HAVE_MASK, first_block))};
830  if (&first_unpruned == first_block) {
831  // All blocks between first_block and chain_tip have data, so nothing is pruned.
832  return std::nullopt;
833  }
834 
835  // Block before the first unpruned block is the last pruned block.
836  return CHECK_NONFATAL(first_unpruned.pprev)->nHeight;
837 }
838 
840 {
841  return RPCHelpMan{"pruneblockchain",
842  "Attempts to delete block and undo data up to a specified height or timestamp, if eligible for pruning.\n"
843  "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",
844  {
845  {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or to a " + UNIX_EPOCH_TIME + "\n"
846  " to prune blocks whose block time is at least 2 hours older than the provided timestamp."},
847  },
848  RPCResult{
849  RPCResult::Type::NUM, "", "Height of the last block pruned"},
850  RPCExamples{
851  HelpExampleCli("pruneblockchain", "1000")
852  + HelpExampleRpc("pruneblockchain", "1000")
853  },
854  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
855 {
856  ChainstateManager& chainman = EnsureAnyChainman(request.context);
857  if (!chainman.m_blockman.IsPruneMode()) {
858  throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode.");
859  }
860 
861  LOCK(cs_main);
862  Chainstate& active_chainstate = chainman.ActiveChainstate();
863  CChain& active_chain = active_chainstate.m_chain;
864 
865  int heightParam = request.params[0].getInt<int>();
866  if (heightParam < 0) {
867  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative block height.");
868  }
869 
870  // Height value more than a billion is too high to be a block height, and
871  // too low to be a block time (corresponds to timestamp from Sep 2001).
872  if (heightParam > 1000000000) {
873  // Add a 2 hour buffer to include blocks which might have had old timestamps
874  const CBlockIndex* pindex = active_chain.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0);
875  if (!pindex) {
876  throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp.");
877  }
878  heightParam = pindex->nHeight;
879  }
880 
881  unsigned int height = (unsigned int) heightParam;
882  unsigned int chainHeight = (unsigned int) active_chain.Height();
883  if (chainHeight < chainman.GetParams().PruneAfterHeight()) {
884  throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning.");
885  } else if (height > chainHeight) {
886  throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height.");
887  } else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) {
888  LogDebug(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks.\n");
889  height = chainHeight - MIN_BLOCKS_TO_KEEP;
890  }
891 
892  PruneBlockFilesManual(active_chainstate, height);
893  return GetPruneHeight(chainman.m_blockman, active_chain).value_or(-1);
894 },
895  };
896 }
897 
898 CoinStatsHashType ParseHashType(const std::string& hash_type_input)
899 {
900  if (hash_type_input == "hash_serialized_3") {
901  return CoinStatsHashType::HASH_SERIALIZED;
902  } else if (hash_type_input == "muhash") {
903  return CoinStatsHashType::MUHASH;
904  } else if (hash_type_input == "none") {
906  } else {
907  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("'%s' is not a valid hash_type", hash_type_input));
908  }
909 }
910 
916 static std::optional<kernel::CCoinsStats> GetUTXOStats(CCoinsView* view, node::BlockManager& blockman,
917  kernel::CoinStatsHashType hash_type,
918  const std::function<void()>& interruption_point = {},
919  const CBlockIndex* pindex = nullptr,
920  bool index_requested = true)
921 {
922  // Use CoinStatsIndex if it is requested and available and a hash_type of Muhash or None was requested
923  if ((hash_type == kernel::CoinStatsHashType::MUHASH || hash_type == kernel::CoinStatsHashType::NONE) && g_coin_stats_index && index_requested) {
924  if (pindex) {
925  return g_coin_stats_index->LookUpStats(*pindex);
926  } else {
927  CBlockIndex& block_index = *CHECK_NONFATAL(WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock())));
928  return g_coin_stats_index->LookUpStats(block_index);
929  }
930  }
931 
932  // If the coinstats index isn't requested or is otherwise not usable, the
933  // pindex should either be null or equal to the view's best block. This is
934  // because without the coinstats index we can only get coinstats about the
935  // best block.
936  CHECK_NONFATAL(!pindex || pindex->GetBlockHash() == view->GetBestBlock());
937 
938  return kernel::ComputeUTXOStats(hash_type, view, blockman, interruption_point);
939 }
940 
942 {
943  return RPCHelpMan{"gettxoutsetinfo",
944  "\nReturns statistics about the unspent transaction output set.\n"
945  "Note this call may take some time if you are not using coinstatsindex.\n",
946  {
947  {"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'."},
948  {"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).",
950  .skip_type_check = true,
951  .type_str = {"", "string or numeric"},
952  }},
953  {"use_index", RPCArg::Type::BOOL, RPCArg::Default{true}, "Use coinstatsindex, if available."},
954  },
955  RPCResult{
956  RPCResult::Type::OBJ, "", "",
957  {
958  {RPCResult::Type::NUM, "height", "The block height (index) of the returned statistics"},
959  {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at which these statistics are calculated"},
960  {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
961  {RPCResult::Type::NUM, "bogosize", "Database-independent, meaningless metric indicating the UTXO set size"},
962  {RPCResult::Type::STR_HEX, "hash_serialized_3", /*optional=*/true, "The serialized hash (only present if 'hash_serialized_3' hash_type is chosen)"},
963  {RPCResult::Type::STR_HEX, "muhash", /*optional=*/true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
964  {RPCResult::Type::NUM, "transactions", /*optional=*/true, "The number of transactions with unspent outputs (not available when coinstatsindex is used)"},
965  {RPCResult::Type::NUM, "disk_size", /*optional=*/true, "The estimated size of the chainstate on disk (not available when coinstatsindex is used)"},
966  {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of coins in the UTXO set"},
967  {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)"},
968  {RPCResult::Type::OBJ, "block_info", /*optional=*/true, "Info on amounts in the block at this block height (only available if coinstatsindex is used)",
969  {
970  {RPCResult::Type::STR_AMOUNT, "prevout_spent", "Total amount of all prevouts spent in this block"},
971  {RPCResult::Type::STR_AMOUNT, "coinbase", "Coinbase subsidy amount of this block"},
972  {RPCResult::Type::STR_AMOUNT, "new_outputs_ex_coinbase", "Total amount of new outputs created by this block"},
973  {RPCResult::Type::STR_AMOUNT, "unspendable", "Total amount of unspendable outputs created in this block"},
974  {RPCResult::Type::OBJ, "unspendables", "Detailed view of the unspendable categories",
975  {
976  {RPCResult::Type::STR_AMOUNT, "genesis_block", "The unspendable amount of the Genesis block subsidy"},
977  {RPCResult::Type::STR_AMOUNT, "bip30", "Transactions overridden by duplicates (no longer possible with BIP30)"},
978  {RPCResult::Type::STR_AMOUNT, "scripts", "Amounts sent to scripts that are unspendable (for example OP_RETURN outputs)"},
979  {RPCResult::Type::STR_AMOUNT, "unclaimed_rewards", "Fee rewards that miners did not claim in their coinbase transaction"},
980  }}
981  }},
982  }},
983  RPCExamples{
984  HelpExampleCli("gettxoutsetinfo", "") +
985  HelpExampleCli("gettxoutsetinfo", R"("none")") +
986  HelpExampleCli("gettxoutsetinfo", R"("none" 1000)") +
987  HelpExampleCli("gettxoutsetinfo", R"("none" '"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"')") +
988  HelpExampleCli("-named gettxoutsetinfo", R"(hash_type='muhash' use_index='false')") +
989  HelpExampleRpc("gettxoutsetinfo", "") +
990  HelpExampleRpc("gettxoutsetinfo", R"("none")") +
991  HelpExampleRpc("gettxoutsetinfo", R"("none", 1000)") +
992  HelpExampleRpc("gettxoutsetinfo", R"("none", "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09")")
993  },
994  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
995 {
997 
998  const CBlockIndex* pindex{nullptr};
999  const CoinStatsHashType hash_type{request.params[0].isNull() ? CoinStatsHashType::HASH_SERIALIZED : ParseHashType(request.params[0].get_str())};
1000  bool index_requested = request.params[2].isNull() || request.params[2].get_bool();
1001 
1002  NodeContext& node = EnsureAnyNodeContext(request.context);
1003  ChainstateManager& chainman = EnsureChainman(node);
1004  Chainstate& active_chainstate = chainman.ActiveChainstate();
1005  active_chainstate.ForceFlushStateToDisk();
1006 
1007  CCoinsView* coins_view;
1008  BlockManager* blockman;
1009  {
1010  LOCK(::cs_main);
1011  coins_view = &active_chainstate.CoinsDB();
1012  blockman = &active_chainstate.m_blockman;
1013  pindex = blockman->LookupBlockIndex(coins_view->GetBestBlock());
1014  }
1015 
1016  if (!request.params[1].isNull()) {
1017  if (!g_coin_stats_index) {
1018  throw JSONRPCError(RPC_INVALID_PARAMETER, "Querying specific block heights requires coinstatsindex");
1019  }
1020 
1021  if (hash_type == CoinStatsHashType::HASH_SERIALIZED) {
1022  throw JSONRPCError(RPC_INVALID_PARAMETER, "hash_serialized_3 hash type cannot be queried for a specific block");
1023  }
1024 
1025  if (!index_requested) {
1026  throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot set use_index to false when querying for a specific block");
1027  }
1028  pindex = ParseHashOrHeight(request.params[1], chainman);
1029  }
1030 
1031  if (index_requested && g_coin_stats_index) {
1032  if (!g_coin_stats_index->BlockUntilSyncedToCurrentChain()) {
1033  const IndexSummary summary{g_coin_stats_index->GetSummary()};
1034 
1035  // If a specific block was requested and the index has already synced past that height, we can return the
1036  // data already even though the index is not fully synced yet.
1037  if (pindex->nHeight > summary.best_block_height) {
1038  throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to get data because coinstatsindex is still syncing. Current height: %d", summary.best_block_height));
1039  }
1040  }
1041  }
1042 
1043  const std::optional<CCoinsStats> maybe_stats = GetUTXOStats(coins_view, *blockman, hash_type, node.rpc_interruption_point, pindex, index_requested);
1044  if (maybe_stats.has_value()) {
1045  const CCoinsStats& stats = maybe_stats.value();
1046  ret.pushKV("height", (int64_t)stats.nHeight);
1047  ret.pushKV("bestblock", stats.hashBlock.GetHex());
1048  ret.pushKV("txouts", (int64_t)stats.nTransactionOutputs);
1049  ret.pushKV("bogosize", (int64_t)stats.nBogoSize);
1050  if (hash_type == CoinStatsHashType::HASH_SERIALIZED) {
1051  ret.pushKV("hash_serialized_3", stats.hashSerialized.GetHex());
1052  }
1053  if (hash_type == CoinStatsHashType::MUHASH) {
1054  ret.pushKV("muhash", stats.hashSerialized.GetHex());
1055  }
1056  CHECK_NONFATAL(stats.total_amount.has_value());
1057  ret.pushKV("total_amount", ValueFromAmount(stats.total_amount.value()));
1058  if (!stats.index_used) {
1059  ret.pushKV("transactions", static_cast<int64_t>(stats.nTransactions));
1060  ret.pushKV("disk_size", stats.nDiskSize);
1061  } else {
1062  ret.pushKV("total_unspendable_amount", ValueFromAmount(stats.total_unspendable_amount));
1063 
1064  CCoinsStats prev_stats{};
1065  if (pindex->nHeight > 0) {
1066  const std::optional<CCoinsStats> maybe_prev_stats = GetUTXOStats(coins_view, *blockman, hash_type, node.rpc_interruption_point, pindex->pprev, index_requested);
1067  if (!maybe_prev_stats) {
1068  throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
1069  }
1070  prev_stats = maybe_prev_stats.value();
1071  }
1072 
1073  UniValue block_info(UniValue::VOBJ);
1074  block_info.pushKV("prevout_spent", ValueFromAmount(stats.total_prevout_spent_amount - prev_stats.total_prevout_spent_amount));
1075  block_info.pushKV("coinbase", ValueFromAmount(stats.total_coinbase_amount - prev_stats.total_coinbase_amount));
1076  block_info.pushKV("new_outputs_ex_coinbase", ValueFromAmount(stats.total_new_outputs_ex_coinbase_amount - prev_stats.total_new_outputs_ex_coinbase_amount));
1077  block_info.pushKV("unspendable", ValueFromAmount(stats.total_unspendable_amount - prev_stats.total_unspendable_amount));
1078 
1079  UniValue unspendables(UniValue::VOBJ);
1080  unspendables.pushKV("genesis_block", ValueFromAmount(stats.total_unspendables_genesis_block - prev_stats.total_unspendables_genesis_block));
1081  unspendables.pushKV("bip30", ValueFromAmount(stats.total_unspendables_bip30 - prev_stats.total_unspendables_bip30));
1082  unspendables.pushKV("scripts", ValueFromAmount(stats.total_unspendables_scripts - prev_stats.total_unspendables_scripts));
1083  unspendables.pushKV("unclaimed_rewards", ValueFromAmount(stats.total_unspendables_unclaimed_rewards - prev_stats.total_unspendables_unclaimed_rewards));
1084  block_info.pushKV("unspendables", std::move(unspendables));
1085 
1086  ret.pushKV("block_info", std::move(block_info));
1087  }
1088  } else {
1089  throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
1090  }
1091  return ret;
1092 },
1093  };
1094 }
1095 
1097 {
1098  return RPCHelpMan{"gettxout",
1099  "\nReturns details about an unspent transaction output.\n",
1100  {
1101  {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"},
1102  {"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"},
1103  {"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."},
1104  },
1105  {
1106  RPCResult{"If the UTXO was not found", RPCResult::Type::NONE, "", ""},
1107  RPCResult{"Otherwise", RPCResult::Type::OBJ, "", "", {
1108  {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
1109  {RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
1110  {RPCResult::Type::STR_AMOUNT, "value", "The transaction value in " + CURRENCY_UNIT},
1111  {RPCResult::Type::OBJ, "scriptPubKey", "", {
1112  {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
1113  {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
1114  {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
1115  {RPCResult::Type::STR, "type", "The type, eg pubkeyhash"},
1116  {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
1117  }},
1118  {RPCResult::Type::BOOL, "coinbase", "Coinbase or not"},
1119  }},
1120  },
1121  RPCExamples{
1122  "\nGet unspent transactions\n"
1123  + HelpExampleCli("listunspent", "") +
1124  "\nView the details\n"
1125  + HelpExampleCli("gettxout", "\"txid\" 1") +
1126  "\nAs a JSON-RPC call\n"
1127  + HelpExampleRpc("gettxout", "\"txid\", 1")
1128  },
1129  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1130 {
1131  NodeContext& node = EnsureAnyNodeContext(request.context);
1132  ChainstateManager& chainman = EnsureChainman(node);
1133  LOCK(cs_main);
1134 
1136 
1137  auto hash{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
1138  COutPoint out{hash, request.params[1].getInt<uint32_t>()};
1139  bool fMempool = true;
1140  if (!request.params[2].isNull())
1141  fMempool = request.params[2].get_bool();
1142 
1143  Chainstate& active_chainstate = chainman.ActiveChainstate();
1144  CCoinsViewCache* coins_view = &active_chainstate.CoinsTip();
1145 
1146  std::optional<Coin> coin;
1147  if (fMempool) {
1148  const CTxMemPool& mempool = EnsureMemPool(node);
1149  LOCK(mempool.cs);
1150  CCoinsViewMemPool view(coins_view, mempool);
1151  if (!mempool.isSpent(out)) coin = view.GetCoin(out);
1152  } else {
1153  coin = coins_view->GetCoin(out);
1154  }
1155  if (!coin) return UniValue::VNULL;
1156 
1157  const CBlockIndex* pindex = active_chainstate.m_blockman.LookupBlockIndex(coins_view->GetBestBlock());
1158  ret.pushKV("bestblock", pindex->GetBlockHash().GetHex());
1159  if (coin->nHeight == MEMPOOL_HEIGHT) {
1160  ret.pushKV("confirmations", 0);
1161  } else {
1162  ret.pushKV("confirmations", (int64_t)(pindex->nHeight - coin->nHeight + 1));
1163  }
1164  ret.pushKV("value", ValueFromAmount(coin->out.nValue));
1166  ScriptToUniv(coin->out.scriptPubKey, /*out=*/o, /*include_hex=*/true, /*include_address=*/true);
1167  ret.pushKV("scriptPubKey", std::move(o));
1168  ret.pushKV("coinbase", (bool)coin->fCoinBase);
1169 
1170  return ret;
1171 },
1172  };
1173 }
1174 
1176 {
1177  return RPCHelpMan{"verifychain",
1178  "\nVerifies blockchain database.\n",
1179  {
1180  {"checklevel", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%d, range=0-4", DEFAULT_CHECKLEVEL)},
1181  strprintf("How thorough the block verification is:\n%s", MakeUnorderedList(CHECKLEVEL_DOC))},
1182  {"nblocks", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%d, 0=all", DEFAULT_CHECKBLOCKS)}, "The number of blocks to check."},
1183  },
1184  RPCResult{
1185  RPCResult::Type::BOOL, "", "Verification finished successfully. If false, check debug.log for reason."},
1186  RPCExamples{
1187  HelpExampleCli("verifychain", "")
1188  + HelpExampleRpc("verifychain", "")
1189  },
1190  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1191 {
1192  const int check_level{request.params[0].isNull() ? DEFAULT_CHECKLEVEL : request.params[0].getInt<int>()};
1193  const int check_depth{request.params[1].isNull() ? DEFAULT_CHECKBLOCKS : request.params[1].getInt<int>()};
1194 
1195  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1196  LOCK(cs_main);
1197 
1198  Chainstate& active_chainstate = chainman.ActiveChainstate();
1199  return CVerifyDB(chainman.GetNotifications()).VerifyDB(
1200  active_chainstate, chainman.GetParams().GetConsensus(), active_chainstate.CoinsTip(), check_level, check_depth) == VerifyDBResult::SUCCESS;
1201 },
1202  };
1203 }
1204 
1205 static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::BuriedDeployment dep)
1206 {
1207  // For buried deployments.
1208 
1209  if (!DeploymentEnabled(chainman, dep)) return;
1210 
1212  rv.pushKV("type", "buried");
1213  // getdeploymentinfo reports the softfork as active from when the chain height is
1214  // one below the activation height
1215  rv.pushKV("active", DeploymentActiveAfter(blockindex, chainman, dep));
1216  rv.pushKV("height", chainman.GetConsensus().DeploymentHeight(dep));
1217  softforks.pushKV(DeploymentName(dep), std::move(rv));
1218 }
1219 
1220 static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id)
1221 {
1222  // For BIP9 deployments.
1223 
1224  if (!DeploymentEnabled(chainman, id)) return;
1225  if (blockindex == nullptr) return;
1226 
1227  auto get_state_name = [](const ThresholdState state) -> std::string {
1228  switch (state) {
1229  case ThresholdState::DEFINED: return "defined";
1230  case ThresholdState::STARTED: return "started";
1231  case ThresholdState::LOCKED_IN: return "locked_in";
1232  case ThresholdState::ACTIVE: return "active";
1233  case ThresholdState::FAILED: return "failed";
1234  }
1235  return "invalid";
1236  };
1237 
1238  UniValue bip9(UniValue::VOBJ);
1239 
1240  const ThresholdState next_state = chainman.m_versionbitscache.State(blockindex, chainman.GetConsensus(), id);
1241  const ThresholdState current_state = chainman.m_versionbitscache.State(blockindex->pprev, chainman.GetConsensus(), id);
1242 
1243  const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state);
1244 
1245  // BIP9 parameters
1246  if (has_signal) {
1247  bip9.pushKV("bit", chainman.GetConsensus().vDeployments[id].bit);
1248  }
1249  bip9.pushKV("start_time", chainman.GetConsensus().vDeployments[id].nStartTime);
1250  bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout);
1251  bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height);
1252 
1253  // BIP9 status
1254  bip9.pushKV("status", get_state_name(current_state));
1255  bip9.pushKV("since", chainman.m_versionbitscache.StateSinceHeight(blockindex->pprev, chainman.GetConsensus(), id));
1256  bip9.pushKV("status_next", get_state_name(next_state));
1257 
1258  // BIP9 signalling status, if applicable
1259  if (has_signal) {
1260  UniValue statsUV(UniValue::VOBJ);
1261  std::vector<bool> signals;
1262  BIP9Stats statsStruct = chainman.m_versionbitscache.Statistics(blockindex, chainman.GetConsensus(), id, &signals);
1263  statsUV.pushKV("period", statsStruct.period);
1264  statsUV.pushKV("elapsed", statsStruct.elapsed);
1265  statsUV.pushKV("count", statsStruct.count);
1266  if (ThresholdState::LOCKED_IN != current_state) {
1267  statsUV.pushKV("threshold", statsStruct.threshold);
1268  statsUV.pushKV("possible", statsStruct.possible);
1269  }
1270  bip9.pushKV("statistics", std::move(statsUV));
1271 
1272  std::string sig;
1273  sig.reserve(signals.size());
1274  for (const bool s : signals) {
1275  sig.push_back(s ? '#' : '-');
1276  }
1277  bip9.pushKV("signalling", sig);
1278  }
1279 
1281  rv.pushKV("type", "bip9");
1282  if (ThresholdState::ACTIVE == next_state) {
1283  rv.pushKV("height", chainman.m_versionbitscache.StateSinceHeight(blockindex, chainman.GetConsensus(), id));
1284  }
1285  rv.pushKV("active", ThresholdState::ACTIVE == next_state);
1286  rv.pushKV("bip9", std::move(bip9));
1287 
1288  softforks.pushKV(DeploymentName(id), std::move(rv));
1289 }
1290 
1291 // used by rest.cpp:rest_chaininfo, so cannot be static
1293 {
1294  return RPCHelpMan{"getblockchaininfo",
1295  "Returns an object containing various state info regarding blockchain processing.\n",
1296  {},
1297  RPCResult{
1298  RPCResult::Type::OBJ, "", "",
1299  {
1300  {RPCResult::Type::STR, "chain", "current network name (" LIST_CHAIN_NAMES ")"},
1301  {RPCResult::Type::NUM, "blocks", "the height of the most-work fully-validated chain. The genesis block has height 0"},
1302  {RPCResult::Type::NUM, "headers", "the current number of headers we have validated"},
1303  {RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block"},
1304  {RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},
1305  {RPCResult::Type::STR_HEX, "target", "The difficulty target"},
1306  {RPCResult::Type::NUM, "difficulty", "the current difficulty"},
1307  {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME},
1308  {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
1309  {RPCResult::Type::NUM, "verificationprogress", "estimate of verification progress [0..1]"},
1310  {RPCResult::Type::BOOL, "initialblockdownload", "(debug information) estimate of whether this node is in Initial Block Download mode"},
1311  {RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"},
1312  {RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"},
1313  {RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"},
1314  {RPCResult::Type::NUM, "pruneheight", /*optional=*/true, "height of the last block pruned, plus one (only present if pruning is enabled)"},
1315  {RPCResult::Type::BOOL, "automatic_pruning", /*optional=*/true, "whether automatic pruning is enabled (only present if pruning is enabled)"},
1316  {RPCResult::Type::NUM, "prune_target_size", /*optional=*/true, "the target size used by pruning (only present if automatic pruning is enabled)"},
1317  {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "the block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)"},
1318  (IsDeprecatedRPCEnabled("warnings") ?
1319  RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} :
1320  RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)",
1321  {
1322  {RPCResult::Type::STR, "", "warning"},
1323  }
1324  }
1325  ),
1326  }},
1327  RPCExamples{
1328  HelpExampleCli("getblockchaininfo", "")
1329  + HelpExampleRpc("getblockchaininfo", "")
1330  },
1331  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1332 {
1333  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1334  LOCK(cs_main);
1335  Chainstate& active_chainstate = chainman.ActiveChainstate();
1336 
1337  const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())};
1338  const int height{tip.nHeight};
1339  UniValue obj(UniValue::VOBJ);
1340  obj.pushKV("chain", chainman.GetParams().GetChainTypeString());
1341  obj.pushKV("blocks", height);
1342  obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
1343  obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
1344  obj.pushKV("bits", strprintf("%08x", tip.nBits));
1345  obj.pushKV("target", GetTarget(tip, chainman.GetConsensus().powLimit).GetHex());
1346  obj.pushKV("difficulty", GetDifficulty(tip));
1347  obj.pushKV("time", tip.GetBlockTime());
1348  obj.pushKV("mediantime", tip.GetMedianTimePast());
1349  obj.pushKV("verificationprogress", chainman.GuessVerificationProgress(&tip));
1350  obj.pushKV("initialblockdownload", chainman.IsInitialBlockDownload());
1351  obj.pushKV("chainwork", tip.nChainWork.GetHex());
1352  obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());
1353  obj.pushKV("pruned", chainman.m_blockman.IsPruneMode());
1354  if (chainman.m_blockman.IsPruneMode()) {
1355  const auto prune_height{GetPruneHeight(chainman.m_blockman, active_chainstate.m_chain)};
1356  obj.pushKV("pruneheight", prune_height ? prune_height.value() + 1 : 0);
1357 
1358  const bool automatic_pruning{chainman.m_blockman.GetPruneTarget() != BlockManager::PRUNE_TARGET_MANUAL};
1359  obj.pushKV("automatic_pruning", automatic_pruning);
1360  if (automatic_pruning) {
1361  obj.pushKV("prune_target_size", chainman.m_blockman.GetPruneTarget());
1362  }
1363  }
1364  if (chainman.GetParams().GetChainType() == ChainType::SIGNET) {
1365  const std::vector<uint8_t>& signet_challenge =
1367  obj.pushKV("signet_challenge", HexStr(signet_challenge));
1368  }
1369 
1370  NodeContext& node = EnsureAnyNodeContext(request.context);
1371  obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings")));
1372  return obj;
1373 },
1374  };
1375 }
1376 
1377 namespace {
1378 const std::vector<RPCResult> RPCHelpForDeployment{
1379  {RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""},
1380  {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)"},
1381  {RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"},
1382  {RPCResult::Type::OBJ, "bip9", /*optional=*/true, "status of bip9 softforks (only for \"bip9\" type)",
1383  {
1384  {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)"},
1385  {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"},
1386  {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"},
1387  {RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"},
1388  {RPCResult::Type::STR, "status", "status of deployment at specified block (one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\")"},
1389  {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"},
1390  {RPCResult::Type::STR, "status_next", "status of deployment at the next block"},
1391  {RPCResult::Type::OBJ, "statistics", /*optional=*/true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)",
1392  {
1393  {RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"},
1394  {RPCResult::Type::NUM, "threshold", /*optional=*/true, "the number of blocks with the version bit set required to activate the feature (only for \"started\" status)"},
1395  {RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"},
1396  {RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"},
1397  {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)"},
1398  }},
1399  {RPCResult::Type::STR, "signalling", /*optional=*/true, "indicates blocks that signalled with a # and blocks that did not with a -"},
1400  }},
1401 };
1402 
1403 UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager& chainman)
1404 {
1405  UniValue softforks(UniValue::VOBJ);
1406  SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_HEIGHTINCB);
1407  SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_DERSIG);
1408  SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CLTV);
1409  SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CSV);
1410  SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_SEGWIT);
1411  SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TESTDUMMY);
1412  SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TAPROOT);
1413  return softforks;
1414 }
1415 } // anon namespace
1416 
1418 {
1419  return RPCHelpMan{"getdeploymentinfo",
1420  "Returns an object containing various state info regarding deployments of consensus changes.",
1421  {
1422  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Default{"hash of current chain tip"}, "The block hash at which to query deployment state"},
1423  },
1424  RPCResult{
1425  RPCResult::Type::OBJ, "", "", {
1426  {RPCResult::Type::STR, "hash", "requested block hash (or tip)"},
1427  {RPCResult::Type::NUM, "height", "requested block height (or tip)"},
1428  {RPCResult::Type::OBJ_DYN, "deployments", "", {
1429  {RPCResult::Type::OBJ, "xxxx", "name of the deployment", RPCHelpForDeployment}
1430  }},
1431  }
1432  },
1433  RPCExamples{ HelpExampleCli("getdeploymentinfo", "") + HelpExampleRpc("getdeploymentinfo", "") },
1434  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1435  {
1436  const ChainstateManager& chainman = EnsureAnyChainman(request.context);
1437  LOCK(cs_main);
1438  const Chainstate& active_chainstate = chainman.ActiveChainstate();
1439 
1440  const CBlockIndex* blockindex;
1441  if (request.params[0].isNull()) {
1442  blockindex = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
1443  } else {
1444  const uint256 hash(ParseHashV(request.params[0], "blockhash"));
1445  blockindex = chainman.m_blockman.LookupBlockIndex(hash);
1446  if (!blockindex) {
1447  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1448  }
1449  }
1450 
1451  UniValue deploymentinfo(UniValue::VOBJ);
1452  deploymentinfo.pushKV("hash", blockindex->GetBlockHash().ToString());
1453  deploymentinfo.pushKV("height", blockindex->nHeight);
1454  deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, chainman));
1455  return deploymentinfo;
1456  },
1457  };
1458 }
1459 
1462 {
1463  bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
1464  {
1465  /* Make sure that unequal blocks with the same height do not compare
1466  equal. Use the pointers themselves to make a distinction. */
1467 
1468  if (a->nHeight != b->nHeight)
1469  return (a->nHeight > b->nHeight);
1470 
1471  return a < b;
1472  }
1473 };
1474 
1476 {
1477  return RPCHelpMan{"getchaintips",
1478  "Return information about all known tips in the block tree,"
1479  " including the main chain as well as orphaned branches.\n",
1480  {},
1481  RPCResult{
1482  RPCResult::Type::ARR, "", "",
1483  {{RPCResult::Type::OBJ, "", "",
1484  {
1485  {RPCResult::Type::NUM, "height", "height of the chain tip"},
1486  {RPCResult::Type::STR_HEX, "hash", "block hash of the tip"},
1487  {RPCResult::Type::NUM, "branchlen", "zero for main chain, otherwise length of branch connecting the tip to the main chain"},
1488  {RPCResult::Type::STR, "status", "status of the chain, \"active\" for the main chain\n"
1489  "Possible values for status:\n"
1490  "1. \"invalid\" This branch contains at least one invalid block\n"
1491  "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
1492  "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
1493  "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
1494  "5. \"active\" This is the tip of the active main chain, which is certainly valid"},
1495  }}}},
1496  RPCExamples{
1497  HelpExampleCli("getchaintips", "")
1498  + HelpExampleRpc("getchaintips", "")
1499  },
1500  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1501 {
1502  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1503  LOCK(cs_main);
1504  CChain& active_chain = chainman.ActiveChain();
1505 
1506  /*
1507  * Idea: The set of chain tips is the active chain tip, plus orphan blocks which do not have another orphan building off of them.
1508  * Algorithm:
1509  * - Make one pass through BlockIndex(), picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
1510  * - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
1511  * - Add the active chain tip
1512  */
1513  std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
1514  std::set<const CBlockIndex*> setOrphans;
1515  std::set<const CBlockIndex*> setPrevs;
1516 
1517  for (const auto& [_, block_index] : chainman.BlockIndex()) {
1518  if (!active_chain.Contains(&block_index)) {
1519  setOrphans.insert(&block_index);
1520  setPrevs.insert(block_index.pprev);
1521  }
1522  }
1523 
1524  for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it) {
1525  if (setPrevs.erase(*it) == 0) {
1526  setTips.insert(*it);
1527  }
1528  }
1529 
1530  // Always report the currently active tip.
1531  setTips.insert(active_chain.Tip());
1532 
1533  /* Construct the output array. */
1534  UniValue res(UniValue::VARR);
1535  for (const CBlockIndex* block : setTips) {
1536  UniValue obj(UniValue::VOBJ);
1537  obj.pushKV("height", block->nHeight);
1538  obj.pushKV("hash", block->phashBlock->GetHex());
1539 
1540  const int branchLen = block->nHeight - active_chain.FindFork(block)->nHeight;
1541  obj.pushKV("branchlen", branchLen);
1542 
1543  std::string status;
1544  if (active_chain.Contains(block)) {
1545  // This block is part of the currently active chain.
1546  status = "active";
1547  } else if (block->nStatus & BLOCK_FAILED_MASK) {
1548  // This block or one of its ancestors is invalid.
1549  status = "invalid";
1550  } else if (!block->HaveNumChainTxs()) {
1551  // This block cannot be connected because full block data for it or one of its parents is missing.
1552  status = "headers-only";
1553  } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
1554  // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
1555  status = "valid-fork";
1556  } else if (block->IsValid(BLOCK_VALID_TREE)) {
1557  // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
1558  status = "valid-headers";
1559  } else {
1560  // No clue.
1561  status = "unknown";
1562  }
1563  obj.pushKV("status", status);
1564 
1565  res.push_back(std::move(obj));
1566  }
1567 
1568  return res;
1569 },
1570  };
1571 }
1572 
1574 {
1575  return RPCHelpMan{"preciousblock",
1576  "\nTreats a block as if it were received before others with the same work.\n"
1577  "\nA later preciousblock call can override the effect of an earlier one.\n"
1578  "\nThe effects of preciousblock are not retained across restarts.\n",
1579  {
1580  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as precious"},
1581  },
1583  RPCExamples{
1584  HelpExampleCli("preciousblock", "\"blockhash\"")
1585  + HelpExampleRpc("preciousblock", "\"blockhash\"")
1586  },
1587  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1588 {
1589  uint256 hash(ParseHashV(request.params[0], "blockhash"));
1590  CBlockIndex* pblockindex;
1591 
1592  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1593  {
1594  LOCK(cs_main);
1595  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
1596  if (!pblockindex) {
1597  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1598  }
1599  }
1600 
1601  BlockValidationState state;
1602  chainman.ActiveChainstate().PreciousBlock(state, pblockindex);
1603 
1604  if (!state.IsValid()) {
1605  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
1606  }
1607 
1608  return UniValue::VNULL;
1609 },
1610  };
1611 }
1612 
1613 void InvalidateBlock(ChainstateManager& chainman, const uint256 block_hash) {
1614  BlockValidationState state;
1615  CBlockIndex* pblockindex;
1616  {
1617  LOCK(chainman.GetMutex());
1618  pblockindex = chainman.m_blockman.LookupBlockIndex(block_hash);
1619  if (!pblockindex) {
1620  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1621  }
1622  }
1623  chainman.ActiveChainstate().InvalidateBlock(state, pblockindex);
1624 
1625  if (state.IsValid()) {
1626  chainman.ActiveChainstate().ActivateBestChain(state);
1627  }
1628 
1629  if (!state.IsValid()) {
1630  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
1631  }
1632 }
1633 
1635 {
1636  return RPCHelpMan{"invalidateblock",
1637  "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n",
1638  {
1639  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as invalid"},
1640  },
1642  RPCExamples{
1643  HelpExampleCli("invalidateblock", "\"blockhash\"")
1644  + HelpExampleRpc("invalidateblock", "\"blockhash\"")
1645  },
1646  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1647 {
1648  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1649  uint256 hash(ParseHashV(request.params[0], "blockhash"));
1650 
1651  InvalidateBlock(chainman, hash);
1652 
1653  return UniValue::VNULL;
1654 },
1655  };
1656 }
1657 
1658 void ReconsiderBlock(ChainstateManager& chainman, uint256 block_hash) {
1659  {
1660  LOCK(chainman.GetMutex());
1661  CBlockIndex* pblockindex = chainman.m_blockman.LookupBlockIndex(block_hash);
1662  if (!pblockindex) {
1663  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1664  }
1665 
1666  chainman.ActiveChainstate().ResetBlockFailureFlags(pblockindex);
1667  chainman.RecalculateBestHeader();
1668  }
1669 
1670  BlockValidationState state;
1671  chainman.ActiveChainstate().ActivateBestChain(state);
1672 
1673  if (!state.IsValid()) {
1674  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
1675  }
1676 }
1677 
1679 {
1680  return RPCHelpMan{"reconsiderblock",
1681  "\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n"
1682  "This can be used to undo the effects of invalidateblock.\n",
1683  {
1684  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"},
1685  },
1687  RPCExamples{
1688  HelpExampleCli("reconsiderblock", "\"blockhash\"")
1689  + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
1690  },
1691  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1692 {
1693  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1694  uint256 hash(ParseHashV(request.params[0], "blockhash"));
1695 
1696  ReconsiderBlock(chainman, hash);
1697 
1698  return UniValue::VNULL;
1699 },
1700  };
1701 }
1702 
1704 {
1705  return RPCHelpMan{"getchaintxstats",
1706  "\nCompute statistics about the total number and rate of transactions in the chain.\n",
1707  {
1708  {"nblocks", RPCArg::Type::NUM, RPCArg::DefaultHint{"one month"}, "Size of the window in number of blocks"},
1709  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::DefaultHint{"chain tip"}, "The hash of the block that ends the window."},
1710  },
1711  RPCResult{
1712  RPCResult::Type::OBJ, "", "",
1713  {
1714  {RPCResult::Type::NUM_TIME, "time", "The timestamp for the final block in the window, expressed in " + UNIX_EPOCH_TIME},
1715  {RPCResult::Type::NUM, "txcount", /*optional=*/true,
1716  "The total number of transactions in the chain up to that point, if known. "
1717  "It may be unknown when using assumeutxo."},
1718  {RPCResult::Type::STR_HEX, "window_final_block_hash", "The hash of the final block in the window"},
1719  {RPCResult::Type::NUM, "window_final_block_height", "The height of the final block in the window."},
1720  {RPCResult::Type::NUM, "window_block_count", "Size of the window in number of blocks"},
1721  {RPCResult::Type::NUM, "window_interval", /*optional=*/true, "The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0"},
1722  {RPCResult::Type::NUM, "window_tx_count", /*optional=*/true,
1723  "The number of transactions in the window. "
1724  "Only returned if \"window_block_count\" is > 0 and if txcount exists for the start and end of the window."},
1725  {RPCResult::Type::NUM, "txrate", /*optional=*/true,
1726  "The average rate of transactions per second in the window. "
1727  "Only returned if \"window_interval\" is > 0 and if window_tx_count exists."},
1728  }},
1729  RPCExamples{
1730  HelpExampleCli("getchaintxstats", "")
1731  + HelpExampleRpc("getchaintxstats", "2016")
1732  },
1733  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1734 {
1735  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1736  const CBlockIndex* pindex;
1737  int blockcount = 30 * 24 * 60 * 60 / chainman.GetParams().GetConsensus().nPowTargetSpacing; // By default: 1 month
1738 
1739  if (request.params[1].isNull()) {
1740  LOCK(cs_main);
1741  pindex = chainman.ActiveChain().Tip();
1742  } else {
1743  uint256 hash(ParseHashV(request.params[1], "blockhash"));
1744  LOCK(cs_main);
1745  pindex = chainman.m_blockman.LookupBlockIndex(hash);
1746  if (!pindex) {
1747  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1748  }
1749  if (!chainman.ActiveChain().Contains(pindex)) {
1750  throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain");
1751  }
1752  }
1753 
1754  CHECK_NONFATAL(pindex != nullptr);
1755 
1756  if (request.params[0].isNull()) {
1757  blockcount = std::max(0, std::min(blockcount, pindex->nHeight - 1));
1758  } else {
1759  blockcount = request.params[0].getInt<int>();
1760 
1761  if (blockcount < 0 || (blockcount > 0 && blockcount >= pindex->nHeight)) {
1762  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1");
1763  }
1764  }
1765 
1766  const CBlockIndex& past_block{*CHECK_NONFATAL(pindex->GetAncestor(pindex->nHeight - blockcount))};
1767  const int64_t nTimeDiff{pindex->GetMedianTimePast() - past_block.GetMedianTimePast()};
1768 
1770  ret.pushKV("time", (int64_t)pindex->nTime);
1771  if (pindex->m_chain_tx_count) {
1772  ret.pushKV("txcount", pindex->m_chain_tx_count);
1773  }
1774  ret.pushKV("window_final_block_hash", pindex->GetBlockHash().GetHex());
1775  ret.pushKV("window_final_block_height", pindex->nHeight);
1776  ret.pushKV("window_block_count", blockcount);
1777  if (blockcount > 0) {
1778  ret.pushKV("window_interval", nTimeDiff);
1779  if (pindex->m_chain_tx_count != 0 && past_block.m_chain_tx_count != 0) {
1780  const auto window_tx_count = pindex->m_chain_tx_count - past_block.m_chain_tx_count;
1781  ret.pushKV("window_tx_count", window_tx_count);
1782  if (nTimeDiff > 0) {
1783  ret.pushKV("txrate", double(window_tx_count) / nTimeDiff);
1784  }
1785  }
1786  }
1787 
1788  return ret;
1789 },
1790  };
1791 }
1792 
1793 template<typename T>
1794 static T CalculateTruncatedMedian(std::vector<T>& scores)
1795 {
1796  size_t size = scores.size();
1797  if (size == 0) {
1798  return 0;
1799  }
1800 
1801  std::sort(scores.begin(), scores.end());
1802  if (size % 2 == 0) {
1803  return (scores[size / 2 - 1] + scores[size / 2]) / 2;
1804  } else {
1805  return scores[size / 2];
1806  }
1807 }
1808 
1809 void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight)
1810 {
1811  if (scores.empty()) {
1812  return;
1813  }
1814 
1815  std::sort(scores.begin(), scores.end());
1816 
1817  // 10th, 25th, 50th, 75th, and 90th percentile weight units.
1818  const double weights[NUM_GETBLOCKSTATS_PERCENTILES] = {
1819  total_weight / 10.0, total_weight / 4.0, total_weight / 2.0, (total_weight * 3.0) / 4.0, (total_weight * 9.0) / 10.0
1820  };
1821 
1822  int64_t next_percentile_index = 0;
1823  int64_t cumulative_weight = 0;
1824  for (const auto& element : scores) {
1825  cumulative_weight += element.second;
1826  while (next_percentile_index < NUM_GETBLOCKSTATS_PERCENTILES && cumulative_weight >= weights[next_percentile_index]) {
1827  result[next_percentile_index] = element.first;
1828  ++next_percentile_index;
1829  }
1830  }
1831 
1832  // Fill any remaining percentiles with the last value.
1833  for (int64_t i = next_percentile_index; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) {
1834  result[i] = scores.back().first;
1835  }
1836 }
1837 
1838 template<typename T>
1839 static inline bool SetHasKeys(const std::set<T>& set) {return false;}
1840 template<typename T, typename Tk, typename... Args>
1841 static inline bool SetHasKeys(const std::set<T>& set, const Tk& key, const Args&... args)
1842 {
1843  return (set.count(key) != 0) || SetHasKeys(set, args...);
1844 }
1845 
1846 // outpoint (needed for the utxo index) + nHeight + fCoinBase
1847 static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool);
1848 
1850 {
1851  return RPCHelpMan{"getblockstats",
1852  "\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
1853  "It won't work for some heights with pruning.\n",
1854  {
1855  {"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block hash or height of the target block",
1856  RPCArgOptions{
1857  .skip_type_check = true,
1858  .type_str = {"", "string or numeric"},
1859  }},
1860  {"stats", RPCArg::Type::ARR, RPCArg::DefaultHint{"all values"}, "Values to plot (see result below)",
1861  {
1862  {"height", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
1863  {"time", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
1864  },
1866  },
1867  RPCResult{
1868  RPCResult::Type::OBJ, "", "",
1869  {
1870  {RPCResult::Type::NUM, "avgfee", /*optional=*/true, "Average fee in the block"},
1871  {RPCResult::Type::NUM, "avgfeerate", /*optional=*/true, "Average feerate (in satoshis per virtual byte)"},
1872  {RPCResult::Type::NUM, "avgtxsize", /*optional=*/true, "Average transaction size"},
1873  {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block hash (to check for potential reorgs)"},
1874  {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)",
1875  {
1876  {RPCResult::Type::NUM, "10th_percentile_feerate", "The 10th percentile feerate"},
1877  {RPCResult::Type::NUM, "25th_percentile_feerate", "The 25th percentile feerate"},
1878  {RPCResult::Type::NUM, "50th_percentile_feerate", "The 50th percentile feerate"},
1879  {RPCResult::Type::NUM, "75th_percentile_feerate", "The 75th percentile feerate"},
1880  {RPCResult::Type::NUM, "90th_percentile_feerate", "The 90th percentile feerate"},
1881  }},
1882  {RPCResult::Type::NUM, "height", /*optional=*/true, "The height of the block"},
1883  {RPCResult::Type::NUM, "ins", /*optional=*/true, "The number of inputs (excluding coinbase)"},
1884  {RPCResult::Type::NUM, "maxfee", /*optional=*/true, "Maximum fee in the block"},
1885  {RPCResult::Type::NUM, "maxfeerate", /*optional=*/true, "Maximum feerate (in satoshis per virtual byte)"},
1886  {RPCResult::Type::NUM, "maxtxsize", /*optional=*/true, "Maximum transaction size"},
1887  {RPCResult::Type::NUM, "medianfee", /*optional=*/true, "Truncated median fee in the block"},
1888  {RPCResult::Type::NUM, "mediantime", /*optional=*/true, "The block median time past"},
1889  {RPCResult::Type::NUM, "mediantxsize", /*optional=*/true, "Truncated median transaction size"},
1890  {RPCResult::Type::NUM, "minfee", /*optional=*/true, "Minimum fee in the block"},
1891  {RPCResult::Type::NUM, "minfeerate", /*optional=*/true, "Minimum feerate (in satoshis per virtual byte)"},
1892  {RPCResult::Type::NUM, "mintxsize", /*optional=*/true, "Minimum transaction size"},
1893  {RPCResult::Type::NUM, "outs", /*optional=*/true, "The number of outputs"},
1894  {RPCResult::Type::NUM, "subsidy", /*optional=*/true, "The block subsidy"},
1895  {RPCResult::Type::NUM, "swtotal_size", /*optional=*/true, "Total size of all segwit transactions"},
1896  {RPCResult::Type::NUM, "swtotal_weight", /*optional=*/true, "Total weight of all segwit transactions"},
1897  {RPCResult::Type::NUM, "swtxs", /*optional=*/true, "The number of segwit transactions"},
1898  {RPCResult::Type::NUM, "time", /*optional=*/true, "The block time"},
1899  {RPCResult::Type::NUM, "total_out", /*optional=*/true, "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"},
1900  {RPCResult::Type::NUM, "total_size", /*optional=*/true, "Total size of all non-coinbase transactions"},
1901  {RPCResult::Type::NUM, "total_weight", /*optional=*/true, "Total weight of all non-coinbase transactions"},
1902  {RPCResult::Type::NUM, "totalfee", /*optional=*/true, "The fee total"},
1903  {RPCResult::Type::NUM, "txs", /*optional=*/true, "The number of transactions (including coinbase)"},
1904  {RPCResult::Type::NUM, "utxo_increase", /*optional=*/true, "The increase/decrease in the number of unspent outputs (not discounting op_return and similar)"},
1905  {RPCResult::Type::NUM, "utxo_size_inc", /*optional=*/true, "The increase/decrease in size for the utxo index (not discounting op_return and similar)"},
1906  {RPCResult::Type::NUM, "utxo_increase_actual", /*optional=*/true, "The increase/decrease in the number of unspent outputs, not counting unspendables"},
1907  {RPCResult::Type::NUM, "utxo_size_inc_actual", /*optional=*/true, "The increase/decrease in size for the utxo index, not counting unspendables"},
1908  }},
1909  RPCExamples{
1910  HelpExampleCli("getblockstats", R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") +
1911  HelpExampleCli("getblockstats", R"(1000 '["minfeerate","avgfeerate"]')") +
1912  HelpExampleRpc("getblockstats", R"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") +
1913  HelpExampleRpc("getblockstats", R"(1000, ["minfeerate","avgfeerate"])")
1914  },
1915  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
1916 {
1917  ChainstateManager& chainman = EnsureAnyChainman(request.context);
1918  const CBlockIndex& pindex{*CHECK_NONFATAL(ParseHashOrHeight(request.params[0], chainman))};
1919 
1920  std::set<std::string> stats;
1921  if (!request.params[1].isNull()) {
1922  const UniValue stats_univalue = request.params[1].get_array();
1923  for (unsigned int i = 0; i < stats_univalue.size(); i++) {
1924  const std::string stat = stats_univalue[i].get_str();
1925  stats.insert(stat);
1926  }
1927  }
1928 
1929  const CBlock& block = GetBlockChecked(chainman.m_blockman, pindex);
1930  const CBlockUndo& blockUndo = GetUndoChecked(chainman.m_blockman, pindex);
1931 
1932  const bool do_all = stats.size() == 0; // Calculate everything if nothing selected (default)
1933  const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0;
1934  const bool do_medianfee = do_all || stats.count("medianfee") != 0;
1935  const bool do_feerate_percentiles = do_all || stats.count("feerate_percentiles") != 0;
1936  const bool loop_inputs = do_all || do_medianfee || do_feerate_percentiles ||
1937  SetHasKeys(stats, "utxo_increase", "utxo_increase_actual", "utxo_size_inc", "utxo_size_inc_actual", "totalfee", "avgfee", "avgfeerate", "minfee", "maxfee", "minfeerate", "maxfeerate");
1938  const bool loop_outputs = do_all || loop_inputs || stats.count("total_out");
1939  const bool do_calculate_size = do_mediantxsize ||
1940  SetHasKeys(stats, "total_size", "avgtxsize", "mintxsize", "maxtxsize", "swtotal_size");
1941  const bool do_calculate_weight = do_all || SetHasKeys(stats, "total_weight", "avgfeerate", "swtotal_weight", "avgfeerate", "feerate_percentiles", "minfeerate", "maxfeerate");
1942  const bool do_calculate_sw = do_all || SetHasKeys(stats, "swtxs", "swtotal_size", "swtotal_weight");
1943 
1944  CAmount maxfee = 0;
1945  CAmount maxfeerate = 0;
1946  CAmount minfee = MAX_MONEY;
1947  CAmount minfeerate = MAX_MONEY;
1948  CAmount total_out = 0;
1949  CAmount totalfee = 0;
1950  int64_t inputs = 0;
1951  int64_t maxtxsize = 0;
1952  int64_t mintxsize = MAX_BLOCK_SERIALIZED_SIZE;
1953  int64_t outputs = 0;
1954  int64_t swtotal_size = 0;
1955  int64_t swtotal_weight = 0;
1956  int64_t swtxs = 0;
1957  int64_t total_size = 0;
1958  int64_t total_weight = 0;
1959  int64_t utxos = 0;
1960  int64_t utxo_size_inc = 0;
1961  int64_t utxo_size_inc_actual = 0;
1962  std::vector<CAmount> fee_array;
1963  std::vector<std::pair<CAmount, int64_t>> feerate_array;
1964  std::vector<int64_t> txsize_array;
1965 
1966  for (size_t i = 0; i < block.vtx.size(); ++i) {
1967  const auto& tx = block.vtx.at(i);
1968  outputs += tx->vout.size();
1969 
1970  CAmount tx_total_out = 0;
1971  if (loop_outputs) {
1972  for (const CTxOut& out : tx->vout) {
1973  tx_total_out += out.nValue;
1974 
1975  size_t out_size = GetSerializeSize(out) + PER_UTXO_OVERHEAD;
1976  utxo_size_inc += out_size;
1977 
1978  // The Genesis block and the repeated BIP30 block coinbases don't change the UTXO
1979  // set counts, so they have to be excluded from the statistics
1980  if (pindex.nHeight == 0 || (IsBIP30Repeat(pindex) && tx->IsCoinBase())) continue;
1981  // Skip unspendable outputs since they are not included in the UTXO set
1982  if (out.scriptPubKey.IsUnspendable()) continue;
1983 
1984  ++utxos;
1985  utxo_size_inc_actual += out_size;
1986  }
1987  }
1988 
1989  if (tx->IsCoinBase()) {
1990  continue;
1991  }
1992 
1993  inputs += tx->vin.size(); // Don't count coinbase's fake input
1994  total_out += tx_total_out; // Don't count coinbase reward
1995 
1996  int64_t tx_size = 0;
1997  if (do_calculate_size) {
1998 
1999  tx_size = tx->GetTotalSize();
2000  if (do_mediantxsize) {
2001  txsize_array.push_back(tx_size);
2002  }
2003  maxtxsize = std::max(maxtxsize, tx_size);
2004  mintxsize = std::min(mintxsize, tx_size);
2005  total_size += tx_size;
2006  }
2007 
2008  int64_t weight = 0;
2009  if (do_calculate_weight) {
2010  weight = GetTransactionWeight(*tx);
2011  total_weight += weight;
2012  }
2013 
2014  if (do_calculate_sw && tx->HasWitness()) {
2015  ++swtxs;
2016  swtotal_size += tx_size;
2017  swtotal_weight += weight;
2018  }
2019 
2020  if (loop_inputs) {
2021  CAmount tx_total_in = 0;
2022  const auto& txundo = blockUndo.vtxundo.at(i - 1);
2023  for (const Coin& coin: txundo.vprevout) {
2024  const CTxOut& prevoutput = coin.out;
2025 
2026  tx_total_in += prevoutput.nValue;
2027  size_t prevout_size = GetSerializeSize(prevoutput) + PER_UTXO_OVERHEAD;
2028  utxo_size_inc -= prevout_size;
2029  utxo_size_inc_actual -= prevout_size;
2030  }
2031 
2032  CAmount txfee = tx_total_in - tx_total_out;
2033  CHECK_NONFATAL(MoneyRange(txfee));
2034  if (do_medianfee) {
2035  fee_array.push_back(txfee);
2036  }
2037  maxfee = std::max(maxfee, txfee);
2038  minfee = std::min(minfee, txfee);
2039  totalfee += txfee;
2040 
2041  // New feerate uses satoshis per virtual byte instead of per serialized byte
2042  CAmount feerate = weight ? (txfee * WITNESS_SCALE_FACTOR) / weight : 0;
2043  if (do_feerate_percentiles) {
2044  feerate_array.emplace_back(feerate, weight);
2045  }
2046  maxfeerate = std::max(maxfeerate, feerate);
2047  minfeerate = std::min(minfeerate, feerate);
2048  }
2049  }
2050 
2051  CAmount feerate_percentiles[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
2052  CalculatePercentilesByWeight(feerate_percentiles, feerate_array, total_weight);
2053 
2054  UniValue feerates_res(UniValue::VARR);
2055  for (int64_t i = 0; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) {
2056  feerates_res.push_back(feerate_percentiles[i]);
2057  }
2058 
2059  UniValue ret_all(UniValue::VOBJ);
2060  ret_all.pushKV("avgfee", (block.vtx.size() > 1) ? totalfee / (block.vtx.size() - 1) : 0);
2061  ret_all.pushKV("avgfeerate", total_weight ? (totalfee * WITNESS_SCALE_FACTOR) / total_weight : 0); // Unit: sat/vbyte
2062  ret_all.pushKV("avgtxsize", (block.vtx.size() > 1) ? total_size / (block.vtx.size() - 1) : 0);
2063  ret_all.pushKV("blockhash", pindex.GetBlockHash().GetHex());
2064  ret_all.pushKV("feerate_percentiles", std::move(feerates_res));
2065  ret_all.pushKV("height", (int64_t)pindex.nHeight);
2066  ret_all.pushKV("ins", inputs);
2067  ret_all.pushKV("maxfee", maxfee);
2068  ret_all.pushKV("maxfeerate", maxfeerate);
2069  ret_all.pushKV("maxtxsize", maxtxsize);
2070  ret_all.pushKV("medianfee", CalculateTruncatedMedian(fee_array));
2071  ret_all.pushKV("mediantime", pindex.GetMedianTimePast());
2072  ret_all.pushKV("mediantxsize", CalculateTruncatedMedian(txsize_array));
2073  ret_all.pushKV("minfee", (minfee == MAX_MONEY) ? 0 : minfee);
2074  ret_all.pushKV("minfeerate", (minfeerate == MAX_MONEY) ? 0 : minfeerate);
2075  ret_all.pushKV("mintxsize", mintxsize == MAX_BLOCK_SERIALIZED_SIZE ? 0 : mintxsize);
2076  ret_all.pushKV("outs", outputs);
2077  ret_all.pushKV("subsidy", GetBlockSubsidy(pindex.nHeight, chainman.GetParams().GetConsensus()));
2078  ret_all.pushKV("swtotal_size", swtotal_size);
2079  ret_all.pushKV("swtotal_weight", swtotal_weight);
2080  ret_all.pushKV("swtxs", swtxs);
2081  ret_all.pushKV("time", pindex.GetBlockTime());
2082  ret_all.pushKV("total_out", total_out);
2083  ret_all.pushKV("total_size", total_size);
2084  ret_all.pushKV("total_weight", total_weight);
2085  ret_all.pushKV("totalfee", totalfee);
2086  ret_all.pushKV("txs", (int64_t)block.vtx.size());
2087  ret_all.pushKV("utxo_increase", outputs - inputs);
2088  ret_all.pushKV("utxo_size_inc", utxo_size_inc);
2089  ret_all.pushKV("utxo_increase_actual", utxos - inputs);
2090  ret_all.pushKV("utxo_size_inc_actual", utxo_size_inc_actual);
2091 
2092  if (do_all) {
2093  return ret_all;
2094  }
2095 
2097  for (const std::string& stat : stats) {
2098  const UniValue& value = ret_all[stat];
2099  if (value.isNull()) {
2100  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid selected statistic '%s'", stat));
2101  }
2102  ret.pushKV(stat, value);
2103  }
2104  return ret;
2105 },
2106  };
2107 }
2108 
2109 namespace {
2111 bool 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)
2112 {
2113  scan_progress = 0;
2114  count = 0;
2115  while (cursor->Valid()) {
2116  COutPoint key;
2117  Coin coin;
2118  if (!cursor->GetKey(key) || !cursor->GetValue(coin)) return false;
2119  if (++count % 8192 == 0) {
2120  interruption_point();
2121  if (should_abort) {
2122  // allow to abort the scan via the abort reference
2123  return false;
2124  }
2125  }
2126  if (count % 256 == 0) {
2127  // update progress reference every 256 item
2128  uint32_t high = 0x100 * *UCharCast(key.hash.begin()) + *(UCharCast(key.hash.begin()) + 1);
2129  scan_progress = (int)(high * 100.0 / 65536.0 + 0.5);
2130  }
2131  if (needles.count(coin.out.scriptPubKey)) {
2132  out_results.emplace(key, coin);
2133  }
2134  cursor->Next();
2135  }
2136  scan_progress = 100;
2137  return true;
2138 }
2139 } // namespace
2140 
2142 static std::atomic<int> g_scan_progress;
2143 static std::atomic<bool> g_scan_in_progress;
2144 static std::atomic<bool> g_should_abort_scan;
2146 {
2147 private:
2148  bool m_could_reserve{false};
2149 public:
2150  explicit CoinsViewScanReserver() = default;
2151 
2152  bool reserve() {
2154  if (g_scan_in_progress.exchange(true)) {
2155  return false;
2156  }
2158  m_could_reserve = true;
2159  return true;
2160  }
2161 
2163  if (m_could_reserve) {
2164  g_scan_in_progress = false;
2165  g_scan_progress = 0;
2166  }
2167  }
2168 };
2169 
2170 static const auto scan_action_arg_desc = RPCArg{
2171  "action", RPCArg::Type::STR, RPCArg::Optional::NO, "The action to execute\n"
2172  "\"start\" for starting a scan\n"
2173  "\"abort\" for aborting the current scan (returns true when abort was successful)\n"
2174  "\"status\" for progress report (in %) of the current scan"
2175 };
2176 
2177 static const auto scan_objects_arg_desc = RPCArg{
2178  "scanobjects", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Array of scan objects. Required for \"start\" action\n"
2179  "Every scan object is either a string descriptor or an object:",
2180  {
2181  {"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
2182  {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with output descriptor and metadata",
2183  {
2184  {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"},
2185  {"range", RPCArg::Type::RANGE, RPCArg::Default{1000}, "The range of HD chain indexes to explore (either end or [begin,end])"},
2186  }},
2187  },
2188  RPCArgOptions{.oneline_description="[scanobjects,...]"},
2189 };
2190 
2191 static const auto scan_result_abort = RPCResult{
2192  "when action=='abort'", RPCResult::Type::BOOL, "success",
2193  "True if scan will be aborted (not necessarily before this RPC returns), or false if there is no scan to abort"
2194 };
2196  "when action=='status' and no scan is in progress - possibly already completed", RPCResult::Type::NONE, "", ""
2197 };
2199  "when action=='status' and a scan is currently in progress", RPCResult::Type::OBJ, "", "",
2200  {{RPCResult::Type::NUM, "progress", "Approximate percent complete"},}
2201 };
2202 
2203 
2205 {
2206  // raw() descriptor corresponding to mainnet address 12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S
2207  const std::string EXAMPLE_DESCRIPTOR_RAW = "raw(76a91411b366edfc0a8b66feebae5c2e25a7b6a5d1cf3188ac)#fm24fxxy";
2208 
2209  return RPCHelpMan{"scantxoutset",
2210  "\nScans the unspent transaction output set for entries that match certain output descriptors.\n"
2211  "Examples of output descriptors are:\n"
2212  " addr(<address>) Outputs whose output script corresponds to the specified address (does not include P2PK)\n"
2213  " raw(<hex script>) Outputs whose output script equals the specified hex-encoded bytes\n"
2214  " combo(<pubkey>) P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH outputs for the given pubkey\n"
2215  " pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
2216  " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
2217  " tr(<pubkey>) P2TR\n"
2218  " tr(<pubkey>,{pk(<pubkey>)}) P2TR with single fallback pubkey in tapscript\n"
2219  " rawtr(<pubkey>) P2TR with the specified key as output key rather than inner\n"
2220  " wsh(and_v(v:pk(<pubkey>),after(2))) P2WSH miniscript with mandatory pubkey and a timelock\n"
2221  "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
2222  "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
2223  "unhardened or hardened child keys.\n"
2224  "In the latter case, a range needs to be specified by below if different from 1000.\n"
2225  "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n",
2226  {
2229  },
2230  {
2231  RPCResult{"when action=='start'; only returns after scan completes", RPCResult::Type::OBJ, "", "", {
2232  {RPCResult::Type::BOOL, "success", "Whether the scan was completed"},
2233  {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs scanned"},
2234  {RPCResult::Type::NUM, "height", "The block height at which the scan was done"},
2235  {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
2236  {RPCResult::Type::ARR, "unspents", "",
2237  {
2238  {RPCResult::Type::OBJ, "", "",
2239  {
2240  {RPCResult::Type::STR_HEX, "txid", "The transaction id"},
2241  {RPCResult::Type::NUM, "vout", "The vout value"},
2242  {RPCResult::Type::STR_HEX, "scriptPubKey", "The output script"},
2243  {RPCResult::Type::STR, "desc", "A specialized descriptor for the matched output script"},
2244  {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the unspent output"},
2245  {RPCResult::Type::BOOL, "coinbase", "Whether this is a coinbase output"},
2246  {RPCResult::Type::NUM, "height", "Height of the unspent transaction output"},
2247  {RPCResult::Type::STR_HEX, "blockhash", "Blockhash of the unspent transaction output"},
2248  {RPCResult::Type::NUM, "confirmations", "Number of confirmations of the unspent transaction output when the scan was done"},
2249  }},
2250  }},
2251  {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT},
2252  }},
2256  },
2257  RPCExamples{
2258  HelpExampleCli("scantxoutset", "start \'[\"" + EXAMPLE_DESCRIPTOR_RAW + "\"]\'") +
2259  HelpExampleCli("scantxoutset", "status") +
2260  HelpExampleCli("scantxoutset", "abort") +
2261  HelpExampleRpc("scantxoutset", "\"start\", [\"" + EXAMPLE_DESCRIPTOR_RAW + "\"]") +
2262  HelpExampleRpc("scantxoutset", "\"status\"") +
2263  HelpExampleRpc("scantxoutset", "\"abort\"")
2264  },
2265  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
2266 {
2268  const auto action{self.Arg<std::string>("action")};
2269  if (action == "status") {
2270  CoinsViewScanReserver reserver;
2271  if (reserver.reserve()) {
2272  // no scan in progress
2273  return UniValue::VNULL;
2274  }
2275  result.pushKV("progress", g_scan_progress.load());
2276  return result;
2277  } else if (action == "abort") {
2278  CoinsViewScanReserver reserver;
2279  if (reserver.reserve()) {
2280  // reserve was possible which means no scan was running
2281  return false;
2282  }
2283  // set the abort flag
2284  g_should_abort_scan = true;
2285  return true;
2286  } else if (action == "start") {
2287  CoinsViewScanReserver reserver;
2288  if (!reserver.reserve()) {
2289  throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
2290  }
2291 
2292  if (request.params.size() < 2) {
2293  throw JSONRPCError(RPC_MISC_ERROR, "scanobjects argument is required for the start action");
2294  }
2295 
2296  std::set<CScript> needles;
2297  std::map<CScript, std::string> descriptors;
2298  CAmount total_in = 0;
2299 
2300  // loop through the scan objects
2301  for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
2302  FlatSigningProvider provider;
2303  auto scripts = EvalDescriptorStringOrObject(scanobject, provider);
2304  for (CScript& script : scripts) {
2305  std::string inferred = InferDescriptor(script, provider)->ToString();
2306  needles.emplace(script);
2307  descriptors.emplace(std::move(script), std::move(inferred));
2308  }
2309  }
2310 
2311  // Scan the unspent transaction output set for inputs
2312  UniValue unspents(UniValue::VARR);
2313  std::vector<CTxOut> input_txos;
2314  std::map<COutPoint, Coin> coins;
2315  g_should_abort_scan = false;
2316  int64_t count = 0;
2317  std::unique_ptr<CCoinsViewCursor> pcursor;
2318  const CBlockIndex* tip;
2319  NodeContext& node = EnsureAnyNodeContext(request.context);
2320  {
2321  ChainstateManager& chainman = EnsureChainman(node);
2322  LOCK(cs_main);
2323  Chainstate& active_chainstate = chainman.ActiveChainstate();
2324  active_chainstate.ForceFlushStateToDisk();
2325  pcursor = CHECK_NONFATAL(active_chainstate.CoinsDB().Cursor());
2326  tip = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
2327  }
2328  bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins, node.rpc_interruption_point);
2329  result.pushKV("success", res);
2330  result.pushKV("txouts", count);
2331  result.pushKV("height", tip->nHeight);
2332  result.pushKV("bestblock", tip->GetBlockHash().GetHex());
2333 
2334  for (const auto& it : coins) {
2335  const COutPoint& outpoint = it.first;
2336  const Coin& coin = it.second;
2337  const CTxOut& txo = coin.out;
2338  const CBlockIndex& coinb_block{*CHECK_NONFATAL(tip->GetAncestor(coin.nHeight))};
2339  input_txos.push_back(txo);
2340  total_in += txo.nValue;
2341 
2342  UniValue unspent(UniValue::VOBJ);
2343  unspent.pushKV("txid", outpoint.hash.GetHex());
2344  unspent.pushKV("vout", outpoint.n);
2345  unspent.pushKV("scriptPubKey", HexStr(txo.scriptPubKey));
2346  unspent.pushKV("desc", descriptors[txo.scriptPubKey]);
2347  unspent.pushKV("amount", ValueFromAmount(txo.nValue));
2348  unspent.pushKV("coinbase", coin.IsCoinBase());
2349  unspent.pushKV("height", coin.nHeight);
2350  unspent.pushKV("blockhash", coinb_block.GetBlockHash().GetHex());
2351  unspent.pushKV("confirmations", tip->nHeight - coin.nHeight + 1);
2352 
2353  unspents.push_back(std::move(unspent));
2354  }
2355  result.pushKV("unspents", std::move(unspents));
2356  result.pushKV("total_amount", ValueFromAmount(total_in));
2357  } else {
2358  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", action));
2359  }
2360  return result;
2361 },
2362  };
2363 }
2364 
2366 static std::atomic<int> g_scanfilter_progress;
2367 static std::atomic<int> g_scanfilter_progress_height;
2368 static std::atomic<bool> g_scanfilter_in_progress;
2369 static std::atomic<bool> g_scanfilter_should_abort_scan;
2371 {
2372 private:
2373  bool m_could_reserve{false};
2374 public:
2375  explicit BlockFiltersScanReserver() = default;
2376 
2377  bool reserve() {
2379  if (g_scanfilter_in_progress.exchange(true)) {
2380  return false;
2381  }
2382  m_could_reserve = true;
2383  return true;
2384  }
2385 
2387  if (m_could_reserve) {
2388  g_scanfilter_in_progress = false;
2389  }
2390  }
2391 };
2392 
2393 static bool CheckBlockFilterMatches(BlockManager& blockman, const CBlockIndex& blockindex, const GCSFilter::ElementSet& needles)
2394 {
2395  const CBlock block{GetBlockChecked(blockman, blockindex)};
2396  const CBlockUndo block_undo{GetUndoChecked(blockman, blockindex)};
2397 
2398  // Check if any of the outputs match the scriptPubKey
2399  for (const auto& tx : block.vtx) {
2400  if (std::any_of(tx->vout.cbegin(), tx->vout.cend(), [&](const auto& txout) {
2401  return needles.count(std::vector<unsigned char>(txout.scriptPubKey.begin(), txout.scriptPubKey.end())) != 0;
2402  })) {
2403  return true;
2404  }
2405  }
2406  // Check if any of the inputs match the scriptPubKey
2407  for (const auto& txundo : block_undo.vtxundo) {
2408  if (std::any_of(txundo.vprevout.cbegin(), txundo.vprevout.cend(), [&](const auto& coin) {
2409  return needles.count(std::vector<unsigned char>(coin.out.scriptPubKey.begin(), coin.out.scriptPubKey.end())) != 0;
2410  })) {
2411  return true;
2412  }
2413  }
2414 
2415  return false;
2416 }
2417 
2419 {
2420  return RPCHelpMan{"scanblocks",
2421  "\nReturn relevant blockhashes for given descriptors (requires blockfilterindex).\n"
2422  "This call may take several minutes. Make sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
2423  {
2426  RPCArg{"start_height", RPCArg::Type::NUM, RPCArg::Default{0}, "Height to start to scan from"},
2427  RPCArg{"stop_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"chain tip"}, "Height to stop to scan"},
2428  RPCArg{"filtertype", RPCArg::Type::STR, RPCArg::Default{BlockFilterTypeName(BlockFilterType::BASIC)}, "The type name of the filter"},
2430  {
2431  {"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"},
2432  },
2433  RPCArgOptions{.oneline_description="options"}},
2434  },
2435  {
2437  RPCResult{"When action=='start'; only returns after scan completes", RPCResult::Type::OBJ, "", "", {
2438  {RPCResult::Type::NUM, "from_height", "The height we started the scan from"},
2439  {RPCResult::Type::NUM, "to_height", "The height we ended the scan at"},
2440  {RPCResult::Type::ARR, "relevant_blocks", "Blocks that may have matched a scanobject.", {
2441  {RPCResult::Type::STR_HEX, "blockhash", "A relevant blockhash"},
2442  }},
2443  {RPCResult::Type::BOOL, "completed", "true if the scan process was not aborted"}
2444  }},
2445  RPCResult{"when action=='status' and a scan is currently in progress", RPCResult::Type::OBJ, "", "", {
2446  {RPCResult::Type::NUM, "progress", "Approximate percent complete"},
2447  {RPCResult::Type::NUM, "current_height", "Height of the block currently being scanned"},
2448  },
2449  },
2451  },
2452  RPCExamples{
2453  HelpExampleCli("scanblocks", "start '[\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"]' 300000") +
2454  HelpExampleCli("scanblocks", "start '[\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"]' 100 150 basic") +
2455  HelpExampleCli("scanblocks", "status") +
2456  HelpExampleRpc("scanblocks", "\"start\", [\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"], 300000") +
2457  HelpExampleRpc("scanblocks", "\"start\", [\"addr(bcrt1q4u4nsgk6ug0sqz7r3rj9tykjxrsl0yy4d0wwte)\"], 100, 150, \"basic\"") +
2458  HelpExampleRpc("scanblocks", "\"status\"")
2459  },
2460  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
2461 {
2463  if (request.params[0].get_str() == "status") {
2464  BlockFiltersScanReserver reserver;
2465  if (reserver.reserve()) {
2466  // no scan in progress
2467  return NullUniValue;
2468  }
2469  ret.pushKV("progress", g_scanfilter_progress.load());
2470  ret.pushKV("current_height", g_scanfilter_progress_height.load());
2471  return ret;
2472  } else if (request.params[0].get_str() == "abort") {
2473  BlockFiltersScanReserver reserver;
2474  if (reserver.reserve()) {
2475  // reserve was possible which means no scan was running
2476  return false;
2477  }
2478  // set the abort flag
2480  return true;
2481  } else if (request.params[0].get_str() == "start") {
2482  BlockFiltersScanReserver reserver;
2483  if (!reserver.reserve()) {
2484  throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
2485  }
2486  const std::string filtertype_name{request.params[4].isNull() ? "basic" : request.params[4].get_str()};
2487 
2488  BlockFilterType filtertype;
2489  if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
2490  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown filtertype");
2491  }
2492 
2493  UniValue options{request.params[5].isNull() ? UniValue::VOBJ : request.params[5]};
2494  bool filter_false_positives{options.exists("filter_false_positives") ? options["filter_false_positives"].get_bool() : false};
2495 
2496  BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
2497  if (!index) {
2498  throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name);
2499  }
2500 
2501  NodeContext& node = EnsureAnyNodeContext(request.context);
2502  ChainstateManager& chainman = EnsureChainman(node);
2503 
2504  // set the start-height
2505  const CBlockIndex* start_index = nullptr;
2506  const CBlockIndex* stop_block = nullptr;
2507  {
2508  LOCK(cs_main);
2509  CChain& active_chain = chainman.ActiveChain();
2510  start_index = active_chain.Genesis();
2511  stop_block = active_chain.Tip(); // If no stop block is provided, stop at the chain tip.
2512  if (!request.params[2].isNull()) {
2513  start_index = active_chain[request.params[2].getInt<int>()];
2514  if (!start_index) {
2515  throw JSONRPCError(RPC_MISC_ERROR, "Invalid start_height");
2516  }
2517  }
2518  if (!request.params[3].isNull()) {
2519  stop_block = active_chain[request.params[3].getInt<int>()];
2520  if (!stop_block || stop_block->nHeight < start_index->nHeight) {
2521  throw JSONRPCError(RPC_MISC_ERROR, "Invalid stop_height");
2522  }
2523  }
2524  }
2525  CHECK_NONFATAL(start_index);
2526  CHECK_NONFATAL(stop_block);
2527 
2528  // loop through the scan objects, add scripts to the needle_set
2529  GCSFilter::ElementSet needle_set;
2530  for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
2531  FlatSigningProvider provider;
2532  std::vector<CScript> scripts = EvalDescriptorStringOrObject(scanobject, provider);
2533  for (const CScript& script : scripts) {
2534  needle_set.emplace(script.begin(), script.end());
2535  }
2536  }
2537  UniValue blocks(UniValue::VARR);
2538  const int amount_per_chunk = 10000;
2539  std::vector<BlockFilter> filters;
2540  int start_block_height = start_index->nHeight; // for progress reporting
2541  const int total_blocks_to_process = stop_block->nHeight - start_block_height;
2542 
2545  g_scanfilter_progress_height = start_block_height;
2546  bool completed = true;
2547 
2548  const CBlockIndex* end_range = nullptr;
2549  do {
2550  node.rpc_interruption_point(); // allow a clean shutdown
2552  completed = false;
2553  break;
2554  }
2555 
2556  // split the lookup range in chunks if we are deeper than 'amount_per_chunk' blocks from the stopping block
2557  int start_block = !end_range ? start_index->nHeight : start_index->nHeight + 1; // to not include the previous round 'end_range' block
2558  end_range = (start_block + amount_per_chunk < stop_block->nHeight) ?
2559  WITH_LOCK(::cs_main, return chainman.ActiveChain()[start_block + amount_per_chunk]) :
2560  stop_block;
2561 
2562  if (index->LookupFilterRange(start_block, end_range, filters)) {
2563  for (const BlockFilter& filter : filters) {
2564  // compare the elements-set with each filter
2565  if (filter.GetFilter().MatchAny(needle_set)) {
2566  if (filter_false_positives) {
2567  // Double check the filter matches by scanning the block
2568  const CBlockIndex& blockindex = *CHECK_NONFATAL(WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(filter.GetBlockHash())));
2569 
2570  if (!CheckBlockFilterMatches(chainman.m_blockman, blockindex, needle_set)) {
2571  continue;
2572  }
2573  }
2574 
2575  blocks.push_back(filter.GetBlockHash().GetHex());
2576  }
2577  }
2578  }
2579  start_index = end_range;
2580 
2581  // update progress
2582  int blocks_processed = end_range->nHeight - start_block_height;
2583  if (total_blocks_to_process > 0) { // avoid division by zero
2584  g_scanfilter_progress = (int)(100.0 / total_blocks_to_process * blocks_processed);
2585  } else {
2586  g_scanfilter_progress = 100;
2587  }
2589 
2590  // Finish if we reached the stop block
2591  } while (start_index != stop_block);
2592 
2593  ret.pushKV("from_height", start_block_height);
2594  ret.pushKV("to_height", start_index->nHeight); // start_index is always the last scanned block here
2595  ret.pushKV("relevant_blocks", std::move(blocks));
2596  ret.pushKV("completed", completed);
2597  }
2598  else {
2599  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", request.params[0].get_str()));
2600  }
2601  return ret;
2602 },
2603  };
2604 }
2605 
2607 {
2608  return RPCHelpMan{"getdescriptoractivity",
2609  "\nGet spend and receive activity associated with a set of descriptors for a set of blocks. "
2610  "This command pairs well with the `relevant_blocks` output of `scanblocks()`.\n"
2611  "This call may take several minutes. If you encounter timeouts, try specifying no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
2612  {
2613  RPCArg{"blockhashes", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The list of blockhashes to examine for activity. Order doesn't matter. Must be along main chain or an error is thrown.\n", {
2614  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A valid blockhash"},
2615  }},
2617  {"include_mempool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to include unconfirmed activity"},
2618  },
2619  RPCResult{
2620  RPCResult::Type::OBJ, "", "", {
2621  {RPCResult::Type::ARR, "activity", "events", {
2622  {RPCResult::Type::OBJ, "", "", {
2623  {RPCResult::Type::STR, "type", "always 'spend'"},
2624  {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the spent output"},
2625  {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The blockhash this spend appears in (omitted if unconfirmed)"},
2626  {RPCResult::Type::NUM, "height", /*optional=*/true, "Height of the spend (omitted if unconfirmed)"},
2627  {RPCResult::Type::STR_HEX, "spend_txid", "The txid of the spending transaction"},
2628  {RPCResult::Type::NUM, "spend_vin", "The input index of the spend"},
2629  {RPCResult::Type::STR_HEX, "prevout_txid", "The txid of the prevout"},
2630  {RPCResult::Type::NUM, "prevout_vout", "The vout of the prevout"},
2631  {RPCResult::Type::OBJ, "prevout_spk", "", ScriptPubKeyDoc()},
2632  }},
2633  {RPCResult::Type::OBJ, "", "", {
2634  {RPCResult::Type::STR, "type", "always 'receive'"},
2635  {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the new output"},
2636  {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block that this receive is in (omitted if unconfirmed)"},
2637  {RPCResult::Type::NUM, "height", /*optional=*/true, "The height of the receive (omitted if unconfirmed)"},
2638  {RPCResult::Type::STR_HEX, "txid", "The txid of the receiving transaction"},
2639  {RPCResult::Type::NUM, "vout", "The vout of the receiving output"},
2640  {RPCResult::Type::OBJ, "output_spk", "", ScriptPubKeyDoc()},
2641  }},
2642  // TODO is the skip_type_check avoidable with a heterogeneous ARR?
2643  }, /*skip_type_check=*/true},
2644  },
2645  },
2646  RPCExamples{
2647  HelpExampleCli("getdescriptoractivity", "'[\"000000000000000000001347062c12fded7c528943c8ce133987e2e2f5a840ee\"]' '[\"addr(bc1qzl6nsgqzu89a66l50cvwapnkw5shh23zarqkw9)\"]'")
2648  },
2649  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
2650 {
2652  UniValue activity(UniValue::VARR);
2653  NodeContext& node = EnsureAnyNodeContext(request.context);
2654  ChainstateManager& chainman = EnsureChainman(node);
2655 
2656  struct CompareByHeightAscending {
2657  bool operator()(const CBlockIndex* a, const CBlockIndex* b) const {
2658  return a->nHeight < b->nHeight;
2659  }
2660  };
2661 
2662  std::set<const CBlockIndex*, CompareByHeightAscending> blockindexes_sorted;
2663 
2664  {
2665  // Validate all given blockhashes, and ensure blocks are along a single chain.
2666  LOCK(::cs_main);
2667  for (const UniValue& blockhash : request.params[0].get_array().getValues()) {
2668  uint256 bhash = ParseHashV(blockhash, "blockhash");
2669  CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(bhash);
2670  if (!pindex) {
2671  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
2672  }
2673  if (!chainman.ActiveChain().Contains(pindex)) {
2674  throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain");
2675  }
2676  blockindexes_sorted.insert(pindex);
2677  }
2678  }
2679 
2680  std::set<CScript> scripts_to_watch;
2681 
2682  // Determine scripts to watch.
2683  for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
2684  FlatSigningProvider provider;
2685  std::vector<CScript> scripts = EvalDescriptorStringOrObject(scanobject, provider);
2686 
2687  for (const CScript& script : scripts) {
2688  scripts_to_watch.insert(script);
2689  }
2690  }
2691 
2692  const auto AddSpend = [&](
2693  const CScript& spk,
2694  const CAmount val,
2695  const CTransactionRef& tx,
2696  int vin,
2697  const CTxIn& txin,
2698  const CBlockIndex* index
2699  ) {
2700  UniValue event(UniValue::VOBJ);
2701  UniValue spkUv(UniValue::VOBJ);
2702  ScriptToUniv(spk, /*out=*/spkUv, /*include_hex=*/true, /*include_address=*/true);
2703 
2704  event.pushKV("type", "spend");
2705  event.pushKV("amount", ValueFromAmount(val));
2706  if (index) {
2707  event.pushKV("blockhash", index->GetBlockHash().ToString());
2708  event.pushKV("height", index->nHeight);
2709  }
2710  event.pushKV("spend_txid", tx->GetHash().ToString());
2711  event.pushKV("spend_vin", vin);
2712  event.pushKV("prevout_txid", txin.prevout.hash.ToString());
2713  event.pushKV("prevout_vout", txin.prevout.n);
2714  event.pushKV("prevout_spk", spkUv);
2715 
2716  return event;
2717  };
2718 
2719  const auto AddReceive = [&](const CTxOut& txout, const CBlockIndex* index, int vout, const CTransactionRef& tx) {
2720  UniValue event(UniValue::VOBJ);
2721  UniValue spkUv(UniValue::VOBJ);
2722  ScriptToUniv(txout.scriptPubKey, /*out=*/spkUv, /*include_hex=*/true, /*include_address=*/true);
2723 
2724  event.pushKV("type", "receive");
2725  event.pushKV("amount", ValueFromAmount(txout.nValue));
2726  if (index) {
2727  event.pushKV("blockhash", index->GetBlockHash().ToString());
2728  event.pushKV("height", index->nHeight);
2729  }
2730  event.pushKV("txid", tx->GetHash().ToString());
2731  event.pushKV("vout", vout);
2732  event.pushKV("output_spk", spkUv);
2733 
2734  return event;
2735  };
2736 
2737  BlockManager* blockman;
2738  Chainstate& active_chainstate = chainman.ActiveChainstate();
2739  {
2740  LOCK(::cs_main);
2741  blockman = CHECK_NONFATAL(&active_chainstate.m_blockman);
2742  }
2743 
2744  for (const CBlockIndex* blockindex : blockindexes_sorted) {
2745  const CBlock block{GetBlockChecked(chainman.m_blockman, *blockindex)};
2746  const CBlockUndo block_undo{GetUndoChecked(*blockman, *blockindex)};
2747 
2748  for (size_t i = 0; i < block.vtx.size(); ++i) {
2749  const auto& tx = block.vtx.at(i);
2750 
2751  if (!tx->IsCoinBase()) {
2752  // skip coinbase; spends can't happen there.
2753  const auto& txundo = block_undo.vtxundo.at(i - 1);
2754 
2755  for (size_t vin_idx = 0; vin_idx < tx->vin.size(); ++vin_idx) {
2756  const auto& coin = txundo.vprevout.at(vin_idx);
2757  const auto& txin = tx->vin.at(vin_idx);
2758  if (scripts_to_watch.contains(coin.out.scriptPubKey)) {
2759  activity.push_back(AddSpend(
2760  coin.out.scriptPubKey, coin.out.nValue, tx, vin_idx, txin, blockindex));
2761  }
2762  }
2763  }
2764 
2765  for (size_t vout_idx = 0; vout_idx < tx->vout.size(); ++vout_idx) {
2766  const auto& vout = tx->vout.at(vout_idx);
2767  if (scripts_to_watch.contains(vout.scriptPubKey)) {
2768  activity.push_back(AddReceive(vout, blockindex, vout_idx, tx));
2769  }
2770  }
2771  }
2772  }
2773 
2774  bool search_mempool = true;
2775  if (!request.params[2].isNull()) {
2776  search_mempool = request.params[2].get_bool();
2777  }
2778 
2779  if (search_mempool) {
2780  const CTxMemPool& mempool = EnsureMemPool(node);
2781  LOCK(::cs_main);
2782  LOCK(mempool.cs);
2783  const CCoinsViewCache& coins_view = &active_chainstate.CoinsTip();
2784 
2785  for (const CTxMemPoolEntry& e : mempool.entryAll()) {
2786  const auto& tx = e.GetSharedTx();
2787 
2788  for (size_t vin_idx = 0; vin_idx < tx->vin.size(); ++vin_idx) {
2789  CScript scriptPubKey;
2790  CAmount value;
2791  const auto& txin = tx->vin.at(vin_idx);
2792  std::optional<Coin> coin = coins_view.GetCoin(txin.prevout);
2793 
2794  // Check if the previous output is in the chain
2795  if (!coin) {
2796  // If not found in the chain, check the mempool. Likely, this is a
2797  // child transaction of another transaction in the mempool.
2798  CTransactionRef prev_tx = CHECK_NONFATAL(mempool.get(txin.prevout.hash));
2799 
2800  if (txin.prevout.n >= prev_tx->vout.size()) {
2801  throw std::runtime_error("Invalid output index");
2802  }
2803  const CTxOut& out = prev_tx->vout[txin.prevout.n];
2804  scriptPubKey = out.scriptPubKey;
2805  value = out.nValue;
2806  } else {
2807  // Coin found in the chain
2808  const CTxOut& out = coin->out;
2809  scriptPubKey = out.scriptPubKey;
2810  value = out.nValue;
2811  }
2812 
2813  if (scripts_to_watch.contains(scriptPubKey)) {
2814  UniValue event(UniValue::VOBJ);
2815  activity.push_back(AddSpend(
2816  scriptPubKey, value, tx, vin_idx, txin, nullptr));
2817  }
2818  }
2819 
2820  for (size_t vout_idx = 0; vout_idx < tx->vout.size(); ++vout_idx) {
2821  const auto& vout = tx->vout.at(vout_idx);
2822  if (scripts_to_watch.contains(vout.scriptPubKey)) {
2823  activity.push_back(AddReceive(vout, nullptr, vout_idx, tx));
2824  }
2825  }
2826  }
2827  }
2828 
2829  ret.pushKV("activity", activity);
2830  return ret;
2831 },
2832  };
2833 }
2834 
2836 {
2837  return RPCHelpMan{"getblockfilter",
2838  "\nRetrieve a BIP 157 content filter for a particular block.\n",
2839  {
2840  {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hash of the block"},
2841  {"filtertype", RPCArg::Type::STR, RPCArg::Default{BlockFilterTypeName(BlockFilterType::BASIC)}, "The type name of the filter"},
2842  },
2843  RPCResult{
2844  RPCResult::Type::OBJ, "", "",
2845  {
2846  {RPCResult::Type::STR_HEX, "filter", "the hex-encoded filter data"},
2847  {RPCResult::Type::STR_HEX, "header", "the hex-encoded filter header"},
2848  }},
2849  RPCExamples{
2850  HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") +
2851  HelpExampleRpc("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\", \"basic\"")
2852  },
2853  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
2854 {
2855  uint256 block_hash = ParseHashV(request.params[0], "blockhash");
2856  std::string filtertype_name = BlockFilterTypeName(BlockFilterType::BASIC);
2857  if (!request.params[1].isNull()) {
2858  filtertype_name = request.params[1].get_str();
2859  }
2860 
2861  BlockFilterType filtertype;
2862  if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
2863  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown filtertype");
2864  }
2865 
2866  BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
2867  if (!index) {
2868  throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name);
2869  }
2870 
2871  const CBlockIndex* block_index;
2872  bool block_was_connected;
2873  {
2874  ChainstateManager& chainman = EnsureAnyChainman(request.context);
2875  LOCK(cs_main);
2876  block_index = chainman.m_blockman.LookupBlockIndex(block_hash);
2877  if (!block_index) {
2878  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
2879  }
2880  block_was_connected = block_index->IsValid(BLOCK_VALID_SCRIPTS);
2881  }
2882 
2883  bool index_ready = index->BlockUntilSyncedToCurrentChain();
2884 
2885  BlockFilter filter;
2886  uint256 filter_header;
2887  if (!index->LookupFilter(block_index, filter) ||
2888  !index->LookupFilterHeader(block_index, filter_header)) {
2889  int err_code;
2890  std::string errmsg = "Filter not found.";
2891 
2892  if (!block_was_connected) {
2893  err_code = RPC_INVALID_ADDRESS_OR_KEY;
2894  errmsg += " Block was not connected to active chain.";
2895  } else if (!index_ready) {
2896  err_code = RPC_MISC_ERROR;
2897  errmsg += " Block filters are still in the process of being indexed.";
2898  } else {
2899  err_code = RPC_INTERNAL_ERROR;
2900  errmsg += " This error is unexpected and indicates index corruption.";
2901  }
2902 
2903  throw JSONRPCError(err_code, errmsg);
2904  }
2905 
2907  ret.pushKV("filter", HexStr(filter.GetEncodedFilter()));
2908  ret.pushKV("header", filter_header.GetHex());
2909  return ret;
2910 },
2911  };
2912 }
2913 
2919 {
2921 public:
2922  NetworkDisable(CConnman& connman) : m_connman(connman) {
2923  m_connman.SetNetworkActive(false);
2924  if (m_connman.GetNetworkActive()) {
2925  throw JSONRPCError(RPC_MISC_ERROR, "Network activity could not be suspended.");
2926  }
2927  };
2930  };
2931 };
2932 
2938 {
2941 public:
2942  TemporaryRollback(ChainstateManager& chainman, const CBlockIndex& index) : m_chainman(chainman), m_invalidate_index(index) {
2944  };
2947  };
2948 };
2949 
2956 {
2957  return RPCHelpMan{
2958  "dumptxoutset",
2959  "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\n"
2960  "Unless the \"latest\" type is requested, the node will roll back to the requested height and network activity will be suspended during this process. "
2961  "Because of this it is discouraged to interact with the node in any other way during the execution of this call to avoid inconsistent results and race conditions, particularly RPCs that interact with blockstorage.\n\n"
2962  "This call may take several minutes. Make sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
2963  {
2964  {"path", RPCArg::Type::STR, RPCArg::Optional::NO, "Path to the output file. If relative, will be prefixed by datadir."},
2965  {"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."},
2967  {
2969  "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.",
2970  RPCArgOptions{.skip_type_check = true, .type_str = {"", "string or numeric"}}},
2971  },
2972  },
2973  },
2974  RPCResult{
2975  RPCResult::Type::OBJ, "", "",
2976  {
2977  {RPCResult::Type::NUM, "coins_written", "the number of coins written in the snapshot"},
2978  {RPCResult::Type::STR_HEX, "base_hash", "the hash of the base of the snapshot"},
2979  {RPCResult::Type::NUM, "base_height", "the height of the base of the snapshot"},
2980  {RPCResult::Type::STR, "path", "the absolute path that the snapshot was written to"},
2981  {RPCResult::Type::STR_HEX, "txoutset_hash", "the hash of the UTXO set contents"},
2982  {RPCResult::Type::NUM, "nchaintx", "the number of transactions in the chain up to and including the base block"},
2983  }
2984  },
2985  RPCExamples{
2986  HelpExampleCli("-rpcclienttimeout=0 dumptxoutset", "utxo.dat latest") +
2987  HelpExampleCli("-rpcclienttimeout=0 dumptxoutset", "utxo.dat rollback") +
2988  HelpExampleCli("-rpcclienttimeout=0 -named dumptxoutset", R"(utxo.dat rollback=853456)")
2989  },
2990  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
2991 {
2992  NodeContext& node = EnsureAnyNodeContext(request.context);
2993  const CBlockIndex* tip{WITH_LOCK(::cs_main, return node.chainman->ActiveChain().Tip())};
2994  const CBlockIndex* target_index{nullptr};
2995  const std::string snapshot_type{self.Arg<std::string>("type")};
2996  const UniValue options{request.params[2].isNull() ? UniValue::VOBJ : request.params[2]};
2997  if (options.exists("rollback")) {
2998  if (!snapshot_type.empty() && snapshot_type != "rollback") {
2999  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid snapshot type \"%s\" specified with rollback option", snapshot_type));
3000  }
3001  target_index = ParseHashOrHeight(options["rollback"], *node.chainman);
3002  } else if (snapshot_type == "rollback") {
3003  auto snapshot_heights = node.chainman->GetParams().GetAvailableSnapshotHeights();
3004  CHECK_NONFATAL(snapshot_heights.size() > 0);
3005  auto max_height = std::max_element(snapshot_heights.begin(), snapshot_heights.end());
3006  target_index = ParseHashOrHeight(*max_height, *node.chainman);
3007  } else if (snapshot_type == "latest") {
3008  target_index = tip;
3009  } else {
3010  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid snapshot type \"%s\" specified. Please specify \"rollback\" or \"latest\"", snapshot_type));
3011  }
3012 
3013  const ArgsManager& args{EnsureAnyArgsman(request.context)};
3014  const fs::path path = fsbridge::AbsPathJoin(args.GetDataDirNet(), fs::u8path(request.params[0].get_str()));
3015  // Write to a temporary path and then move into `path` on completion
3016  // to avoid confusion due to an interruption.
3017  const fs::path temppath = fsbridge::AbsPathJoin(args.GetDataDirNet(), fs::u8path(request.params[0].get_str() + ".incomplete"));
3018 
3019  if (fs::exists(path)) {
3020  throw JSONRPCError(
3022  path.utf8string() + " already exists. If you are sure this is what you want, "
3023  "move it out of the way first");
3024  }
3025 
3026  FILE* file{fsbridge::fopen(temppath, "wb")};
3027  AutoFile afile{file};
3028  if (afile.IsNull()) {
3029  throw JSONRPCError(
3031  "Couldn't open file " + temppath.utf8string() + " for writing.");
3032  }
3033 
3034  CConnman& connman = EnsureConnman(node);
3035  const CBlockIndex* invalidate_index{nullptr};
3036  std::optional<NetworkDisable> disable_network;
3037  std::optional<TemporaryRollback> temporary_rollback;
3038 
3039  // If the user wants to dump the txoutset of the current tip, we don't have
3040  // to roll back at all
3041  if (target_index != tip) {
3042  // If the node is running in pruned mode we ensure all necessary block
3043  // data is available before starting to roll back.
3044  if (node.chainman->m_blockman.IsPruneMode()) {
3045  LOCK(node.chainman->GetMutex());
3046  const CBlockIndex* current_tip{node.chainman->ActiveChain().Tip()};
3047  const CBlockIndex* first_block{node.chainman->m_blockman.GetFirstBlock(*current_tip, /*status_mask=*/BLOCK_HAVE_MASK)};
3048  if (first_block->nHeight > target_index->nHeight) {
3049  throw JSONRPCError(RPC_MISC_ERROR, "Could not roll back to requested height since necessary block data is already pruned.");
3050  }
3051  }
3052 
3053  // Suspend network activity for the duration of the process when we are
3054  // rolling back the chain to get a utxo set from a past height. We do
3055  // this so we don't punish peers that send us that send us data that
3056  // seems wrong in this temporary state. For example a normal new block
3057  // would be classified as a block connecting an invalid block.
3058  // Skip if the network is already disabled because this
3059  // automatically re-enables the network activity at the end of the
3060  // process which may not be what the user wants.
3061  if (connman.GetNetworkActive()) {
3062  disable_network.emplace(connman);
3063  }
3064 
3065  invalidate_index = WITH_LOCK(::cs_main, return node.chainman->ActiveChain().Next(target_index));
3066  temporary_rollback.emplace(*node.chainman, *invalidate_index);
3067  }
3068 
3069  Chainstate* chainstate;
3070  std::unique_ptr<CCoinsViewCursor> cursor;
3071  CCoinsStats stats;
3072  {
3073  // Lock the chainstate before calling PrepareUtxoSnapshot, to be able
3074  // to get a UTXO database cursor while the chain is pointing at the
3075  // target block. After that, release the lock while calling
3076  // WriteUTXOSnapshot. The cursor will remain valid and be used by
3077  // WriteUTXOSnapshot to write a consistent snapshot even if the
3078  // chainstate changes.
3079  LOCK(node.chainman->GetMutex());
3080  chainstate = &node.chainman->ActiveChainstate();
3081  // In case there is any issue with a block being read from disk we need
3082  // to stop here, otherwise the dump could still be created for the wrong
3083  // height.
3084  // The new tip could also not be the target block if we have a stale
3085  // sister block of invalidate_index. This block (or a descendant) would
3086  // be activated as the new tip and we would not get to new_tip_index.
3087  if (target_index != chainstate->m_chain.Tip()) {
3088  LogWarning("dumptxoutset failed to roll back to requested height, reverting to tip.\n");
3089  throw JSONRPCError(RPC_MISC_ERROR, "Could not roll back to requested height.");
3090  } else {
3091  std::tie(cursor, stats, tip) = PrepareUTXOSnapshot(*chainstate, node.rpc_interruption_point);
3092  }
3093  }
3094 
3095  UniValue result = WriteUTXOSnapshot(*chainstate, cursor.get(), &stats, tip, afile, path, temppath, node.rpc_interruption_point);
3096  fs::rename(temppath, path);
3097 
3098  result.pushKV("path", path.utf8string());
3099  return result;
3100 },
3101  };
3102 }
3103 
3104 std::tuple<std::unique_ptr<CCoinsViewCursor>, CCoinsStats, const CBlockIndex*>
3106  Chainstate& chainstate,
3107  const std::function<void()>& interruption_point)
3108 {
3109  std::unique_ptr<CCoinsViewCursor> pcursor;
3110  std::optional<CCoinsStats> maybe_stats;
3111  const CBlockIndex* tip;
3112 
3113  {
3114  // We need to lock cs_main to ensure that the coinsdb isn't written to
3115  // between (i) flushing coins cache to disk (coinsdb), (ii) getting stats
3116  // based upon the coinsdb, and (iii) constructing a cursor to the
3117  // coinsdb for use in WriteUTXOSnapshot.
3118  //
3119  // Cursors returned by leveldb iterate over snapshots, so the contents
3120  // of the pcursor will not be affected by simultaneous writes during
3121  // use below this block.
3122  //
3123  // See discussion here:
3124  // https://github.com/bitcoin/bitcoin/pull/15606#discussion_r274479369
3125  //
3127 
3128  chainstate.ForceFlushStateToDisk();
3129 
3130  maybe_stats = GetUTXOStats(&chainstate.CoinsDB(), chainstate.m_blockman, CoinStatsHashType::HASH_SERIALIZED, interruption_point);
3131  if (!maybe_stats) {
3132  throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
3133  }
3134 
3135  pcursor = chainstate.CoinsDB().Cursor();
3136  tip = CHECK_NONFATAL(chainstate.m_blockman.LookupBlockIndex(maybe_stats->hashBlock));
3137  }
3138 
3139  return {std::move(pcursor), *CHECK_NONFATAL(maybe_stats), tip};
3140 }
3141 
3143  Chainstate& chainstate,
3144  CCoinsViewCursor* pcursor,
3145  CCoinsStats* maybe_stats,
3146  const CBlockIndex* tip,
3147  AutoFile& afile,
3148  const fs::path& path,
3149  const fs::path& temppath,
3150  const std::function<void()>& interruption_point)
3151 {
3152  LOG_TIME_SECONDS(strprintf("writing UTXO snapshot at height %s (%s) to file %s (via %s)",
3153  tip->nHeight, tip->GetBlockHash().ToString(),
3154  fs::PathToString(path), fs::PathToString(temppath)));
3155 
3156  SnapshotMetadata metadata{chainstate.m_chainman.GetParams().MessageStart(), tip->GetBlockHash(), maybe_stats->coins_count};
3157 
3158  afile << metadata;
3159 
3160  COutPoint key;
3161  Txid last_hash;
3162  Coin coin;
3163  unsigned int iter{0};
3164  size_t written_coins_count{0};
3165  std::vector<std::pair<uint32_t, Coin>> coins;
3166 
3167  // To reduce space the serialization format of the snapshot avoids
3168  // duplication of tx hashes. The code takes advantage of the guarantee by
3169  // leveldb that keys are lexicographically sorted.
3170  // In the coins vector we collect all coins that belong to a certain tx hash
3171  // (key.hash) and when we have them all (key.hash != last_hash) we write
3172  // them to file using the below lambda function.
3173  // See also https://github.com/bitcoin/bitcoin/issues/25675
3174  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) {
3175  afile << last_hash;
3176  WriteCompactSize(afile, coins.size());
3177  for (const auto& [n, coin] : coins) {
3178  WriteCompactSize(afile, n);
3179  afile << coin;
3180  ++written_coins_count;
3181  }
3182  };
3183 
3184  pcursor->GetKey(key);
3185  last_hash = key.hash;
3186  while (pcursor->Valid()) {
3187  if (iter % 5000 == 0) interruption_point();
3188  ++iter;
3189  if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
3190  if (key.hash != last_hash) {
3191  write_coins_to_file(afile, last_hash, coins, written_coins_count);
3192  last_hash = key.hash;
3193  coins.clear();
3194  }
3195  coins.emplace_back(key.n, coin);
3196  }
3197  pcursor->Next();
3198  }
3199 
3200  if (!coins.empty()) {
3201  write_coins_to_file(afile, last_hash, coins, written_coins_count);
3202  }
3203 
3204  CHECK_NONFATAL(written_coins_count == maybe_stats->coins_count);
3205 
3206  afile.fclose();
3207 
3209  result.pushKV("coins_written", written_coins_count);
3210  result.pushKV("base_hash", tip->GetBlockHash().ToString());
3211  result.pushKV("base_height", tip->nHeight);
3212  result.pushKV("path", path.utf8string());
3213  result.pushKV("txoutset_hash", maybe_stats->hashSerialized.ToString());
3214  result.pushKV("nchaintx", tip->m_chain_tx_count);
3215  return result;
3216 }
3217 
3220  Chainstate& chainstate,
3221  AutoFile& afile,
3222  const fs::path& path,
3223  const fs::path& tmppath)
3224 {
3225  auto [cursor, stats, tip]{WITH_LOCK(::cs_main, return PrepareUTXOSnapshot(chainstate, node.rpc_interruption_point))};
3226  return WriteUTXOSnapshot(chainstate, cursor.get(), &stats, tip, afile, path, tmppath, node.rpc_interruption_point);
3227 }
3228 
3230 {
3231  return RPCHelpMan{
3232  "loadtxoutset",
3233  "Load the serialized UTXO set from a file.\n"
3234  "Once this snapshot is loaded, its contents will be "
3235  "deserialized into a second chainstate data structure, which is then used to sync to "
3236  "the network's tip. "
3237  "Meanwhile, the original chainstate will complete the initial block download process in "
3238  "the background, eventually validating up to the block that the snapshot is based upon.\n\n"
3239 
3240  "The result is a usable bitcoind instance that is current with the network tip in a "
3241  "matter of minutes rather than hours. UTXO snapshot are typically obtained from "
3242  "third-party sources (HTTP, torrent, etc.) which is reasonable since their "
3243  "contents are always checked by hash.\n\n"
3244 
3245  "You can find more information on this process in the `assumeutxo` design "
3246  "document (<https://github.com/bitcoin/bitcoin/blob/master/doc/design/assumeutxo.md>).",
3247  {
3248  {"path",
3251  "path to the snapshot file. If relative, will be prefixed by datadir."},
3252  },
3253  RPCResult{
3254  RPCResult::Type::OBJ, "", "",
3255  {
3256  {RPCResult::Type::NUM, "coins_loaded", "the number of coins loaded from the snapshot"},
3257  {RPCResult::Type::STR_HEX, "tip_hash", "the hash of the base of the snapshot"},
3258  {RPCResult::Type::NUM, "base_height", "the height of the base of the snapshot"},
3259  {RPCResult::Type::STR, "path", "the absolute path that the snapshot was loaded from"},
3260  }
3261  },
3262  RPCExamples{
3263  HelpExampleCli("-rpcclienttimeout=0 loadtxoutset", "utxo.dat")
3264  },
3265  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
3266 {
3267  NodeContext& node = EnsureAnyNodeContext(request.context);
3268  ChainstateManager& chainman = EnsureChainman(node);
3269  const fs::path path{AbsPathForConfigVal(EnsureArgsman(node), fs::u8path(self.Arg<std::string>("path")))};
3270 
3271  FILE* file{fsbridge::fopen(path, "rb")};
3272  AutoFile afile{file};
3273  if (afile.IsNull()) {
3274  throw JSONRPCError(
3276  "Couldn't open file " + path.utf8string() + " for reading.");
3277  }
3278 
3279  SnapshotMetadata metadata{chainman.GetParams().MessageStart()};
3280  try {
3281  afile >> metadata;
3282  } catch (const std::ios_base::failure& e) {
3283  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("Unable to parse metadata: %s", e.what()));
3284  }
3285 
3286  auto activation_result{chainman.ActivateSnapshot(afile, metadata, false)};
3287  if (!activation_result) {
3288  throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to load UTXO snapshot: %s. (%s)", util::ErrorString(activation_result).original, path.utf8string()));
3289  }
3290 
3291  // Because we can't provide historical blocks during tip or background sync.
3292  // Update local services to reflect we are a limited peer until we are fully sync.
3293  node.connman->RemoveLocalServices(NODE_NETWORK);
3294  // Setting the limited state is usually redundant because the node can always
3295  // provide the last 288 blocks, but it doesn't hurt to set it.
3296  node.connman->AddLocalServices(NODE_NETWORK_LIMITED);
3297 
3298  CBlockIndex& snapshot_index{*CHECK_NONFATAL(*activation_result)};
3299 
3301  result.pushKV("coins_loaded", metadata.m_coins_count);
3302  result.pushKV("tip_hash", snapshot_index.GetBlockHash().ToString());
3303  result.pushKV("base_height", snapshot_index.nHeight);
3304  result.pushKV("path", fs::PathToString(path));
3305  return result;
3306 },
3307  };
3308 }
3309 
3310 const std::vector<RPCResult> RPCHelpForChainstate{
3311  {RPCResult::Type::NUM, "blocks", "number of blocks in this chainstate"},
3312  {RPCResult::Type::STR_HEX, "bestblockhash", "blockhash of the tip"},
3313  {RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},
3314  {RPCResult::Type::STR_HEX, "target", "The difficulty target"},
3315  {RPCResult::Type::NUM, "difficulty", "difficulty of the tip"},
3316  {RPCResult::Type::NUM, "verificationprogress", "progress towards the network tip"},
3317  {RPCResult::Type::STR_HEX, "snapshot_blockhash", /*optional=*/true, "the base block of the snapshot this chainstate is based on, if any"},
3318  {RPCResult::Type::NUM, "coins_db_cache_bytes", "size of the coinsdb cache"},
3319  {RPCResult::Type::NUM, "coins_tip_cache_bytes", "size of the coinstip cache"},
3320  {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."},
3321 };
3322 
3324 {
3325 return RPCHelpMan{
3326  "getchainstates",
3327  "\nReturn information about chainstates.\n",
3328  {},
3329  RPCResult{
3330  RPCResult::Type::OBJ, "", "", {
3331  {RPCResult::Type::NUM, "headers", "the number of headers seen so far"},
3332  {RPCResult::Type::ARR, "chainstates", "list of the chainstates ordered by work, with the most-work (active) chainstate last", {{RPCResult::Type::OBJ, "", "", RPCHelpForChainstate},}},
3333  }
3334  },
3335  RPCExamples{
3336  HelpExampleCli("getchainstates", "")
3337  + HelpExampleRpc("getchainstates", "")
3338  },
3339  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
3340 {
3341  LOCK(cs_main);
3342  UniValue obj(UniValue::VOBJ);
3343 
3344  ChainstateManager& chainman = EnsureAnyChainman(request.context);
3345 
3346  auto make_chain_data = [&](const Chainstate& cs, bool validated) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
3349  if (!cs.m_chain.Tip()) {
3350  return data;
3351  }
3352  const CChain& chain = cs.m_chain;
3353  const CBlockIndex* tip = chain.Tip();
3354 
3355  data.pushKV("blocks", (int)chain.Height());
3356  data.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
3357  data.pushKV("bits", strprintf("%08x", tip->nBits));
3358  data.pushKV("target", GetTarget(*tip, chainman.GetConsensus().powLimit).GetHex());
3359  data.pushKV("difficulty", GetDifficulty(*tip));
3360  data.pushKV("verificationprogress", chainman.GuessVerificationProgress(tip));
3361  data.pushKV("coins_db_cache_bytes", cs.m_coinsdb_cache_size_bytes);
3362  data.pushKV("coins_tip_cache_bytes", cs.m_coinstip_cache_size_bytes);
3363  if (cs.m_from_snapshot_blockhash) {
3364  data.pushKV("snapshot_blockhash", cs.m_from_snapshot_blockhash->ToString());
3365  }
3366  data.pushKV("validated", validated);
3367  return data;
3368  };
3369 
3370  obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
3371 
3372  const auto& chainstates = chainman.GetAll();
3373  UniValue obj_chainstates{UniValue::VARR};
3374  for (Chainstate* cs : chainstates) {
3375  obj_chainstates.push_back(make_chain_data(*cs, !cs->m_from_snapshot_blockhash || chainstates.size() == 1));
3376  }
3377  obj.pushKV("chainstates", std::move(obj_chainstates));
3378  return obj;
3379 }
3380  };
3381 }
3382 
3383 
3385 {
3386  static const CRPCCommand commands[]{
3387  {"blockchain", &getblockchaininfo},
3388  {"blockchain", &getchaintxstats},
3389  {"blockchain", &getblockstats},
3390  {"blockchain", &getbestblockhash},
3391  {"blockchain", &getblockcount},
3392  {"blockchain", &getblock},
3393  {"blockchain", &getblockfrompeer},
3394  {"blockchain", &getblockhash},
3395  {"blockchain", &getblockheader},
3396  {"blockchain", &getchaintips},
3397  {"blockchain", &getdifficulty},
3398  {"blockchain", &getdeploymentinfo},
3399  {"blockchain", &gettxout},
3400  {"blockchain", &gettxoutsetinfo},
3401  {"blockchain", &pruneblockchain},
3402  {"blockchain", &verifychain},
3403  {"blockchain", &preciousblock},
3404  {"blockchain", &scantxoutset},
3405  {"blockchain", &scanblocks},
3406  {"blockchain", &getdescriptoractivity},
3407  {"blockchain", &getblockfilter},
3408  {"blockchain", &dumptxoutset},
3409  {"blockchain", &loadtxoutset},
3410  {"blockchain", &getchainstates},
3411  {"hidden", &invalidateblock},
3412  {"hidden", &reconsiderblock},
3413  {"hidden", &waitfornewblock},
3414  {"hidden", &waitforblock},
3415  {"hidden", &waitforblockheight},
3416  {"hidden", &syncwithvalidationinterfacequeue},
3417  };
3418  for (const auto& c : commands) {
3419  t.appendCommand(c.name, &c);
3420  }
3421 }
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:611
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
Definition: chain.h:165
CAmount nValue
Definition: transaction.h:152
const std::vector< RPCResult > RPCHelpForChainstate
std::vector< RPCResult > ScriptPubKeyDoc()
Definition: util.cpp:1413
int min_activation_height
If lock in occurs, delay activation until at least this block height.
Definition: params.h:54
std::string GetHex() const
uint64_t nTransactions
Definition: coinstats.h:35
void PruneBlockFilesManual(Chainstate &active_chainstate, int nManualPruneHeight)
Prune block files up to a given height.
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...
Definition: config.cpp:226
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1007
bool LookupFilter(const CBlockIndex *block_index, BlockFilter &filter_out) const
Get a single filter by block.
static RPCHelpMan syncwithvalidationinterfacequeue()
Definition: blockchain.cpp:412
Display status of an in-progress BIP9 softfork.
Definition: versionbits.h:41
static const auto scan_result_abort
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
void push_back(UniValue val)
Definition: univalue.cpp:104
const std::vector< std::string > CHECKLEVEL_DOC
Documentation for argument &#39;checklevel&#39;.
Definition: validation.cpp:99
int ret
static constexpr int NUM_GETBLOCKSTATS_PERCENTILES
Definition: blockchain.h:28
bool IsCoinBase() const
Definition: coins.h:57
CConnman & m_connman
static RPCHelpMan getblock()
Definition: blockchain.cpp:700
static std::atomic< int > g_scanfilter_progress_height
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:36
The same as previous option with information about prevouts if available.
AssertLockHeld(pool.cs)
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
const std::vector< UniValue > & getValues() const
std::unique_ptr< CCoinsViewCursor > Cursor() const override
Get a cursor to iterate over the whole state.
Definition: txdb.cpp:182
bool ReadRawBlock(std::vector< uint8_t > &block, const FlatFilePos &pos) const
static const int WITNESS_SCALE_FACTOR
Definition: consensus.h:21
bool IsPruneMode() const
Whether running in -prune mode.
Definition: blockstorage.h:349
RPC command dispatcher.
Definition: server.h:126
int64_t GetBlockTime() const
Definition: chain.h:266
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:26
CScript scriptPubKey
Definition: transaction.h:153
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:147
uint64_t CalculateCurrentUsage()
Calculate the amount of disk space the block & undo files currently use.
bool IsRPCRunning()
Query whether RPC is running.
Definition: server.cpp:310
static RPCHelpMan getblockfrompeer()
Definition: blockchain.cpp:451
Required arg.
uint256 GetTarget(const CBlockIndex &blockindex, const uint256 pow_limit)
Definition: util.cpp:1424
std::string GetChainTypeString() const
Return the chain type string.
Definition: chainparams.h:113
node::BlockManager & m_blockman
Reference to a BlockManager instance which itself is shared across all Chainstate instances...
Definition: validation.h:535
A UTXO entry.
Definition: coins.h:32
CTxMemPool & EnsureMemPool(const NodeContext &node)
Definition: server_util.cpp:34
Definition: block.h:68
bool BlockFilterTypeByName(const std::string &name, BlockFilterType &filter_type)
Find a filter type by its human-readable name.
TxVerbosity
Verbose level for block&#39;s transaction.
Definition: core_io.h:28
UniValue blockToJSON(BlockManager &blockman, const CBlock &block, const CBlockIndex &tip, const CBlockIndex &blockindex, TxVerbosity verbosity, const uint256 pow_limit)
Block description to JSON.
Definition: blockchain.cpp:179
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:865
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
DeploymentPos
Definition: params.h:32
An in-memory indexed chain of blocks.
Definition: chain.h:416
static std::atomic< bool > g_scanfilter_should_abort_scan
BlockFiltersScanReserver()=default
NetworkDisable(CConnman &connman)
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1103
CAmount total_new_outputs_ex_coinbase_amount
Total cumulative amount of outputs created up to and including this block.
Definition: coinstats.h:58
virtual void Next()=0
bool index_used
Signals if the coinstatsindex was used to retrieve the statistics.
Definition: coinstats.h:47
Comparison function for sorting the getchaintips heads.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...
Definition: validation.h:68
int StateSinceHeight(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the block height at which the BIP9 deployment switched into the state for the block after pindexP...
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1111
static std::vector< uint8_t > GetRawBlockChecked(BlockManager &blockman, const CBlockIndex &blockindex)
Definition: blockchain.cpp:638
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
Definition: chain.h:97
static constexpr int DEFAULT_CHECKLEVEL
Definition: validation.h:70
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:27
CBlockHeader GetBlockHeader() const
Definition: chain.h:230
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:81
int Height() const
Return the maximal height in the chain.
Definition: chain.h:462
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
CTxOut out
unspent transaction output
Definition: coins.h:36
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
std::optional< CAmount > total_amount
The total amount, or nullopt if an overflow occurred calculating it.
Definition: coinstats.h:41
constexpr const std::byte * begin() const
#define LOG_TIME_SECONDS(end_msg)
Definition: timer.h:107
static const auto scan_result_status_some
bool ReadBlock(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
const std::string & get_str() const
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
Definition: chain.h:427
bool isNum() const
Definition: univalue.h:84
const UniValue & get_array() const
uint64_t coins_count
The number of coins contained.
Definition: coinstats.h:44
uint32_t nTime
Definition: chain.h:189
undo data available in rev*.dat
Definition: chain.h:122
#define LIST_CHAIN_NAMES
List of possible chain / network names.
static RPCHelpMan scantxoutset()
bool skip_type_check
Definition: util.h:167
ThresholdState
BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
Definition: versionbits.h:27
Int getInt() const
Definition: univalue.h:138
double GuessVerificationProgress(const CBlockIndex *pindex) const
Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip).
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:585
static BIP9Stats Statistics(const CBlockIndex *pindex, const Consensus::Params &params, Consensus::DeploymentPos pos, std::vector< bool > *signalling_blocks=nullptr)
Get the numerical statistics for a given deployment for the signalling period that includes pindex...
consteval auto _(util::TranslatedLiteral str)
Definition: translation.h:79
uint64_t nDiskSize
Definition: coinstats.h:39
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:66
static int ComputeNextBlockAndDepth(const CBlockIndex &tip, const CBlockIndex &blockindex, const CBlockIndex *&next)
Definition: blockchain.cpp:111
std::optional< Coin > GetCoin(const COutPoint &outpoint) const override
GetCoin, returning whether it exists and is not spent.
Definition: txmempool.cpp:1027
util::Result< CBlockIndex * > ActivateSnapshot(AutoFile &coins_file, const node::SnapshotMetadata &metadata, bool in_memory)
Construct and activate a Chainstate on the basis of UTXO snapshot data.
static std::atomic< int > g_scan_progress
RAII object to prevent concurrency issue when scanning the txout set.
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:391
static int32_t GetTransactionWeight(const CTransaction &tx)
Definition: validation.h:133
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
Definition: chain.h:37
static RPCHelpMan loadtxoutset()
int threshold
Number of blocks with the version bit set required to activate the softfork.
Definition: versionbits.h:45
CoinStatsHashType
Definition: coinstats.h:26
CAmount total_unspendables_scripts
Total cumulative amount of outputs sent to unspendable scripts (OP_RETURN for example) up to and incl...
Definition: coinstats.h:66
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible...
bool isSpent(const COutPoint &outpoint) const
Definition: txmempool.cpp:419
Invalid, missing or duplicate parameter.
Definition: protocol.h:44
static RPCHelpMan getdescriptoractivity()
CAmount total_coinbase_amount
Total cumulative amount of coinbase outputs up to and including this block.
Definition: coinstats.h:60
RAII class that temporarily rolls back the local chain in it&#39;s constructor and rolls it forward again...
RPCHelpMan getblockchaininfo()
VersionBitsCache m_versionbitscache
Track versionbit status.
Definition: validation.h:1134
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
Definition: mempool_entry.h:65
bool DeploymentEnabled(const Consensus::Params &params, Consensus::BuriedDeployment dep)
Determine if a deployment is enabled (can ever be active)
CoinStatsHashType ParseHashType(const std::string &hash_type_input)
Definition: blockchain.cpp:898
CoinsViewScanReserver()=default
static RPCHelpMan getchaintxstats()
ThresholdState State(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the BIP9 state for a given deployment for the block after pindexPrev.
const RPCResult getblock_vin
Definition: blockchain.cpp:676
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
CAmount total_unspendables_unclaimed_rewards
Total cumulative amount of coins lost due to unclaimed miner rewards up to and including this block...
Definition: coinstats.h:68
CAmount total_unspendables_bip30
The two unspendable coinbase outputs total amount caused by BIP30.
Definition: coinstats.h:64
static T CalculateTruncatedMedian(std::vector< T > &scores)
std::string GetAllOutputTypes()
Gets all existing output types formatted for RPC help sections.
Definition: util.cpp:49
virtual bool GetValue(Coin &coin) const =0
uint256 GetBlockHash() const
Definition: chain.h:243
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:168
uint32_t nHeight
at which height this containing transaction was included in the active block chain ...
Definition: coins.h:42
bool IsValid() const
Definition: validation.h:106
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...
Definition: chain.cpp:71
iterator end()
Definition: prevector.h:304
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coin to signify they are only in the memory pool (since 0...
Definition: txmempool.h:49
BlockFilterType
Definition: blockfilter.h:92
static RPCHelpMan getblockfilter()
uint64_t PruneAfterHeight() const
Definition: chainparams.h:105
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
Definition: string.h:213
Special type that is a STR with only hex chars.
NodeContext struct containing references to chain state and connection state.
Definition: context.h:56
bool IsBIP30Repeat(const CBlockIndex &block_index)
Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30) ...
uint256 powLimit
Proof of work parameters.
Definition: params.h:109
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:204
ChainstateManager & m_chainman
The chainstate manager that owns this chainstate.
Definition: validation.h:545
Interface giving clients (RPC, Stratum v2 Template Provider in the future) ability to create block te...
Definition: mining.h:63
static std::atomic< bool > g_scan_in_progress
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
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={})
Definition: blockchain.cpp:79
void ReconsiderBlock(ChainstateManager &chainman, uint256 block_hash)
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: args.h:234
bool operator()(const CBlockIndex *a, const CBlockIndex *b) const
Special string with only hex chars.
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:151
Definition: util.h:183
ArgsManager & args
Definition: bitcoind.cpp:277
virtual bool Valid() const =0
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:504
static RPCHelpMan waitfornewblock()
Definition: blockchain.cpp:260
Include TXID, inputs, outputs, and other common block&#39;s transaction information.
static void SoftForkDescPushBack(const CBlockIndex *blockindex, UniValue &softforks, const ChainstateManager &chainman, Consensus::BuriedDeployment dep)
Scripts & signatures ok.
Definition: chain.h:115
static const CBlockIndex * ParseHashOrHeight(const UniValue &param, ChainstateManager &chainman)
Definition: blockchain.cpp:121
void RegisterBlockchainRPCCommands(CRPCTable &t)
void ScriptToUniv(const CScript &script, UniValue &out, bool include_hex=true, bool include_address=false, const SigningProvider *provider=nullptr)
Definition: core_write.cpp:150
uint32_t nNonce
Definition: chain.h:191
Abstract view on the open txout dataset.
Definition: coins.h:309
static void pool cs
UniValue blockheaderToJSON(const CBlockIndex &tip, const CBlockIndex &blockindex, const uint256 pow_limit)
Block header to JSON.
Definition: blockchain.cpp:149
An input of a transaction.
Definition: transaction.h:66
uint64_t m_chain_tx_count
(memory only) Number of transactions in the chain up to and including this block. ...
Definition: chain.h:176
int period
Length of blocks of the BIP9 signalling period.
Definition: versionbits.h:43
#define LOCK(cs)
Definition: sync.h:257
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:146
int DeploymentHeight(BuriedDeployment dep) const
Definition: params.h:136
std::string ToString() const
Definition: validation.h:112
static RPCHelpMan dumptxoutset()
Serialize the UTXO set to a file for loading elsewhere.
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
Definition: serialize.h:1097
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
static RPCHelpMan getblockheader()
Definition: blockchain.cpp:535
Complete block filter struct as defined in BIP 157.
Definition: blockfilter.h:114
CAmount total_prevout_spent_amount
Total cumulative amount of prevouts spent up to and including this block.
Definition: coinstats.h:56
Special array that has a fixed number of entries.
static RPCHelpMan getchainstates()
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:447
kernel::Notifications & GetNotifications() const
Definition: validation.h:981
Txid hash
Definition: transaction.h:31
int64_t nStartTime
Start MedianTime for version bits miner confirmation.
Definition: params.h:47
int64_t nPowTargetSpacing
Definition: params.h:117
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
Definition: time.h:87
RAII wrapper for VerifyDB: Verify consistency of the block and coin databases.
Definition: validation.h:413
uint32_t n
Definition: transaction.h:32
interfaces::Mining & EnsureMining(const NodeContext &node)
uint256 hashSerialized
Definition: coinstats.h:38
static RPCHelpMan getblockstats()
const Consensus::Params & GetConsensus() const
Definition: validation.h:977
const std::string CURRENCY_UNIT
Definition: feerate.h:17
uint256 hashMerkleRoot
Definition: chain.h:188
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1113
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: blockstorage.h:138
CCoinsViewDB & CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:619
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...
Definition: blockchain.cpp:814
General application defined errors.
Definition: protocol.h:40
std::string DefaultHint
Hint for default value.
Definition: util.h:217
UniValue CreateUTXOSnapshot(node::NodeContext &node, Chainstate &chainstate, AutoFile &afile, const fs::path &path, const fs::path &tmppath)
Test-only helper to create UTXO snapshots given a chainstate and a file handle.
int64_t NodeId
Definition: net.h:97
void ForceFlushStateToDisk()
Unconditionally flush all changes to disk.
int count
Number of blocks with the version bit set since the beginning of the current period.
Definition: versionbits.h:49
Definition: net.h:1051
void SetNetworkActive(bool active)
Definition: net.cpp:3194
bool GetNetworkActive() const
Definition: net.h:1136
An output of a transaction.
Definition: transaction.h:149
CAmount total_unspendable_amount
Total cumulative amount of unspendable coins up to and including this block.
Definition: coinstats.h:54
std::string ToString() const
Definition: uint256.cpp:47
Invalid address or key.
Definition: protocol.h:42
RAII class that disables the network in its constructor and enables it in its destructor.
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
Definition: validation.h:1001
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
static std::atomic< bool > g_scanfilter_in_progress
static const auto scan_result_status_none
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:28
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:186
virtual BlockRef waitTipChanged(uint256 current_tip, MillisecondsDouble timeout=MillisecondsDouble::max())=0
Waits for the connected tip to change.
bool IsDeprecatedRPCEnabled(const std::string &method)
Definition: server.cpp:341
Chainstate &InitializeChainstate(CTxMemPool *mempool) EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate.
Definition: validation.h:1080
unsigned int nHeight
bool isNull() const
Definition: univalue.h:79
Special numeric to denote unix epoch time.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
UniValue Default
Default constant value.
Definition: util.h:219
int64_t GetMedianTimePast() const
Definition: chain.h:278
static RPCHelpMan getdifficulty()
Definition: blockchain.cpp:431
static RPCHelpMan invalidateblock()
std::unordered_set< Element, ByteVectorHash > ElementSet
Definition: blockfilter.h:32
virtual bool GetKey(COutPoint &key) const =0
UniValue GetWarningsForRpc(const Warnings &warnings, bool use_deprecated)
RPC helper function that wraps warnings.GetMessages().
Definition: warnings.cpp:54
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:1125
static RPCHelpMan getblockcount()
Definition: blockchain.cpp:219
Definition: messages.h:20
void InvalidateBlock(ChainstateManager &chainman, const uint256 block_hash)
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:173
Database error.
Definition: protocol.h:45
Special type that is a NUM or [NUM,NUM].
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
Definition: chain.h:295
int32_t nVersion
block header
Definition: chain.h:187
static bool ComputeUTXOStats(CCoinsView *view, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point)
Calculate statistics about the unspent transaction output set.
Definition: coinstats.cpp:116
const CChainParams & GetParams() const
Definition: validation.h:976
int64_t nTimeout
Timeout/expiry MedianTime for the deployment attempt.
Definition: params.h:49
256-bit opaque blob.
Definition: uint256.h:201
Optional argument for which the default value is omitted from help text for one of two reasons: ...
static const auto scan_action_arg_desc
static std::atomic< bool > g_should_abort_scan
ChainType GetChainType() const
Return the chain type.
Definition: chainparams.h:115
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
static RPCHelpMan waitforblock()
Definition: blockchain.cpp:302
std::vector< CTransactionRef > vtx
Definition: block.h:72
std::string utf8string() const
Return a UTF-8 representation of the path as a std::string, for compatibility with code using std::st...
Definition: fs.h:63
static const auto scan_objects_arg_desc
static CBlock GetBlockChecked(BlockManager &blockman, const CBlockIndex &blockindex)
Definition: blockchain.cpp:621
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:303
auto result
Definition: common-types.h:74
#define LogDebug(category,...)
Definition: logging.h:381
static bool SetHasKeys(const std::set< T > &set)
static std::optional< kernel::CCoinsStats > GetUTXOStats(CCoinsView *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.
Definition: blockchain.cpp:916
int ParseVerbosity(const UniValue &arg, int default_verbosity, bool allow_bool)
Parses verbosity from provided UniValue.
Definition: util.cpp:86
Only TXID for each block&#39;s transaction.
Special string to represent a floating point amount.
static RPCHelpMan gettxout()
static RPCHelpMan verifychain()
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:140
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
Undo information for a CBlock.
Definition: undo.h:62
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
static transaction_identifier FromUint256(const uint256 &id)
uint256 ParseHashV(const UniValue &v, std::string_view name)
Utilities: convert hex-encoded Values (throws error if not hex).
Definition: util.cpp:120
static const signed int DEFAULT_CHECKBLOCKS
Definition: validation.h:69
Undo information for a CTransaction.
Definition: undo.h:52
ChainstateManager & EnsureChainman(const NodeContext &node)
Definition: server_util.cpp:74
const MessageStartChars & MessageStart() const
Definition: chainparams.h:94
virtual std::optional< BlockRef > getTip()=0
Returns the hash and height for the tip of this chain.
virtual uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:17
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network) ...
std::vector< uint8_t > signet_challenge
Definition: params.h:134
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:433
static RPCHelpMan preciousblock()
std::string GetHex() const
Definition: uint256.cpp:11
static constexpr size_t PER_UTXO_OVERHEAD
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:29
static RPCHelpMan waitforblockheight()
Definition: blockchain.cpp:356
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
static RPCHelpMan gettxoutsetinfo()
Definition: blockchain.cpp:941
int fclose()
Definition: streams.h:409
ArgsManager & EnsureAnyArgsman(const std::any &context)
Definition: server_util.cpp:69
const UniValue NullUniValue
Definition: univalue.cpp:16
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:26
static RPCHelpMan pruneblockchain()
Definition: blockchain.cpp:839
#define AssertLockNotHeld(cs)
Definition: sync.h:147
int elapsed
Number of blocks elapsed since the beginning of the current period.
Definition: versionbits.h:47
static int count
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
iterator begin()
Definition: prevector.h:302
TemporaryRollback(ChainstateManager &chainman, const CBlockIndex &index)
static CBlockUndo GetUndoChecked(BlockManager &blockman, const CBlockIndex &blockindex)
Definition: blockchain.cpp:657
#define LogWarning(...)
Definition: logging.h:357
RPCHelpMan getdeploymentinfo()
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 ...
Definition: util.cpp:1347
static RPCHelpMan reconsiderblock()
bool possible
False if there are not enough blocks left in this period to pass activation threshold.
Definition: versionbits.h:51
PeerManager & EnsurePeerman(const NodeContext &node)
const CBlockIndex & m_invalidate_index
unsigned char * UCharCast(char *c)
Definition: span.h:280
ChainstateManager & m_chainman
static RPCHelpMan getchaintips()
std::unique_ptr< CoinStatsIndex > g_coin_stats_index
The global UTXO set hash object.
CTransactionRef get(const uint256 &hash) const
Definition: txmempool.cpp:884
double GetDifficulty(const CBlockIndex &blockindex)
Get the difficulty of the net wrt to the given block index.
Definition: blockchain.cpp:91
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE
The maximum allowed size for a serialized block, in bytes (only for buffer size limits) ...
Definition: consensus.h:13
std::string GetHex() const
Hex encoding of the number (with the most significant digits first).
size_t size() const
Definition: univalue.h:71
static bool CheckBlockFilterMatches(BlockManager &blockman, const CBlockIndex &blockindex, const GCSFilter::ElementSet &needles)
CAmount total_unspendables_genesis_block
The unspendable coinbase amount from the genesis block.
Definition: coinstats.h:62
static std::atomic< int > g_scanfilter_progress
RAII object to prevent concurrency issue when scanning blockfilters.
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:153
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Definition: chain.h:208
const std::vector< unsigned char > & GetEncodedFilter() const LIFETIMEBOUND
Definition: blockfilter.h:138
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:93
int bit
Bit position to select the particular bit in nVersion.
Definition: params.h:45
void CheckBlockDataAvailability(BlockManager &blockman, const CBlockIndex &blockindex, bool check_for_undo)
Definition: blockchain.cpp:606
Special dictionary with keys that are not literals.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:362
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:120
full block available in blk*.dat
Definition: chain.h:121
static bool exists(const path &p)
Definition: fs.h:89
ChainstateManager & EnsureAnyChainman(const std::any &context)
Definition: server_util.cpp:82
static path u8path(const std::string &utf8_str)
Definition: fs.h:75
std::vector< CTxUndo > vtxundo
Definition: undo.h:65
static int64_t GetBlockWeight(const CBlock &block)
Definition: validation.h:137
static RPCHelpMan scanblocks()
uint64_t nBogoSize
Definition: coinstats.h:37
uint64_t nTransactionOutputs
Definition: coinstats.h:36
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:32
uint64_t GetPruneTarget() const
Attempt to stay below this number of bytes of block files.
Definition: blockstorage.h:352
std::tuple< std::unique_ptr< CCoinsViewCursor >, CCoinsStats, const CBlockIndex * > PrepareUTXOSnapshot(Chainstate &chainstate, const std::function< void()> &interruption_point)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: cs_main.cpp:8
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Find the last common block between this chain and a block index entry.
Definition: chain.cpp:60
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.
CCoinsView that brings transactions from a mempool into view.
Definition: txmempool.h:924
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.
#define T(expected, seed, data)
uint32_t nBits
Definition: chain.h:190
BuriedDeployment
A buried deployment is one where the height of the activation has been hardcoded into the client impl...
Definition: params.h:22
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:170
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
Definition: validation.h:1110
std::vector< CTxMemPoolEntryRef > entryAll() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:851
NodeContext & EnsureAnyNodeContext(const std::any &context)
Definition: server_util.cpp:25
static RPCHelpMan getblockhash()
Definition: blockchain.cpp:506
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]
Definition: params.h:107
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
Definition: txmempool.h:390
ArgsManager & EnsureArgsman(const NodeContext &node)
Definition: server_util.cpp:61
Error parsing or validating structure in raw format.
Definition: protocol.h:46
CConnman & EnsureConnman(const NodeContext &node)
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency...
Definition: util.cpp:46
static constexpr TransactionSerParams TX_WITH_WITNESS
Definition: transaction.h:195
static constexpr TransactionSerParams TX_NO_WITNESS
Definition: transaction.h:196
Special type to denote elision (...)
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
void TxToUniv(const CTransaction &tx, const uint256 &block_hash, UniValue &entry, bool include_hex=true, const CTxUndo *txundo=nullptr, TxVerbosity verbosity=TxVerbosity::SHOW_DETAILS)
Definition: core_write.cpp:171
std::string DeploymentName(Consensus::BuriedDeployment dep)
bool ReadBlockUndo(CBlockUndo &blockundo, const CBlockIndex &index) const
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition: streams.h:428
Metadata describing a serialized version of a UTXO set from which an assumeutxo Chainstate can be con...
Definition: utxo_snapshot.h:33
Cursor for iterating over CoinsView state.
Definition: coins.h:234
static RPCHelpMan getbestblockhash()
Definition: blockchain.cpp:240