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