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