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