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