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