Bitcoin ABC  0.26.3
P2P Digital Currency
blockchain.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 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 <config.h>
13 #include <consensus/amount.h>
14 #include <consensus/params.h>
15 #include <consensus/validation.h>
16 #include <core_io.h>
17 #include <hash.h>
18 #include <index/blockfilterindex.h>
19 #include <index/coinstatsindex.h>
20 #include <net.h>
21 #include <net_processing.h>
22 #include <node/blockstorage.h>
23 #include <node/coinstats.h>
24 #include <node/context.h>
25 #include <node/utxo_snapshot.h>
26 #include <policy/policy.h>
27 #include <primitives/transaction.h>
28 #include <rpc/server.h>
29 #include <rpc/server_util.h>
30 #include <rpc/util.h>
31 #include <script/descriptor.h>
32 #include <streams.h>
33 #include <txdb.h>
34 #include <txmempool.h>
35 #include <undo.h>
36 #include <util/check.h>
37 #include <util/strencodings.h>
38 #include <util/translation.h>
39 #include <validation.h>
40 #include <validationinterface.h>
41 #include <warnings.h>
42 
43 #include <condition_variable>
44 #include <cstdint>
45 #include <memory>
46 #include <mutex>
47 
48 using node::BlockManager;
49 using node::CCoinsStats;
51 using node::GetUTXOStats;
52 using node::NodeContext;
56 
57 struct CUpdatedBlock {
59  int height;
60 };
61 
63 static std::condition_variable cond_blockchange;
65 
69 double GetDifficulty(const CBlockIndex *blockindex) {
70  CHECK_NONFATAL(blockindex);
71 
72  int nShift = (blockindex->nBits >> 24) & 0xff;
73  double dDiff = double(0x0000ffff) / double(blockindex->nBits & 0x00ffffff);
74 
75  while (nShift < 29) {
76  dDiff *= 256.0;
77  nShift++;
78  }
79  while (nShift > 29) {
80  dDiff /= 256.0;
81  nShift--;
82  }
83 
84  return dDiff;
85 }
86 
87 static int ComputeNextBlockAndDepth(const CBlockIndex *tip,
88  const CBlockIndex *blockindex,
89  const CBlockIndex *&next) {
90  next = tip->GetAncestor(blockindex->nHeight + 1);
91  if (next && next->pprev == blockindex) {
92  return tip->nHeight - blockindex->nHeight + 1;
93  }
94  next = nullptr;
95  return blockindex == tip ? 1 : -1;
96 }
97 
98 static const CBlockIndex *ParseHashOrHeight(const UniValue &param,
99  ChainstateManager &chainman) {
100  LOCK(::cs_main);
101  CChain &active_chain = chainman.ActiveChain();
102 
103  if (param.isNum()) {
104  const int height{param.get_int()};
105  if (height < 0) {
106  throw JSONRPCError(
108  strprintf("Target block height %d is negative", height));
109  }
110  const int current_tip{active_chain.Height()};
111  if (height > current_tip) {
112  throw JSONRPCError(
114  strprintf("Target block height %d after current tip %d", height,
115  current_tip));
116  }
117 
118  return active_chain[height];
119  } else {
120  const BlockHash hash{ParseHashV(param, "hash_or_height")};
121  const CBlockIndex *pindex = chainman.m_blockman.LookupBlockIndex(hash);
122 
123  if (!pindex) {
124  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
125  }
126 
127  return pindex;
128  }
129 }
131  const CBlockIndex *blockindex) {
132  // Serialize passed information without accessing chain state of the active
133  // chain!
134  // For performance reasons
136 
137  UniValue result(UniValue::VOBJ);
138  result.pushKV("hash", blockindex->GetBlockHash().GetHex());
139  const CBlockIndex *pnext;
140  int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
141  result.pushKV("confirmations", confirmations);
142  result.pushKV("height", blockindex->nHeight);
143  result.pushKV("version", blockindex->nVersion);
144  result.pushKV("versionHex", strprintf("%08x", blockindex->nVersion));
145  result.pushKV("merkleroot", blockindex->hashMerkleRoot.GetHex());
146  result.pushKV("time", int64_t(blockindex->nTime));
147  result.pushKV("mediantime", int64_t(blockindex->GetMedianTimePast()));
148  result.pushKV("nonce", uint64_t(blockindex->nNonce));
149  result.pushKV("bits", strprintf("%08x", blockindex->nBits));
150  result.pushKV("difficulty", GetDifficulty(blockindex));
151  result.pushKV("chainwork", blockindex->nChainWork.GetHex());
152  result.pushKV("nTx", uint64_t(blockindex->nTx));
153 
154  if (blockindex->pprev) {
155  result.pushKV("previousblockhash",
156  blockindex->pprev->GetBlockHash().GetHex());
157  }
158  if (pnext) {
159  result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
160  }
161  return result;
162 }
163 
164 UniValue blockToJSON(BlockManager &blockman, const CBlock &block,
165  const CBlockIndex *tip, const CBlockIndex *blockindex,
166  bool txDetails) {
167  UniValue result = blockheaderToJSON(tip, blockindex);
168 
169  result.pushKV("size", (int)::GetSerializeSize(block, PROTOCOL_VERSION));
171  if (txDetails) {
172  CBlockUndo blockUndo;
173  const bool is_not_pruned{
174  WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex))};
175  const bool have_undo{is_not_pruned &&
176  UndoReadFromDisk(blockUndo, blockindex)};
177  for (size_t i = 0; i < block.vtx.size(); ++i) {
178  const CTransactionRef &tx = block.vtx.at(i);
179  // coinbase transaction (i == 0) doesn't have undo data
180  const CTxUndo *txundo =
181  (have_undo && i) ? &blockUndo.vtxundo.at(i - 1) : nullptr;
182  UniValue objTx(UniValue::VOBJ);
183  TxToUniv(*tx, BlockHash(), objTx, true, RPCSerializationFlags(),
184  txundo);
185  txs.push_back(objTx);
186  }
187  } else {
188  for (const CTransactionRef &tx : block.vtx) {
189  txs.push_back(tx->GetId().GetHex());
190  }
191  }
192  result.pushKV("tx", txs);
193 
194  return result;
195 }
196 
198  return RPCHelpMan{
199  "getblockcount",
200  "Returns the height of the most-work fully-validated chain.\n"
201  "The genesis block has height 0.\n",
202  {},
203  RPCResult{RPCResult::Type::NUM, "", "The current block count"},
204  RPCExamples{HelpExampleCli("getblockcount", "") +
205  HelpExampleRpc("getblockcount", "")},
206  [&](const RPCHelpMan &self, const Config &config,
207  const JSONRPCRequest &request) -> UniValue {
208  ChainstateManager &chainman = EnsureAnyChainman(request.context);
209  LOCK(cs_main);
210  return chainman.ActiveHeight();
211  },
212  };
213 }
214 
216  return RPCHelpMan{
217  "getbestblockhash",
218  "Returns the hash of the best (tip) block in the "
219  "most-work fully-validated chain.\n",
220  {},
221  RPCResult{RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"},
222  RPCExamples{HelpExampleCli("getbestblockhash", "") +
223  HelpExampleRpc("getbestblockhash", "")},
224  [&](const RPCHelpMan &self, const Config &config,
225  const JSONRPCRequest &request) -> UniValue {
226  ChainstateManager &chainman = EnsureAnyChainman(request.context);
227  LOCK(cs_main);
228  return chainman.ActiveTip()->GetBlockHash().GetHex();
229  },
230  };
231 }
232 
233 void RPCNotifyBlockChange(const CBlockIndex *pindex) {
234  if (pindex) {
236  latestblock.hash = pindex->GetBlockHash();
237  latestblock.height = pindex->nHeight;
238  }
239  cond_blockchange.notify_all();
240 }
241 
243  return RPCHelpMan{
244  "waitfornewblock",
245  "Waits for a specific new block and returns useful info about it.\n"
246  "\nReturns the current block on timeout or exit.\n",
247  {
248  {"timeout", RPCArg::Type::NUM, /* default */ "0",
249  "Time in milliseconds to wait for a response. 0 indicates no "
250  "timeout."},
251  },
253  "",
254  "",
255  {
256  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
257  {RPCResult::Type::NUM, "height", "Block height"},
258  }},
259  RPCExamples{HelpExampleCli("waitfornewblock", "1000") +
260  HelpExampleRpc("waitfornewblock", "1000")},
261  [&](const RPCHelpMan &self, const Config &config,
262  const JSONRPCRequest &request) -> UniValue {
263  int timeout = 0;
264  if (!request.params[0].isNull()) {
265  timeout = request.params[0].get_int();
266  }
267 
268  CUpdatedBlock block;
269  {
270  WAIT_LOCK(cs_blockchange, lock);
271  block = latestblock;
272  if (timeout) {
273  cond_blockchange.wait_for(
274  lock, std::chrono::milliseconds(timeout),
276  return latestblock.height != block.height ||
277  latestblock.hash != block.hash ||
278  !IsRPCRunning();
279  });
280  } else {
281  cond_blockchange.wait(
282  lock,
284  return latestblock.height != block.height ||
285  latestblock.hash != block.hash ||
286  !IsRPCRunning();
287  });
288  }
289  block = latestblock;
290  }
292  ret.pushKV("hash", block.hash.GetHex());
293  ret.pushKV("height", block.height);
294  return ret;
295  },
296  };
297 }
298 
300  return RPCHelpMan{
301  "waitforblock",
302  "Waits for a specific new block and returns useful info about it.\n"
303  "\nReturns the current block on timeout or exit.\n",
304  {
306  "Block hash to wait for."},
307  {"timeout", RPCArg::Type::NUM, /* default */ "0",
308  "Time in milliseconds to wait for a response. 0 indicates no "
309  "timeout."},
310  },
312  "",
313  "",
314  {
315  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
316  {RPCResult::Type::NUM, "height", "Block height"},
317  }},
318  RPCExamples{HelpExampleCli("waitforblock",
319  "\"0000000000079f8ef3d2c688c244eb7a4570b24c9"
320  "ed7b4a8c619eb02596f8862\" 1000") +
321  HelpExampleRpc("waitforblock",
322  "\"0000000000079f8ef3d2c688c244eb7a4570b24c9"
323  "ed7b4a8c619eb02596f8862\", 1000")},
324  [&](const RPCHelpMan &self, const Config &config,
325  const JSONRPCRequest &request) -> UniValue {
326  int timeout = 0;
327 
328  BlockHash hash(ParseHashV(request.params[0], "blockhash"));
329 
330  if (!request.params[1].isNull()) {
331  timeout = request.params[1].get_int();
332  }
333 
334  CUpdatedBlock block;
335  {
336  WAIT_LOCK(cs_blockchange, lock);
337  if (timeout) {
338  cond_blockchange.wait_for(
339  lock, std::chrono::milliseconds(timeout),
341  return latestblock.hash == hash || !IsRPCRunning();
342  });
343  } else {
344  cond_blockchange.wait(
345  lock,
347  return latestblock.hash == hash || !IsRPCRunning();
348  });
349  }
350  block = latestblock;
351  }
352 
354  ret.pushKV("hash", block.hash.GetHex());
355  ret.pushKV("height", block.height);
356  return ret;
357  },
358  };
359 }
360 
362  return RPCHelpMan{
363  "waitforblockheight",
364  "Waits for (at least) block height and returns the height and "
365  "hash\nof the current tip.\n"
366  "\nReturns the current block on timeout or exit.\n",
367  {
369  "Block height to wait for."},
370  {"timeout", RPCArg::Type::NUM, /* default */ "0",
371  "Time in milliseconds to wait for a response. 0 indicates no "
372  "timeout."},
373  },
375  "",
376  "",
377  {
378  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
379  {RPCResult::Type::NUM, "height", "Block height"},
380  }},
381  RPCExamples{HelpExampleCli("waitforblockheight", "100 1000") +
382  HelpExampleRpc("waitforblockheight", "100, 1000")},
383  [&](const RPCHelpMan &self, const Config &config,
384  const JSONRPCRequest &request) -> UniValue {
385  int timeout = 0;
386 
387  int height = request.params[0].get_int();
388 
389  if (!request.params[1].isNull()) {
390  timeout = request.params[1].get_int();
391  }
392 
393  CUpdatedBlock block;
394  {
395  WAIT_LOCK(cs_blockchange, lock);
396  if (timeout) {
397  cond_blockchange.wait_for(
398  lock, std::chrono::milliseconds(timeout),
400  return latestblock.height >= height ||
401  !IsRPCRunning();
402  });
403  } else {
404  cond_blockchange.wait(
405  lock,
407  return latestblock.height >= height ||
408  !IsRPCRunning();
409  });
410  }
411  block = latestblock;
412  }
414  ret.pushKV("hash", block.hash.GetHex());
415  ret.pushKV("height", block.height);
416  return ret;
417  },
418  };
419 }
420 
422  return RPCHelpMan{
423  "syncwithvalidationinterfacequeue",
424  "Waits for the validation interface queue to catch up on everything "
425  "that was there when we entered this function.\n",
426  {},
428  RPCExamples{HelpExampleCli("syncwithvalidationinterfacequeue", "") +
429  HelpExampleRpc("syncwithvalidationinterfacequeue", "")},
430  [&](const RPCHelpMan &self, const Config &config,
431  const JSONRPCRequest &request) -> UniValue {
433  return NullUniValue;
434  },
435  };
436 }
437 
439  return RPCHelpMan{
440  "getdifficulty",
441  "Returns the proof-of-work difficulty as a multiple of the minimum "
442  "difficulty.\n",
443  {},
445  "the proof-of-work difficulty as a multiple of the minimum "
446  "difficulty."},
447  RPCExamples{HelpExampleCli("getdifficulty", "") +
448  HelpExampleRpc("getdifficulty", "")},
449  [&](const RPCHelpMan &self, const Config &config,
450  const JSONRPCRequest &request) -> UniValue {
451  ChainstateManager &chainman = EnsureAnyChainman(request.context);
452  LOCK(cs_main);
453  return GetDifficulty(chainman.ActiveTip());
454  },
455  };
456 }
457 
458 static std::vector<RPCResult> MempoolEntryDescription() {
459  const auto &ticker = Currency::get().ticker;
460  return {
461  RPCResult{RPCResult::Type::NUM, "size", "transaction size."},
463  "local time transaction entered pool in seconds since 1 Jan "
464  "1970 GMT"},
466  "block height when transaction entered pool"},
468  "fees",
469  "",
470  {{
472  "transaction fee in " + ticker},
474  "transaction fee with fee deltas used for "
475  "mining priority in " +
476  ticker},
477  }}},
478  RPCResult{
480  "depends",
481  "unconfirmed transactions used as inputs for this transaction",
482  {RPCResult{RPCResult::Type::STR_HEX, "transactionid",
483  "parent transaction id"}}},
484  RPCResult{
486  "spentby",
487  "unconfirmed transactions spending outputs from this transaction",
488  {RPCResult{RPCResult::Type::STR_HEX, "transactionid",
489  "child transaction id"}}},
490  RPCResult{RPCResult::Type::BOOL, "unbroadcast",
491  "Whether this transaction is currently unbroadcast (initial "
492  "broadcast not yet acknowledged by any peers)"},
493  };
494 }
495 
496 static void entryToJSON(const CTxMemPool &pool, UniValue &info,
497  const CTxMemPoolEntry &e)
498  EXCLUSIVE_LOCKS_REQUIRED(pool.cs) {
499  AssertLockHeld(pool.cs);
500 
501  UniValue fees(UniValue::VOBJ);
502  fees.pushKV("base", e.GetFee());
503  fees.pushKV("modified", e.GetModifiedFee());
504  info.pushKV("fees", fees);
505 
506  info.pushKV("size", (int)e.GetTxSize());
507  info.pushKV("time", count_seconds(e.GetTime()));
508  info.pushKV("height", (int)e.GetHeight());
509  const CTransaction &tx = e.GetTx();
510  std::set<std::string> setDepends;
511  for (const CTxIn &txin : tx.vin) {
512  if (pool.exists(txin.prevout.GetTxId())) {
513  setDepends.insert(txin.prevout.GetTxId().ToString());
514  }
515  }
516 
517  UniValue depends(UniValue::VARR);
518  for (const std::string &dep : setDepends) {
519  depends.push_back(dep);
520  }
521 
522  info.pushKV("depends", depends);
523 
524  UniValue spent(UniValue::VARR);
525  for (const CTxMemPoolEntry &child : e.GetMemPoolChildrenConst()) {
526  spent.push_back(child.GetTx().GetId().ToString());
527  }
528 
529  info.pushKV("spentby", spent);
530  info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetId()));
531 }
532 
533 UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose,
534  bool include_mempool_sequence) {
535  if (verbose) {
536  if (include_mempool_sequence) {
537  throw JSONRPCError(
539  "Verbose results cannot contain mempool sequence values.");
540  }
541  LOCK(pool.cs);
543  for (const CTxMemPoolEntry &e : pool.mapTx) {
544  const TxId &txid = e.GetTx().GetId();
545  UniValue info(UniValue::VOBJ);
546  entryToJSON(pool, info, e);
547  // Mempool has unique entries so there is no advantage in using
548  // UniValue::pushKV, which checks if the key already exists in O(N).
549  // UniValue::__pushKV is used instead which currently is O(1).
550  o.__pushKV(txid.ToString(), info);
551  }
552  return o;
553  } else {
554  uint64_t mempool_sequence;
555  std::vector<TxId> vtxids;
556  {
557  LOCK(pool.cs);
558  pool.getAllTxIds(vtxids);
559  mempool_sequence = pool.GetSequence();
560  }
562  for (const TxId &txid : vtxids) {
563  a.push_back(txid.ToString());
564  }
565 
566  if (!include_mempool_sequence) {
567  return a;
568  } else {
570  o.pushKV("txids", a);
571  o.pushKV("mempool_sequence", mempool_sequence);
572  return o;
573  }
574  }
575 }
576 
578  return RPCHelpMan{
579  "getrawmempool",
580  "Returns all transaction ids in memory pool as a json array of "
581  "string transaction ids.\n"
582  "\nHint: use getmempoolentry to fetch a specific transaction from the "
583  "mempool.\n",
584  {
585  {"verbose", RPCArg::Type::BOOL, /* default */ "false",
586  "True for a json object, false for array of transaction ids"},
587  {"mempool_sequence", RPCArg::Type::BOOL, /* default */ "false",
588  "If verbose=false, returns a json object with transaction list "
589  "and mempool sequence number attached."},
590  },
591  {
592  RPCResult{"for verbose = false",
594  "",
595  "",
596  {
597  {RPCResult::Type::STR_HEX, "", "The transaction id"},
598  }},
599  RPCResult{"for verbose = true",
601  "",
602  "",
603  {
604  {RPCResult::Type::OBJ, "transactionid", "",
606  }},
607  RPCResult{
608  "for verbose = false and mempool_sequence = true",
610  "",
611  "",
612  {
614  "txids",
615  "",
616  {
617  {RPCResult::Type::STR_HEX, "", "The transaction id"},
618  }},
619  {RPCResult::Type::NUM, "mempool_sequence",
620  "The mempool sequence value."},
621  }},
622  },
623  RPCExamples{HelpExampleCli("getrawmempool", "true") +
624  HelpExampleRpc("getrawmempool", "true")},
625  [&](const RPCHelpMan &self, const Config &config,
626  const JSONRPCRequest &request) -> UniValue {
627  bool fVerbose = false;
628  if (!request.params[0].isNull()) {
629  fVerbose = request.params[0].get_bool();
630  }
631 
632  bool include_mempool_sequence = false;
633  if (!request.params[1].isNull()) {
634  include_mempool_sequence = request.params[1].get_bool();
635  }
636 
637  return MempoolToJSON(EnsureAnyMemPool(request.context), fVerbose,
638  include_mempool_sequence);
639  },
640  };
641 }
642 
644  return RPCHelpMan{
645  "getmempoolancestors",
646  "If txid is in the mempool, returns all in-mempool ancestors.\n",
647  {
649  "The transaction id (must be in mempool)"},
650  {"verbose", RPCArg::Type::BOOL, /* default */ "false",
651  "True for a json object, false for array of transaction ids"},
652  },
653  {
654  RPCResult{
655  "for verbose = false",
657  "",
658  "",
660  "The transaction id of an in-mempool ancestor transaction"}}},
661  RPCResult{"for verbose = true",
663  "",
664  "",
665  {
666  {RPCResult::Type::OBJ, "transactionid", "",
668  }},
669  },
670  RPCExamples{HelpExampleCli("getmempoolancestors", "\"mytxid\"") +
671  HelpExampleRpc("getmempoolancestors", "\"mytxid\"")},
672  [&](const RPCHelpMan &self, const Config &config,
673  const JSONRPCRequest &request) -> UniValue {
674  bool fVerbose = false;
675  if (!request.params[1].isNull()) {
676  fVerbose = request.params[1].get_bool();
677  }
678 
679  TxId txid(ParseHashV(request.params[0], "parameter 1"));
680 
681  const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
682  LOCK(mempool.cs);
683 
684  CTxMemPool::txiter it = mempool.mapTx.find(txid);
685  if (it == mempool.mapTx.end()) {
687  "Transaction not in mempool");
688  }
689 
690  CTxMemPool::setEntries setAncestors;
691  mempool.CalculateMemPoolAncestors(*it, setAncestors, false);
692 
693  if (!fVerbose) {
695  for (CTxMemPool::txiter ancestorIt : setAncestors) {
696  o.push_back(ancestorIt->GetTx().GetId().ToString());
697  }
698  return o;
699  } else {
701  for (CTxMemPool::txiter ancestorIt : setAncestors) {
702  const CTxMemPoolEntry &e = *ancestorIt;
703  const TxId &_txid = e.GetTx().GetId();
704  UniValue info(UniValue::VOBJ);
705  entryToJSON(mempool, info, e);
706  o.pushKV(_txid.ToString(), info);
707  }
708  return o;
709  }
710  },
711  };
712 }
713 
715  return RPCHelpMan{
716  "getmempooldescendants",
717  "If txid is in the mempool, returns all in-mempool descendants.\n",
718  {
720  "The transaction id (must be in mempool)"},
721  {"verbose", RPCArg::Type::BOOL, /* default */ "false",
722  "True for a json object, false for array of transaction ids"},
723  },
724  {
725  RPCResult{"for verbose = false",
727  "",
728  "",
730  "The transaction id of an in-mempool descendant "
731  "transaction"}}},
732  RPCResult{"for verbose = true",
734  "",
735  "",
736  {
737  {RPCResult::Type::OBJ, "transactionid", "",
739  }},
740  },
741  RPCExamples{HelpExampleCli("getmempooldescendants", "\"mytxid\"") +
742  HelpExampleRpc("getmempooldescendants", "\"mytxid\"")},
743  [&](const RPCHelpMan &self, const Config &config,
744  const JSONRPCRequest &request) -> UniValue {
745  bool fVerbose = false;
746  if (!request.params[1].isNull()) {
747  fVerbose = request.params[1].get_bool();
748  }
749 
750  TxId txid(ParseHashV(request.params[0], "parameter 1"));
751 
752  const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
753  LOCK(mempool.cs);
754 
755  CTxMemPool::txiter it = mempool.mapTx.find(txid);
756  if (it == mempool.mapTx.end()) {
758  "Transaction not in mempool");
759  }
760 
761  CTxMemPool::setEntries setDescendants;
762  mempool.CalculateDescendants(it, setDescendants);
763  // CTxMemPool::CalculateDescendants will include the given tx
764  setDescendants.erase(it);
765 
766  if (!fVerbose) {
768  for (CTxMemPool::txiter descendantIt : setDescendants) {
769  o.push_back(descendantIt->GetTx().GetId().ToString());
770  }
771 
772  return o;
773  } else {
775  for (CTxMemPool::txiter descendantIt : setDescendants) {
776  const CTxMemPoolEntry &e = *descendantIt;
777  const TxId &_txid = e.GetTx().GetId();
778  UniValue info(UniValue::VOBJ);
779  entryToJSON(mempool, info, e);
780  o.pushKV(_txid.ToString(), info);
781  }
782  return o;
783  }
784  },
785  };
786 }
787 
789  return RPCHelpMan{
790  "getmempoolentry",
791  "Returns mempool data for given transaction\n",
792  {
794  "The transaction id (must be in mempool)"},
795  },
797  RPCExamples{HelpExampleCli("getmempoolentry", "\"mytxid\"") +
798  HelpExampleRpc("getmempoolentry", "\"mytxid\"")},
799  [&](const RPCHelpMan &self, const Config &config,
800  const JSONRPCRequest &request) -> UniValue {
801  TxId txid(ParseHashV(request.params[0], "parameter 1"));
802 
803  const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
804  LOCK(mempool.cs);
805 
806  CTxMemPool::txiter it = mempool.mapTx.find(txid);
807  if (it == mempool.mapTx.end()) {
809  "Transaction not in mempool");
810  }
811 
812  const CTxMemPoolEntry &e = *it;
813  UniValue info(UniValue::VOBJ);
814  entryToJSON(mempool, info, e);
815  return info;
816  },
817  };
818 }
819 
821  return RPCHelpMan{
822  "getblockfrompeer",
823  "\nAttempt to fetch block from a given peer.\n"
824  "\nWe must have the header for this block, e.g. using submitheader.\n"
825  "Subsequent calls for the same block and a new peer will cause the "
826  "response from the previous peer to be ignored.\n"
827  "\nReturns an empty JSON object if the request was successfully "
828  "scheduled.",
829  {
831  "The block hash to try to fetch"},
833  "The peer to fetch it from (see getpeerinfo for peer IDs)"},
834  },
835  RPCResult{RPCResult::Type::OBJ_EMPTY, "", /*optional=*/false, "", {}},
836  RPCExamples{HelpExampleCli("getblockfrompeer",
837  "\"00000000c937983704a73af28acdec37b049d214a"
838  "dbda81d7e2a3dd146f6ed09\" 0") +
839  HelpExampleRpc("getblockfrompeer",
840  "\"00000000c937983704a73af28acdec37b049d214a"
841  "dbda81d7e2a3dd146f6ed09\" 0")},
842  [&](const RPCHelpMan &self, const Config &config,
843  const JSONRPCRequest &request) -> UniValue {
844  const NodeContext &node = EnsureAnyNodeContext(request.context);
846  PeerManager &peerman = EnsurePeerman(node);
847 
848  const BlockHash block_hash{
849  ParseHashV(request.params[0], "blockhash")};
850  const NodeId peer_id{request.params[1].get_int64()};
851 
852  const CBlockIndex *const index = WITH_LOCK(
853  cs_main,
854  return chainman.m_blockman.LookupBlockIndex(block_hash););
855 
856  if (!index) {
857  throw JSONRPCError(RPC_MISC_ERROR, "Block header missing");
858  }
859 
860  if (WITH_LOCK(::cs_main, return index->nStatus.hasData())) {
861  throw JSONRPCError(RPC_MISC_ERROR, "Block already downloaded");
862  }
863 
864  if (const auto err{peerman.FetchBlock(config, peer_id, *index)}) {
865  throw JSONRPCError(RPC_MISC_ERROR, err.value());
866  }
867  return UniValue::VOBJ;
868  },
869  };
870 }
871 
873  return RPCHelpMan{
874  "getblockhash",
875  "Returns hash of block in best-block-chain at height provided.\n",
876  {
878  "The height index"},
879  },
880  RPCResult{RPCResult::Type::STR_HEX, "", "The block hash"},
881  RPCExamples{HelpExampleCli("getblockhash", "1000") +
882  HelpExampleRpc("getblockhash", "1000")},
883  [&](const RPCHelpMan &self, const Config &config,
884  const JSONRPCRequest &request) -> UniValue {
885  ChainstateManager &chainman = EnsureAnyChainman(request.context);
886  LOCK(cs_main);
887  const CChain &active_chain = chainman.ActiveChain();
888 
889  int nHeight = request.params[0].get_int();
890  if (nHeight < 0 || nHeight > active_chain.Height()) {
892  "Block height out of range");
893  }
894 
895  const CBlockIndex *pblockindex = active_chain[nHeight];
896  return pblockindex->GetBlockHash().GetHex();
897  },
898  };
899 }
900 
902  return RPCHelpMan{
903  "getblockheader",
904  "If verbose is false, returns a string that is serialized, hex-encoded "
905  "data for blockheader 'hash'.\n"
906  "If verbose is true, returns an Object with information about "
907  "blockheader <hash>.\n",
908  {
910  "The block hash"},
911  {"verbose", RPCArg::Type::BOOL, /* default */ "true",
912  "true for a json object, false for the hex-encoded data"},
913  },
914  {
915  RPCResult{
916  "for verbose = true",
918  "",
919  "",
920  {
921  {RPCResult::Type::STR_HEX, "hash",
922  "the block hash (same as provided)"},
923  {RPCResult::Type::NUM, "confirmations",
924  "The number of confirmations, or -1 if the block is not "
925  "on the main chain"},
926  {RPCResult::Type::NUM, "height",
927  "The block height or index"},
928  {RPCResult::Type::NUM, "version", "The block version"},
929  {RPCResult::Type::STR_HEX, "versionHex",
930  "The block version formatted in hexadecimal"},
931  {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
932  {RPCResult::Type::NUM_TIME, "time",
933  "The block time expressed in " + UNIX_EPOCH_TIME},
934  {RPCResult::Type::NUM_TIME, "mediantime",
935  "The median block time expressed in " + UNIX_EPOCH_TIME},
936  {RPCResult::Type::NUM, "nonce", "The nonce"},
937  {RPCResult::Type::STR_HEX, "bits", "The bits"},
938  {RPCResult::Type::NUM, "difficulty", "The difficulty"},
939  {RPCResult::Type::STR_HEX, "chainwork",
940  "Expected number of hashes required to produce the "
941  "current chain"},
942  {RPCResult::Type::NUM, "nTx",
943  "The number of transactions in the block"},
944  {RPCResult::Type::STR_HEX, "previousblockhash",
945  /* optional */ true,
946  "The hash of the previous block (if available)"},
947  {RPCResult::Type::STR_HEX, "nextblockhash",
948  /* optional */ true,
949  "The hash of the next block (if available)"},
950  }},
951  RPCResult{"for verbose=false", RPCResult::Type::STR_HEX, "",
952  "A string that is serialized, hex-encoded data for block "
953  "'hash'"},
954  },
955  RPCExamples{HelpExampleCli("getblockheader",
956  "\"00000000c937983704a73af28acdec37b049d214a"
957  "dbda81d7e2a3dd146f6ed09\"") +
958  HelpExampleRpc("getblockheader",
959  "\"00000000c937983704a73af28acdec37b049d214a"
960  "dbda81d7e2a3dd146f6ed09\"")},
961  [&](const RPCHelpMan &self, const Config &config,
962  const JSONRPCRequest &request) -> UniValue {
963  BlockHash hash(ParseHashV(request.params[0], "hash"));
964 
965  bool fVerbose = true;
966  if (!request.params[1].isNull()) {
967  fVerbose = request.params[1].get_bool();
968  }
969 
970  const CBlockIndex *pblockindex;
971  const CBlockIndex *tip;
972  {
973  ChainstateManager &chainman =
974  EnsureAnyChainman(request.context);
975  LOCK(cs_main);
976  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
977  tip = chainman.ActiveTip();
978  }
979 
980  if (!pblockindex) {
982  "Block not found");
983  }
984 
985  if (!fVerbose) {
987  ssBlock << pblockindex->GetBlockHeader();
988  std::string strHex = HexStr(ssBlock);
989  return strHex;
990  }
991 
992  return blockheaderToJSON(tip, pblockindex);
993  },
994  };
995 }
996 
997 static CBlock GetBlockChecked(const Config &config, BlockManager &blockman,
998  const CBlockIndex *pblockindex) {
999  CBlock block;
1000  {
1001  LOCK(cs_main);
1002  if (blockman.IsBlockPruned(pblockindex)) {
1004  "Block not available (pruned data)");
1005  }
1006  }
1007 
1008  if (!ReadBlockFromDisk(block, pblockindex,
1009  config.GetChainParams().GetConsensus())) {
1010  // Block not found on disk. This could be because we have the block
1011  // header in our index but not yet have the block or did not accept the
1012  // block. Or if the block was pruned right after we released the lock
1013  // above.
1014  throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
1015  }
1016 
1017  return block;
1018 }
1019 
1021  const CBlockIndex *pblockindex) {
1022  CBlockUndo blockUndo;
1023 
1024  {
1025  LOCK(cs_main);
1026  if (blockman.IsBlockPruned(pblockindex)) {
1028  "Undo data not available (pruned data)");
1029  }
1030  }
1031 
1032  if (!UndoReadFromDisk(blockUndo, pblockindex)) {
1033  throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk");
1034  }
1035 
1036  return blockUndo;
1037 }
1038 
1040  return RPCHelpMan{
1041  "getblock",
1042  "If verbosity is 0 or false, returns a string that is serialized, "
1043  "hex-encoded data for block 'hash'.\n"
1044  "If verbosity is 1 or true, returns an Object with information about "
1045  "block <hash>.\n"
1046  "If verbosity is 2, returns an Object with information about block "
1047  "<hash> and information about each transaction.\n",
1048  {
1050  "The block hash"},
1051  {"verbosity|verbose", RPCArg::Type::NUM, /* default */ "1",
1052  "0 for hex-encoded data, 1 for a json object, and 2 for json "
1053  "object with transaction data"},
1054  },
1055  {
1056  RPCResult{"for verbosity = 0", RPCResult::Type::STR_HEX, "",
1057  "A string that is serialized, hex-encoded data for block "
1058  "'hash'"},
1059  RPCResult{
1060  "for verbosity = 1",
1062  "",
1063  "",
1064  {
1065  {RPCResult::Type::STR_HEX, "hash",
1066  "the block hash (same as provided)"},
1067  {RPCResult::Type::NUM, "confirmations",
1068  "The number of confirmations, or -1 if the block is not "
1069  "on the main chain"},
1070  {RPCResult::Type::NUM, "size", "The block size"},
1071  {RPCResult::Type::NUM, "height",
1072  "The block height or index"},
1073  {RPCResult::Type::NUM, "version", "The block version"},
1074  {RPCResult::Type::STR_HEX, "versionHex",
1075  "The block version formatted in hexadecimal"},
1076  {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
1078  "tx",
1079  "The transaction ids",
1080  {{RPCResult::Type::STR_HEX, "", "The transaction id"}}},
1081  {RPCResult::Type::NUM_TIME, "time",
1082  "The block time expressed in " + UNIX_EPOCH_TIME},
1083  {RPCResult::Type::NUM_TIME, "mediantime",
1084  "The median block time expressed in " + UNIX_EPOCH_TIME},
1085  {RPCResult::Type::NUM, "nonce", "The nonce"},
1086  {RPCResult::Type::STR_HEX, "bits", "The bits"},
1087  {RPCResult::Type::NUM, "difficulty", "The difficulty"},
1088  {RPCResult::Type::STR_HEX, "chainwork",
1089  "Expected number of hashes required to produce the chain "
1090  "up to this block (in hex)"},
1091  {RPCResult::Type::NUM, "nTx",
1092  "The number of transactions in the block"},
1093  {RPCResult::Type::STR_HEX, "previousblockhash",
1094  /* optional */ true,
1095  "The hash of the previous block (if available)"},
1096  {RPCResult::Type::STR_HEX, "nextblockhash",
1097  /* optional */ true,
1098  "The hash of the next block (if available)"},
1099  }},
1100  RPCResult{"for verbosity = 2",
1102  "",
1103  "",
1104  {
1106  "Same output as verbosity = 1"},
1108  "tx",
1109  "",
1110  {
1112  "",
1113  "",
1114  {
1116  "The transactions in the format of the "
1117  "getrawtransaction RPC. Different from "
1118  "verbosity = 1 \"tx\" result"},
1120  "The transaction fee in " +
1121  Currency::get().ticker +
1122  ", omitted if block undo data is not "
1123  "available"},
1124  }},
1125  }},
1126  }},
1127  },
1128  RPCExamples{
1129  HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d"
1130  "214adbda81d7e2a3dd146f6ed09\"") +
1131  HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d"
1132  "214adbda81d7e2a3dd146f6ed09\"")},
1133  [&](const RPCHelpMan &self, const Config &config,
1134  const JSONRPCRequest &request) -> UniValue {
1135  BlockHash hash(ParseHashV(request.params[0], "blockhash"));
1136 
1137  int verbosity = 1;
1138  if (!request.params[1].isNull()) {
1139  if (request.params[1].isNum()) {
1140  verbosity = request.params[1].get_int();
1141  } else {
1142  verbosity = request.params[1].get_bool() ? 1 : 0;
1143  }
1144  }
1145 
1146  const CBlockIndex *pblockindex;
1147  const CBlockIndex *tip;
1148  ChainstateManager &chainman = EnsureAnyChainman(request.context);
1149  {
1150  LOCK(cs_main);
1151  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
1152  tip = chainman.ActiveTip();
1153 
1154  if (!pblockindex) {
1156  "Block not found");
1157  }
1158  }
1159 
1160  const CBlock block =
1161  GetBlockChecked(config, chainman.m_blockman, pblockindex);
1162 
1163  if (verbosity <= 0) {
1164  CDataStream ssBlock(SER_NETWORK,
1166  ssBlock << block;
1167  std::string strHex = HexStr(ssBlock);
1168  return strHex;
1169  }
1170 
1171  return blockToJSON(chainman.m_blockman, block, tip, pblockindex,
1172  verbosity >= 2);
1173  },
1174  };
1175 }
1176 
1178  return RPCHelpMan{
1179  "pruneblockchain",
1180  "",
1181  {
1183  "The block height to prune up to. May be set to a discrete "
1184  "height, or to a " +
1185  UNIX_EPOCH_TIME +
1186  "\n"
1187  " to prune blocks whose block time is at "
1188  "least 2 hours older than the provided timestamp."},
1189  },
1190  RPCResult{RPCResult::Type::NUM, "", "Height of the last block pruned"},
1191  RPCExamples{HelpExampleCli("pruneblockchain", "1000") +
1192  HelpExampleRpc("pruneblockchain", "1000")},
1193  [&](const RPCHelpMan &self, const Config &config,
1194  const JSONRPCRequest &request) -> UniValue {
1195  if (!node::fPruneMode) {
1196  throw JSONRPCError(
1198  "Cannot prune blocks because node is not in prune mode.");
1199  }
1200 
1201  ChainstateManager &chainman = EnsureAnyChainman(request.context);
1202  LOCK(cs_main);
1203  Chainstate &active_chainstate = chainman.ActiveChainstate();
1204  CChain &active_chain = active_chainstate.m_chain;
1205 
1206  int heightParam = request.params[0].get_int();
1207  if (heightParam < 0) {
1209  "Negative block height.");
1210  }
1211 
1212  // Height value more than a billion is too high to be a block
1213  // height, and too low to be a block time (corresponds to timestamp
1214  // from Sep 2001).
1215  if (heightParam > 1000000000) {
1216  // Add a 2 hour buffer to include blocks which might have had
1217  // old timestamps
1218  const CBlockIndex *pindex = active_chain.FindEarliestAtLeast(
1219  heightParam - TIMESTAMP_WINDOW, 0);
1220  if (!pindex) {
1222  "Could not find block with at least the "
1223  "specified timestamp.");
1224  }
1225  heightParam = pindex->nHeight;
1226  }
1227 
1228  unsigned int height = (unsigned int)heightParam;
1229  unsigned int chainHeight = (unsigned int)active_chain.Height();
1230  if (chainHeight < config.GetChainParams().PruneAfterHeight()) {
1232  "Blockchain is too short for pruning.");
1233  } else if (height > chainHeight) {
1234  throw JSONRPCError(
1236  "Blockchain is shorter than the attempted prune height.");
1237  } else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) {
1239  "Attempt to prune blocks close to the tip. "
1240  "Retaining the minimum number of blocks.\n");
1241  height = chainHeight - MIN_BLOCKS_TO_KEEP;
1242  }
1243 
1244  PruneBlockFilesManual(active_chainstate, height);
1245  const CBlockIndex *block = CHECK_NONFATAL(active_chain.Tip());
1246  const CBlockIndex *last_block = node::GetFirstStoredBlock(block);
1247 
1248  return static_cast<uint64_t>(last_block->nHeight);
1249  },
1250  };
1251 }
1252 
1253 static CoinStatsHashType ParseHashType(const std::string &hash_type_input) {
1254  if (hash_type_input == "hash_serialized") {
1255  return CoinStatsHashType::HASH_SERIALIZED;
1256  } else if (hash_type_input == "muhash") {
1257  return CoinStatsHashType::MUHASH;
1258  } else if (hash_type_input == "none") {
1259  return CoinStatsHashType::NONE;
1260  } else {
1261  throw JSONRPCError(
1263  strprintf("%s is not a valid hash_type", hash_type_input));
1264  }
1265 }
1266 
1268  return RPCHelpMan{
1269  "gettxoutsetinfo",
1270  "Returns statistics about the unspent transaction output set.\n"
1271  "Note this call may take some time if you are not using "
1272  "coinstatsindex.\n",
1273  {
1274  {"hash_type", RPCArg::Type::STR, /* default */ "hash_serialized",
1275  "Which UTXO set hash should be calculated. Options: "
1276  "'hash_serialized' (the legacy algorithm), 'muhash', 'none'."},
1277  {"hash_or_height",
1280  "The block hash or height of the target height (only available "
1281  "with coinstatsindex).",
1282  "",
1283  {"", "string or numeric"}},
1284  {"use_index", RPCArg::Type::BOOL, /* default */ "true",
1285  "Use coinstatsindex, if available."},
1286  },
1287  RPCResult{
1289  "",
1290  "",
1291  {
1292  {RPCResult::Type::NUM, "height",
1293  "The current block height (index)"},
1294  {RPCResult::Type::STR_HEX, "bestblock",
1295  "The hash of the block at the tip of the chain"},
1296  {RPCResult::Type::NUM, "txouts",
1297  "The number of unspent transaction outputs"},
1298  {RPCResult::Type::NUM, "bogosize",
1299  "Database-independent, meaningless metric indicating "
1300  "the UTXO set size"},
1301  {RPCResult::Type::STR_HEX, "hash_serialized",
1302  /* optional */ true,
1303  "The serialized hash (only present if 'hash_serialized' "
1304  "hash_type is chosen)"},
1305  {RPCResult::Type::STR_HEX, "muhash", /* optional */ true,
1306  "The serialized hash (only present if 'muhash' "
1307  "hash_type is chosen)"},
1308  {RPCResult::Type::NUM, "transactions",
1309  "The number of transactions with unspent outputs (not "
1310  "available when coinstatsindex is used)"},
1311  {RPCResult::Type::NUM, "disk_size",
1312  "The estimated size of the chainstate on disk (not "
1313  "available when coinstatsindex is used)"},
1314  {RPCResult::Type::STR_AMOUNT, "total_amount",
1315  "The total amount"},
1316  {RPCResult::Type::STR_AMOUNT, "total_unspendable_amount",
1317  "The total amount of coins permanently excluded from the UTXO "
1318  "set (only available if coinstatsindex is used)"},
1320  "block_info",
1321  "Info on amounts in the block at this block height (only "
1322  "available if coinstatsindex is used)",
1323  {{RPCResult::Type::STR_AMOUNT, "prevout_spent",
1324  "Total amount of all prevouts spent in this block"},
1325  {RPCResult::Type::STR_AMOUNT, "coinbase",
1326  "Coinbase subsidy amount of this block"},
1327  {RPCResult::Type::STR_AMOUNT, "new_outputs_ex_coinbase",
1328  "Total amount of new outputs created by this block"},
1329  {RPCResult::Type::STR_AMOUNT, "unspendable",
1330  "Total amount of unspendable outputs created in this block"},
1332  "unspendables",
1333  "Detailed view of the unspendable categories",
1334  {
1335  {RPCResult::Type::STR_AMOUNT, "genesis_block",
1336  "The unspendable amount of the Genesis block subsidy"},
1337  {RPCResult::Type::STR_AMOUNT, "bip30",
1338  "Transactions overridden by duplicates (no longer "
1339  "possible with BIP30)"},
1340  {RPCResult::Type::STR_AMOUNT, "scripts",
1341  "Amounts sent to scripts that are unspendable (for "
1342  "example OP_RETURN outputs)"},
1343  {RPCResult::Type::STR_AMOUNT, "unclaimed_rewards",
1344  "Fee rewards that miners did not claim in their "
1345  "coinbase transaction"},
1346  }}}},
1347  }},
1348  RPCExamples{
1349  HelpExampleCli("gettxoutsetinfo", "") +
1350  HelpExampleCli("gettxoutsetinfo", R"("none")") +
1351  HelpExampleCli("gettxoutsetinfo", R"("none" 1000)") +
1353  "gettxoutsetinfo",
1354  R"("none" '"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"')") +
1355  HelpExampleRpc("gettxoutsetinfo", "") +
1356  HelpExampleRpc("gettxoutsetinfo", R"("none")") +
1357  HelpExampleRpc("gettxoutsetinfo", R"("none", 1000)") +
1359  "gettxoutsetinfo",
1360  R"("none", "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09")")},
1361  [&](const RPCHelpMan &self, const Config &config,
1362  const JSONRPCRequest &request) -> UniValue {
1363  UniValue ret(UniValue::VOBJ);
1364 
1365  const CBlockIndex *pindex{nullptr};
1366  const CoinStatsHashType hash_type{
1367  request.params[0].isNull()
1368  ? CoinStatsHashType::HASH_SERIALIZED
1369  : ParseHashType(request.params[0].get_str())};
1370  CCoinsStats stats{hash_type};
1371  stats.index_requested =
1372  request.params[2].isNull() || request.params[2].get_bool();
1373 
1374  NodeContext &node = EnsureAnyNodeContext(request.context);
1375  ChainstateManager &chainman = EnsureChainman(node);
1376  Chainstate &active_chainstate = chainman.ActiveChainstate();
1377  active_chainstate.ForceFlushStateToDisk();
1378 
1379  CCoinsView *coins_view;
1380  BlockManager *blockman;
1381  {
1382  LOCK(::cs_main);
1383  coins_view = &active_chainstate.CoinsDB();
1384  blockman = &active_chainstate.m_blockman;
1385  pindex = blockman->LookupBlockIndex(coins_view->GetBestBlock());
1386  }
1387 
1388  if (!request.params[1].isNull()) {
1389  if (!g_coin_stats_index) {
1391  "Querying specific block heights "
1392  "requires coinstatsindex");
1393  }
1394 
1395  if (stats.m_hash_type == CoinStatsHashType::HASH_SERIALIZED) {
1397  "hash_serialized hash type cannot be "
1398  "queried for a specific block");
1399  }
1400 
1401  pindex = ParseHashOrHeight(request.params[1], chainman);
1402  }
1403 
1404  if (stats.index_requested && g_coin_stats_index) {
1405  if (!g_coin_stats_index->BlockUntilSyncedToCurrentChain()) {
1406  const IndexSummary summary{
1407  g_coin_stats_index->GetSummary()};
1408 
1409  // If a specific block was requested and the index has
1410  // already synced past that height, we can return the data
1411  // already even though the index is not fully synced yet.
1412  if (pindex->nHeight > summary.best_block_height) {
1413  throw JSONRPCError(
1415  strprintf(
1416  "Unable to get data because coinstatsindex is "
1417  "still syncing. Current height: %d",
1418  summary.best_block_height));
1419  }
1420  }
1421  }
1422 
1423  if (GetUTXOStats(coins_view, *blockman, stats,
1424  node.rpc_interruption_point, pindex)) {
1425  ret.pushKV("height", int64_t(stats.nHeight));
1426  ret.pushKV("bestblock", stats.hashBlock.GetHex());
1427  ret.pushKV("txouts", int64_t(stats.nTransactionOutputs));
1428  ret.pushKV("bogosize", int64_t(stats.nBogoSize));
1429  if (hash_type == CoinStatsHashType::HASH_SERIALIZED) {
1430  ret.pushKV("hash_serialized",
1431  stats.hashSerialized.GetHex());
1432  }
1433  if (hash_type == CoinStatsHashType::MUHASH) {
1434  ret.pushKV("muhash", stats.hashSerialized.GetHex());
1435  }
1436  ret.pushKV("total_amount", stats.nTotalAmount);
1437  if (!stats.index_used) {
1438  ret.pushKV("transactions",
1439  static_cast<int64_t>(stats.nTransactions));
1440  ret.pushKV("disk_size", stats.nDiskSize);
1441  } else {
1442  ret.pushKV("total_unspendable_amount",
1443  stats.total_unspendable_amount);
1444 
1445  CCoinsStats prev_stats{hash_type};
1446 
1447  if (pindex->nHeight > 0) {
1448  GetUTXOStats(coins_view, *blockman, prev_stats,
1449  node.rpc_interruption_point,
1450  pindex->pprev);
1451  }
1452 
1453  UniValue block_info(UniValue::VOBJ);
1454  block_info.pushKV(
1455  "prevout_spent",
1456  stats.total_prevout_spent_amount -
1457  prev_stats.total_prevout_spent_amount);
1458  block_info.pushKV("coinbase",
1459  stats.total_coinbase_amount -
1460  prev_stats.total_coinbase_amount);
1461  block_info.pushKV(
1462  "new_outputs_ex_coinbase",
1463  stats.total_new_outputs_ex_coinbase_amount -
1464  prev_stats.total_new_outputs_ex_coinbase_amount);
1465  block_info.pushKV("unspendable",
1466  stats.total_unspendable_amount -
1467  prev_stats.total_unspendable_amount);
1468 
1469  UniValue unspendables(UniValue::VOBJ);
1470  unspendables.pushKV(
1471  "genesis_block",
1472  stats.total_unspendables_genesis_block -
1473  prev_stats.total_unspendables_genesis_block);
1474  unspendables.pushKV(
1475  "bip30", stats.total_unspendables_bip30 -
1476  prev_stats.total_unspendables_bip30);
1477  unspendables.pushKV(
1478  "scripts", stats.total_unspendables_scripts -
1479  prev_stats.total_unspendables_scripts);
1480  unspendables.pushKV(
1481  "unclaimed_rewards",
1482  stats.total_unspendables_unclaimed_rewards -
1483  prev_stats.total_unspendables_unclaimed_rewards);
1484  block_info.pushKV("unspendables", unspendables);
1485 
1486  ret.pushKV("block_info", block_info);
1487  }
1488  } else {
1490  "Unable to read UTXO set");
1491  }
1492  return ret;
1493  },
1494  };
1495 }
1496 
1498  return RPCHelpMan{
1499  "gettxout",
1500  "Returns details about an unspent transaction output.\n",
1501  {
1503  "The transaction id"},
1504  {"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"},
1505  {"include_mempool", RPCArg::Type::BOOL, /* default */ "true",
1506  "Whether to include the mempool. Note that an unspent output that "
1507  "is spent in the mempool won't appear."},
1508  },
1509  {
1510  RPCResult{"If the UTXO was not found", RPCResult::Type::NONE, "",
1511  ""},
1512  RPCResult{
1513  "Otherwise",
1515  "",
1516  "",
1517  {
1518  {RPCResult::Type::STR_HEX, "bestblock",
1519  "The hash of the block at the tip of the chain"},
1520  {RPCResult::Type::NUM, "confirmations",
1521  "The number of confirmations"},
1522  {RPCResult::Type::STR_AMOUNT, "value",
1523  "The transaction value in " + Currency::get().ticker},
1525  "scriptPubKey",
1526  "",
1527  {
1528  {RPCResult::Type::STR_HEX, "asm", ""},
1529  {RPCResult::Type::STR_HEX, "hex", ""},
1530  {RPCResult::Type::NUM, "reqSigs",
1531  "Number of required signatures"},
1532  {RPCResult::Type::STR_HEX, "type",
1533  "The type, eg pubkeyhash"},
1535  "addresses",
1536  "array of eCash addresses",
1537  {{RPCResult::Type::STR, "address", "eCash address"}}},
1538  }},
1539  {RPCResult::Type::BOOL, "coinbase", "Coinbase or not"},
1540  }},
1541  },
1542  RPCExamples{"\nGet unspent transactions\n" +
1543  HelpExampleCli("listunspent", "") + "\nView the details\n" +
1544  HelpExampleCli("gettxout", "\"txid\" 1") +
1545  "\nAs a JSON-RPC call\n" +
1546  HelpExampleRpc("gettxout", "\"txid\", 1")},
1547  [&](const RPCHelpMan &self, const Config &config,
1548  const JSONRPCRequest &request) -> UniValue {
1549  NodeContext &node = EnsureAnyNodeContext(request.context);
1550  ChainstateManager &chainman = EnsureChainman(node);
1551  LOCK(cs_main);
1552 
1553  UniValue ret(UniValue::VOBJ);
1554 
1555  TxId txid(ParseHashV(request.params[0], "txid"));
1556  int n = request.params[1].get_int();
1557  COutPoint out(txid, n);
1558  bool fMempool = true;
1559  if (!request.params[2].isNull()) {
1560  fMempool = request.params[2].get_bool();
1561  }
1562 
1563  Coin coin;
1564  Chainstate &active_chainstate = chainman.ActiveChainstate();
1565  CCoinsViewCache *coins_view = &active_chainstate.CoinsTip();
1566 
1567  if (fMempool) {
1568  const CTxMemPool &mempool = EnsureMemPool(node);
1569  LOCK(mempool.cs);
1570  CCoinsViewMemPool view(coins_view, mempool);
1571  if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
1572  return NullUniValue;
1573  }
1574  } else {
1575  if (!coins_view->GetCoin(out, coin)) {
1576  return NullUniValue;
1577  }
1578  }
1579 
1580  const CBlockIndex *pindex =
1581  active_chainstate.m_blockman.LookupBlockIndex(
1582  coins_view->GetBestBlock());
1583  ret.pushKV("bestblock", pindex->GetBlockHash().GetHex());
1584  if (coin.GetHeight() == MEMPOOL_HEIGHT) {
1585  ret.pushKV("confirmations", 0);
1586  } else {
1587  ret.pushKV("confirmations",
1588  int64_t(pindex->nHeight - coin.GetHeight() + 1));
1589  }
1590  ret.pushKV("value", coin.GetTxOut().nValue);
1592  ScriptPubKeyToUniv(coin.GetTxOut().scriptPubKey, o, true);
1593  ret.pushKV("scriptPubKey", o);
1594  ret.pushKV("coinbase", coin.IsCoinBase());
1595 
1596  return ret;
1597  },
1598  };
1599 }
1600 
1602  return RPCHelpMan{
1603  "verifychain",
1604  "Verifies blockchain database.\n",
1605  {
1606  {"checklevel", RPCArg::Type::NUM,
1607  /* default */ strprintf("%d, range=0-4", DEFAULT_CHECKLEVEL),
1608  strprintf("How thorough the block verification is:\n - %s",
1609  Join(CHECKLEVEL_DOC, "\n- "))},
1610  {"nblocks", RPCArg::Type::NUM,
1611  /* default */ strprintf("%d, 0=all", DEFAULT_CHECKBLOCKS),
1612  "The number of blocks to check."},
1613  },
1614  RPCResult{RPCResult::Type::BOOL, "", "Verified or not"},
1615  RPCExamples{HelpExampleCli("verifychain", "") +
1616  HelpExampleRpc("verifychain", "")},
1617  [&](const RPCHelpMan &self, const Config &config,
1618  const JSONRPCRequest &request) -> UniValue {
1619  const int check_level(request.params[0].isNull()
1621  : request.params[0].get_int());
1622  const int check_depth{request.params[1].isNull()
1624  : request.params[1].get_int()};
1625 
1626  ChainstateManager &chainman = EnsureAnyChainman(request.context);
1627  LOCK(cs_main);
1628 
1629  Chainstate &active_chainstate = chainman.ActiveChainstate();
1630  return CVerifyDB().VerifyDB(active_chainstate, config,
1631  active_chainstate.CoinsTip(),
1632  check_level, check_depth);
1633  },
1634  };
1635 }
1636 
1638  return RPCHelpMan{
1639  "getblockchaininfo",
1640  "Returns an object containing various state info regarding blockchain "
1641  "processing.\n",
1642  {},
1643  RPCResult{
1645  "",
1646  "",
1647  {
1648  {RPCResult::Type::STR, "chain",
1649  "current network name (main, test, regtest)"},
1650  {RPCResult::Type::NUM, "blocks",
1651  "the height of the most-work fully-validated chain. The "
1652  "genesis block has height 0"},
1653  {RPCResult::Type::NUM, "headers",
1654  "the current number of headers we have validated"},
1655  {RPCResult::Type::STR, "bestblockhash",
1656  "the hash of the currently best block"},
1657  {RPCResult::Type::NUM, "difficulty", "the current difficulty"},
1658  {RPCResult::Type::NUM_TIME, "time",
1659  "The block time expressed in " + UNIX_EPOCH_TIME},
1660  {RPCResult::Type::NUM_TIME, "mediantime",
1661  "The median block time expressed in " + UNIX_EPOCH_TIME},
1662  {RPCResult::Type::NUM, "verificationprogress",
1663  "estimate of verification progress [0..1]"},
1664  {RPCResult::Type::BOOL, "initialblockdownload",
1665  "(debug information) estimate of whether this node is in "
1666  "Initial Block Download mode"},
1667  {RPCResult::Type::STR_HEX, "chainwork",
1668  "total amount of work in active chain, in hexadecimal"},
1669  {RPCResult::Type::NUM, "size_on_disk",
1670  "the estimated size of the block and undo files on disk"},
1671  {RPCResult::Type::BOOL, "pruned",
1672  "if the blocks are subject to pruning"},
1673  {RPCResult::Type::NUM, "pruneheight",
1674  "lowest-height complete block stored (only present if pruning "
1675  "is enabled)"},
1676  {RPCResult::Type::BOOL, "automatic_pruning",
1677  "whether automatic pruning is enabled (only present if "
1678  "pruning is enabled)"},
1679  {RPCResult::Type::NUM, "prune_target_size",
1680  "the target size used by pruning (only present if automatic "
1681  "pruning is enabled)"},
1683  "softforks",
1684  "status of softforks. DEPRECATED: Only displayed if the "
1685  "-deprecatedrpc=softforks "
1686  "option is set",
1687  {
1689  "xxxx",
1690  "name of the softfork",
1691  {
1692  {RPCResult::Type::STR, "type",
1693  "one of \"buried\", \"bip9\""},
1695  "bip9",
1696  "status of bip9 softforks (only for \"bip9\" type)",
1697  {
1698  {RPCResult::Type::STR, "status",
1699  "one of \"defined\", \"started\", "
1700  "\"locked_in\", \"active\", \"failed\""},
1701  {RPCResult::Type::NUM, "bit",
1702  "the bit (0-28) in the block version field "
1703  "used to signal this softfork (only for "
1704  "\"started\" status)"},
1705  {RPCResult::Type::NUM_TIME, "start_time",
1706  "the minimum median time past of a block at "
1707  "which the bit gains its meaning"},
1708  {RPCResult::Type::NUM_TIME, "timeout",
1709  "the median time past of a block at which the "
1710  "deployment is considered failed if not yet "
1711  "locked in"},
1712  {RPCResult::Type::NUM, "since",
1713  "height of the first block to which the status "
1714  "applies"},
1716  "statistics",
1717  "numeric statistics about BIP9 signalling for "
1718  "a softfork",
1719  {
1720  {RPCResult::Type::NUM, "period",
1721  "the length in blocks of the BIP9 "
1722  "signalling period"},
1723  {RPCResult::Type::NUM, "threshold",
1724  "the number of blocks with the version "
1725  "bit set required to activate the "
1726  "feature"},
1727  {RPCResult::Type::NUM, "elapsed",
1728  "the number of blocks elapsed since the "
1729  "beginning of the current period"},
1730  {RPCResult::Type::NUM, "count",
1731  "the number of blocks with the version "
1732  "bit set in the current period"},
1733  {RPCResult::Type::BOOL, "possible",
1734  "returns false if there are not enough "
1735  "blocks left in this period to pass "
1736  "activation threshold"},
1737  }},
1738  }},
1739  {RPCResult::Type::NUM, "height",
1740  "height of the first block which the rules are or "
1741  "will be enforced (only for \"buried\" type, or "
1742  "\"bip9\" type with \"active\" status)"},
1743  {RPCResult::Type::BOOL, "active",
1744  "true if the rules are enforced for the mempool and "
1745  "the next block"},
1746  }},
1747  }},
1748  {RPCResult::Type::STR, "warnings",
1749  "any network and blockchain warnings"},
1750  }},
1751  RPCExamples{HelpExampleCli("getblockchaininfo", "") +
1752  HelpExampleRpc("getblockchaininfo", "")},
1753  [&](const RPCHelpMan &self, const Config &config,
1754  const JSONRPCRequest &request) -> UniValue {
1755  const CChainParams &chainparams = config.GetChainParams();
1756 
1757  ChainstateManager &chainman = EnsureAnyChainman(request.context);
1758  LOCK(cs_main);
1759  Chainstate &active_chainstate = chainman.ActiveChainstate();
1760 
1761  const CBlockIndex &tip{
1762  *CHECK_NONFATAL(active_chainstate.m_chain.Tip())};
1763  const int height{tip.nHeight};
1764 
1765  UniValue obj(UniValue::VOBJ);
1766  obj.pushKV("chain", chainparams.NetworkIDString());
1767  obj.pushKV("blocks", height);
1768  obj.pushKV("headers", chainman.m_best_header
1769  ? chainman.m_best_header->nHeight
1770  : -1);
1771  obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
1772  obj.pushKV("difficulty", GetDifficulty(&tip));
1773  obj.pushKV("time", tip.GetBlockTime());
1774  obj.pushKV("mediantime", tip.GetMedianTimePast());
1775  obj.pushKV("verificationprogress",
1776  GuessVerificationProgress(Params().TxData(), &tip));
1777  obj.pushKV("initialblockdownload",
1778  active_chainstate.IsInitialBlockDownload());
1779  obj.pushKV("chainwork", tip.nChainWork.GetHex());
1780  obj.pushKV("size_on_disk",
1781  chainman.m_blockman.CalculateCurrentUsage());
1782  obj.pushKV("pruned", node::fPruneMode);
1783 
1784  if (node::fPruneMode) {
1785  obj.pushKV("pruneheight",
1787 
1788  // if 0, execution bypasses the whole if block.
1789  bool automatic_pruning = (gArgs.GetIntArg("-prune", 0) != 1);
1790  obj.pushKV("automatic_pruning", automatic_pruning);
1791  if (automatic_pruning) {
1792  obj.pushKV("prune_target_size", node::nPruneTarget);
1793  }
1794  }
1795 
1796  // Deprecated in v0.27.0
1797  if (IsDeprecatedRPCEnabled(gArgs, "softforks")) {
1798  // This field has been empty for a long while and the associated
1799  // code has already been removed, as there is no plan to use
1800  // BIP9 again.
1801  UniValue softforks(UniValue::VOBJ);
1802  obj.pushKV("softforks", softforks);
1803  }
1804 
1805  obj.pushKV("warnings", GetWarnings(false).original);
1806  return obj;
1807  },
1808  };
1809 }
1810 
1813  bool operator()(const CBlockIndex *a, const CBlockIndex *b) const {
1814  // Make sure that unequal blocks with the same height do not compare
1815  // equal. Use the pointers themselves to make a distinction.
1816  if (a->nHeight != b->nHeight) {
1817  return (a->nHeight > b->nHeight);
1818  }
1819 
1820  return a < b;
1821  }
1822 };
1823 
1825  return RPCHelpMan{
1826  "getchaintips",
1827  "Return information about all known tips in the block tree, including "
1828  "the main chain as well as orphaned branches.\n",
1829  {},
1830  RPCResult{
1832  "",
1833  "",
1835  "",
1836  "",
1837  {
1838  {RPCResult::Type::NUM, "height", "height of the chain tip"},
1839  {RPCResult::Type::STR_HEX, "hash", "block hash of the tip"},
1840  {RPCResult::Type::NUM, "branchlen",
1841  "zero for main chain, otherwise length of branch connecting "
1842  "the tip to the main chain"},
1843  {RPCResult::Type::STR, "status",
1844  "status of the chain, \"active\" for the main chain\n"
1845  "Possible values for status:\n"
1846  "1. \"invalid\" This branch contains at "
1847  "least one invalid block\n"
1848  "2. \"parked\" This branch contains at "
1849  "least one parked block\n"
1850  "3. \"headers-only\" Not all blocks for this "
1851  "branch are available, but the headers are valid\n"
1852  "4. \"valid-headers\" All blocks are available for "
1853  "this branch, but they were never fully validated\n"
1854  "5. \"valid-fork\" This branch is not part of "
1855  "the active chain, but is fully validated\n"
1856  "6. \"active\" This is the tip of the "
1857  "active main chain, which is certainly valid"},
1858  }}}},
1859  RPCExamples{HelpExampleCli("getchaintips", "") +
1860  HelpExampleRpc("getchaintips", "")},
1861  [&](const RPCHelpMan &self, const Config &config,
1862  const JSONRPCRequest &request) -> UniValue {
1863  ChainstateManager &chainman = EnsureAnyChainman(request.context);
1864  LOCK(cs_main);
1865  CChain &active_chain = chainman.ActiveChain();
1866 
1878  std::set<const CBlockIndex *, CompareBlocksByHeight> setTips;
1879  std::set<const CBlockIndex *> setOrphans;
1880  std::set<const CBlockIndex *> setPrevs;
1881 
1882  for (const auto &[_, block_index] : chainman.BlockIndex()) {
1883  if (!active_chain.Contains(&block_index)) {
1884  setOrphans.insert(&block_index);
1885  setPrevs.insert(block_index.pprev);
1886  }
1887  }
1888 
1889  for (std::set<const CBlockIndex *>::iterator it =
1890  setOrphans.begin();
1891  it != setOrphans.end(); ++it) {
1892  if (setPrevs.erase(*it) == 0) {
1893  setTips.insert(*it);
1894  }
1895  }
1896 
1897  // Always report the currently active tip.
1898  setTips.insert(active_chain.Tip());
1899 
1900  /* Construct the output array. */
1901  UniValue res(UniValue::VARR);
1902  for (const CBlockIndex *block : setTips) {
1903  UniValue obj(UniValue::VOBJ);
1904  obj.pushKV("height", block->nHeight);
1905  obj.pushKV("hash", block->phashBlock->GetHex());
1906 
1907  const int branchLen =
1908  block->nHeight - active_chain.FindFork(block)->nHeight;
1909  obj.pushKV("branchlen", branchLen);
1910 
1911  std::string status;
1912  if (active_chain.Contains(block)) {
1913  // This block is part of the currently active chain.
1914  status = "active";
1915  } else if (block->nStatus.isInvalid()) {
1916  // This block or one of its ancestors is invalid.
1917  status = "invalid";
1918  } else if (block->nStatus.isOnParkedChain()) {
1919  // This block or one of its ancestors is parked.
1920  status = "parked";
1921  } else if (!block->HaveTxsDownloaded()) {
1922  // This block cannot be connected because full block data
1923  // for it or one of its parents is missing.
1924  status = "headers-only";
1925  } else if (block->IsValid(BlockValidity::SCRIPTS)) {
1926  // This block is fully validated, but no longer part of the
1927  // active chain. It was probably the active block once, but
1928  // was reorganized.
1929  status = "valid-fork";
1930  } else if (block->IsValid(BlockValidity::TREE)) {
1931  // The headers for this block are valid, but it has not been
1932  // validated. It was probably never part of the most-work
1933  // chain.
1934  status = "valid-headers";
1935  } else {
1936  // No clue.
1937  status = "unknown";
1938  }
1939  obj.pushKV("status", status);
1940 
1941  res.push_back(obj);
1942  }
1943 
1944  return res;
1945  },
1946  };
1947 }
1948 
1950  // Make sure this call is atomic in the pool.
1951  LOCK(pool.cs);
1952  UniValue ret(UniValue::VOBJ);
1953  ret.pushKV("loaded", pool.IsLoaded());
1954  ret.pushKV("size", (int64_t)pool.size());
1955  ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
1956  ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
1957  ret.pushKV("total_fee", pool.GetTotalFee());
1958  size_t maxmempool =
1959  gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
1960  ret.pushKV("maxmempool", (int64_t)maxmempool);
1961  ret.pushKV(
1962  "mempoolminfee",
1963  std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK());
1964  ret.pushKV("minrelaytxfee", ::minRelayTxFee.GetFeePerK());
1965  ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
1966  return ret;
1967 }
1968 
1970  const auto &ticker = Currency::get().ticker;
1971  return RPCHelpMan{
1972  "getmempoolinfo",
1973  "Returns details on the active state of the TX memory pool.\n",
1974  {},
1975  RPCResult{
1977  "",
1978  "",
1979  {
1980  {RPCResult::Type::BOOL, "loaded",
1981  "True if the mempool is fully loaded"},
1982  {RPCResult::Type::NUM, "size", "Current tx count"},
1983  {RPCResult::Type::NUM, "bytes", "Sum of all transaction sizes"},
1984  {RPCResult::Type::NUM, "usage",
1985  "Total memory usage for the mempool"},
1986  {RPCResult::Type::NUM, "maxmempool",
1987  "Maximum memory usage for the mempool"},
1988  {RPCResult::Type::STR_AMOUNT, "total_fee",
1989  "Total fees for the mempool in " + ticker +
1990  ", ignoring modified fees through prioritizetransaction"},
1991  {RPCResult::Type::STR_AMOUNT, "mempoolminfee",
1992  "Minimum fee rate in " + ticker +
1993  "/kB for tx to be accepted. Is the maximum of "
1994  "minrelaytxfee and minimum mempool fee"},
1995  {RPCResult::Type::STR_AMOUNT, "minrelaytxfee",
1996  "Current minimum relay fee for transactions"},
1997  {RPCResult::Type::NUM, "unbroadcastcount",
1998  "Current number of transactions that haven't passed initial "
1999  "broadcast yet"},
2000  }},
2001  RPCExamples{HelpExampleCli("getmempoolinfo", "") +
2002  HelpExampleRpc("getmempoolinfo", "")},
2003  [&](const RPCHelpMan &self, const Config &config,
2004  const JSONRPCRequest &request) -> UniValue {
2005  return MempoolInfoToJSON(EnsureAnyMemPool(request.context));
2006  },
2007  };
2008 }
2009 
2011  return RPCHelpMan{
2012  "preciousblock",
2013  "Treats a block as if it were received before others with the same "
2014  "work.\n"
2015  "\nA later preciousblock call can override the effect of an earlier "
2016  "one.\n"
2017  "\nThe effects of preciousblock are not retained across restarts.\n",
2018  {
2020  "the hash of the block to mark as precious"},
2021  },
2023  RPCExamples{HelpExampleCli("preciousblock", "\"blockhash\"") +
2024  HelpExampleRpc("preciousblock", "\"blockhash\"")},
2025  [&](const RPCHelpMan &self, const Config &config,
2026  const JSONRPCRequest &request) -> UniValue {
2027  BlockHash hash(ParseHashV(request.params[0], "blockhash"));
2028  CBlockIndex *pblockindex;
2029 
2030  ChainstateManager &chainman = EnsureAnyChainman(request.context);
2031  {
2032  LOCK(cs_main);
2033  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
2034  if (!pblockindex) {
2036  "Block not found");
2037  }
2038  }
2039 
2040  BlockValidationState state;
2041  chainman.ActiveChainstate().PreciousBlock(config, state,
2042  pblockindex);
2043 
2044  if (!state.IsValid()) {
2046  }
2047 
2048  // Block to make sure wallet/indexers sync before returning
2050 
2051  return NullUniValue;
2052  },
2053  };
2054 }
2055 
2057  return RPCHelpMan{
2058  "invalidateblock",
2059  "Permanently marks a block as invalid, as if it violated a consensus "
2060  "rule.\n",
2061  {
2063  "the hash of the block to mark as invalid"},
2064  },
2066  RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") +
2067  HelpExampleRpc("invalidateblock", "\"blockhash\"")},
2068  [&](const RPCHelpMan &self, const Config &config,
2069  const JSONRPCRequest &request) -> UniValue {
2070  const BlockHash hash(ParseHashV(request.params[0], "blockhash"));
2071  BlockValidationState state;
2072 
2073  ChainstateManager &chainman = EnsureAnyChainman(request.context);
2074  CBlockIndex *pblockindex;
2075  {
2076  LOCK(cs_main);
2077  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
2078  if (!pblockindex) {
2080  "Block not found");
2081  }
2082  }
2083  chainman.ActiveChainstate().InvalidateBlock(config, state,
2084  pblockindex);
2085 
2086  if (state.IsValid()) {
2087  chainman.ActiveChainstate().ActivateBestChain(config, state);
2088  }
2089 
2090  if (!state.IsValid()) {
2091  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
2092  }
2093 
2094  // Block to make sure wallet/indexers sync before returning
2096 
2097  return NullUniValue;
2098  },
2099  };
2100 }
2101 
2103  return RPCHelpMan{
2104  "parkblock",
2105  "Marks a block as parked.\n",
2106  {
2108  "the hash of the block to park"},
2109  },
2111  RPCExamples{HelpExampleCli("parkblock", "\"blockhash\"") +
2112  HelpExampleRpc("parkblock", "\"blockhash\"")},
2113  [&](const RPCHelpMan &self, const Config &config,
2114  const JSONRPCRequest &request) -> UniValue {
2115  const std::string strHash = request.params[0].get_str();
2116  const BlockHash hash(uint256S(strHash));
2117  BlockValidationState state;
2118 
2119  ChainstateManager &chainman = EnsureAnyChainman(request.context);
2120  Chainstate &active_chainstate = chainman.ActiveChainstate();
2121  CBlockIndex *pblockindex = nullptr;
2122  {
2123  LOCK(cs_main);
2124  pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
2125  if (!pblockindex) {
2127  "Block not found");
2128  }
2129 
2130  if (active_chainstate.IsBlockAvalancheFinalized(pblockindex)) {
2131  // Reset avalanche finalization if we park a finalized
2132  // block.
2133  active_chainstate.ClearAvalancheFinalizedBlock();
2134  }
2135  }
2136 
2137  active_chainstate.ParkBlock(config, state, pblockindex);
2138 
2139  if (state.IsValid()) {
2140  active_chainstate.ActivateBestChain(config, state);
2141  }
2142 
2143  if (!state.IsValid()) {
2145  }
2146 
2147  // Block to make sure wallet/indexers sync before returning
2149 
2150  return NullUniValue;
2151  },
2152  };
2153 }
2154 
2156  return RPCHelpMan{
2157  "reconsiderblock",
2158  "Removes invalidity status of a block, its ancestors and its"
2159  "descendants, reconsider them for activation.\n"
2160  "This can be used to undo the effects of invalidateblock.\n",
2161  {
2163  "the hash of the block to reconsider"},
2164  },
2166  RPCExamples{HelpExampleCli("reconsiderblock", "\"blockhash\"") +
2167  HelpExampleRpc("reconsiderblock", "\"blockhash\"")},
2168  [&](const RPCHelpMan &self, const Config &config,
2169  const JSONRPCRequest &request) -> UniValue {
2170  ChainstateManager &chainman = EnsureAnyChainman(request.context);
2171  const BlockHash hash(ParseHashV(request.params[0], "blockhash"));
2172 
2173  {
2174  LOCK(cs_main);
2175  CBlockIndex *pblockindex =
2176  chainman.m_blockman.LookupBlockIndex(hash);
2177  if (!pblockindex) {
2179  "Block not found");
2180  }
2181 
2182  chainman.ActiveChainstate().ResetBlockFailureFlags(pblockindex);
2183  }
2184 
2185  BlockValidationState state;
2186  chainman.ActiveChainstate().ActivateBestChain(config, state);
2187 
2188  if (!state.IsValid()) {
2189  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
2190  }
2191 
2192  // Block to make sure wallet/indexers sync before returning
2194 
2195  return NullUniValue;
2196  },
2197  };
2198 }
2199 
2201  return RPCHelpMan{
2202  "unparkblock",
2203  "Removes parked status of a block and its descendants, reconsider "
2204  "them for activation.\n"
2205  "This can be used to undo the effects of parkblock.\n",
2206  {
2208  "the hash of the block to unpark"},
2209  },
2211  RPCExamples{HelpExampleCli("unparkblock", "\"blockhash\"") +
2212  HelpExampleRpc("unparkblock", "\"blockhash\"")},
2213  [&](const RPCHelpMan &self, const Config &config,
2214  const JSONRPCRequest &request) -> UniValue {
2215  const std::string strHash = request.params[0].get_str();
2216  ChainstateManager &chainman = EnsureAnyChainman(request.context);
2217  const BlockHash hash(uint256S(strHash));
2218  Chainstate &active_chainstate = chainman.ActiveChainstate();
2219 
2220  {
2221  LOCK(cs_main);
2222 
2223  CBlockIndex *pblockindex =
2224  chainman.m_blockman.LookupBlockIndex(hash);
2225  if (!pblockindex) {
2227  "Block not found");
2228  }
2229 
2230  if (!pblockindex->nStatus.isOnParkedChain()) {
2231  // Block to unpark is not parked so there is nothing to do.
2232  return NullUniValue;
2233  }
2234 
2235  const CBlockIndex *tip = active_chainstate.m_chain.Tip();
2236  if (tip) {
2237  const CBlockIndex *ancestor =
2238  LastCommonAncestor(tip, pblockindex);
2239  if (active_chainstate.IsBlockAvalancheFinalized(ancestor)) {
2240  // Only reset avalanche finalization if we unpark a
2241  // block that might conflict with avalanche finalized
2242  // blocks.
2243  active_chainstate.ClearAvalancheFinalizedBlock();
2244  }
2245  }
2246 
2247  active_chainstate.UnparkBlockAndChildren(pblockindex);
2248  }
2249 
2250  BlockValidationState state;
2251  active_chainstate.ActivateBestChain(config, state);
2252 
2253  if (!state.IsValid()) {
2255  }
2256 
2257  // Block to make sure wallet/indexers sync before returning
2259 
2260  return NullUniValue;
2261  },
2262  };
2263 }
2264 
2266  return RPCHelpMan{
2267  "getchaintxstats",
2268  "Compute statistics about the total number and rate of transactions "
2269  "in the chain.\n",
2270  {
2271  {"nblocks", RPCArg::Type::NUM, /* default */ "one month",
2272  "Size of the window in number of blocks"},
2273  {"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip",
2274  "The hash of the block that ends the window."},
2275  },
2277  "",
2278  "",
2279  {
2280  {RPCResult::Type::NUM_TIME, "time",
2281  "The timestamp for the final block in the window, "
2282  "expressed in " +
2283  UNIX_EPOCH_TIME},
2284  {RPCResult::Type::NUM, "txcount",
2285  "The total number of transactions in the chain up to "
2286  "that point"},
2287  {RPCResult::Type::STR_HEX, "window_final_block_hash",
2288  "The hash of the final block in the window"},
2289  {RPCResult::Type::NUM, "window_final_block_height",
2290  "The height of the final block in the window."},
2291  {RPCResult::Type::NUM, "window_block_count",
2292  "Size of the window in number of blocks"},
2293  {RPCResult::Type::NUM, "window_tx_count",
2294  "The number of transactions in the window. Only "
2295  "returned if \"window_block_count\" is > 0"},
2296  {RPCResult::Type::NUM, "window_interval",
2297  "The elapsed time in the window in seconds. Only "
2298  "returned if \"window_block_count\" is > 0"},
2299  {RPCResult::Type::NUM, "txrate",
2300  "The average rate of transactions per second in the "
2301  "window. Only returned if \"window_interval\" is > 0"},
2302  }},
2303  RPCExamples{HelpExampleCli("getchaintxstats", "") +
2304  HelpExampleRpc("getchaintxstats", "2016")},
2305  [&](const RPCHelpMan &self, const Config &config,
2306  const JSONRPCRequest &request) -> UniValue {
2307  ChainstateManager &chainman = EnsureAnyChainman(request.context);
2308  const CBlockIndex *pindex;
2309 
2310  // By default: 1 month
2311  int blockcount =
2312  30 * 24 * 60 * 60 /
2313  config.GetChainParams().GetConsensus().nPowTargetSpacing;
2314 
2315  if (request.params[1].isNull()) {
2316  LOCK(cs_main);
2317  pindex = chainman.ActiveTip();
2318  } else {
2319  BlockHash hash(ParseHashV(request.params[1], "blockhash"));
2320  LOCK(cs_main);
2321  pindex = chainman.m_blockman.LookupBlockIndex(hash);
2322  if (!pindex) {
2324  "Block not found");
2325  }
2326  if (!chainman.ActiveChain().Contains(pindex)) {
2328  "Block is not in main chain");
2329  }
2330  }
2331 
2332  CHECK_NONFATAL(pindex != nullptr);
2333 
2334  if (request.params[0].isNull()) {
2335  blockcount =
2336  std::max(0, std::min(blockcount, pindex->nHeight - 1));
2337  } else {
2338  blockcount = request.params[0].get_int();
2339 
2340  if (blockcount < 0 ||
2341  (blockcount > 0 && blockcount >= pindex->nHeight)) {
2343  "Invalid block count: "
2344  "should be between 0 and "
2345  "the block's height - 1");
2346  }
2347  }
2348 
2349  const CBlockIndex &past_block{*CHECK_NONFATAL(
2350  pindex->GetAncestor(pindex->nHeight - blockcount))};
2351  const int64_t nTimeDiff{pindex->GetMedianTimePast() -
2352  past_block.GetMedianTimePast()};
2353  const int nTxDiff =
2354  pindex->GetChainTxCount() - past_block.GetChainTxCount();
2355 
2356  UniValue ret(UniValue::VOBJ);
2357  ret.pushKV("time", pindex->GetBlockTime());
2358  ret.pushKV("txcount", pindex->GetChainTxCount());
2359  ret.pushKV("window_final_block_hash",
2360  pindex->GetBlockHash().GetHex());
2361  ret.pushKV("window_final_block_height", pindex->nHeight);
2362  ret.pushKV("window_block_count", blockcount);
2363  if (blockcount > 0) {
2364  ret.pushKV("window_tx_count", nTxDiff);
2365  ret.pushKV("window_interval", nTimeDiff);
2366  if (nTimeDiff > 0) {
2367  ret.pushKV("txrate", double(nTxDiff) / nTimeDiff);
2368  }
2369  }
2370 
2371  return ret;
2372  },
2373  };
2374 }
2375 
2376 template <typename T>
2377 static T CalculateTruncatedMedian(std::vector<T> &scores) {
2378  size_t size = scores.size();
2379  if (size == 0) {
2380  return T();
2381  }
2382 
2383  std::sort(scores.begin(), scores.end());
2384  if (size % 2 == 0) {
2385  return (scores[size / 2 - 1] + scores[size / 2]) / 2;
2386  } else {
2387  return scores[size / 2];
2388  }
2389 }
2390 
2391 template <typename T> static inline bool SetHasKeys(const std::set<T> &set) {
2392  return false;
2393 }
2394 template <typename T, typename Tk, typename... Args>
2395 static inline bool SetHasKeys(const std::set<T> &set, const Tk &key,
2396  const Args &...args) {
2397  return (set.count(key) != 0) || SetHasKeys(set, args...);
2398 }
2399 
2400 // outpoint (needed for the utxo index) + nHeight + fCoinBase
2401 static constexpr size_t PER_UTXO_OVERHEAD =
2402  sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool);
2403 
2405  const auto &ticker = Currency::get().ticker;
2406  return RPCHelpMan{
2407  "getblockstats",
2408  "Compute per block statistics for a given window. All amounts are "
2409  "in " +
2410  ticker +
2411  ".\n"
2412  "It won't work for some heights with pruning.\n",
2413  {
2414  {"hash_or_height",
2417  "The block hash or height of the target block",
2418  "",
2419  {"", "string or numeric"}},
2420  {"stats",
2422  /* default */ "all values",
2423  "Values to plot (see result below)",
2424  {
2426  "Selected statistic"},
2428  "Selected statistic"},
2429  },
2430  "stats"},
2431  },
2432  RPCResult{
2434  "",
2435  "",
2436  {
2437  {RPCResult::Type::NUM, "avgfee", "Average fee in the block"},
2438  {RPCResult::Type::NUM, "avgfeerate",
2439  "Average feerate (in satoshis per virtual byte)"},
2440  {RPCResult::Type::NUM, "avgtxsize", "Average transaction size"},
2441  {RPCResult::Type::STR_HEX, "blockhash",
2442  "The block hash (to check for potential reorgs)"},
2443  {RPCResult::Type::NUM, "height", "The height of the block"},
2444  {RPCResult::Type::NUM, "ins",
2445  "The number of inputs (excluding coinbase)"},
2446  {RPCResult::Type::NUM, "maxfee", "Maximum fee in the block"},
2447  {RPCResult::Type::NUM, "maxfeerate",
2448  "Maximum feerate (in satoshis per virtual byte)"},
2449  {RPCResult::Type::NUM, "maxtxsize", "Maximum transaction size"},
2450  {RPCResult::Type::NUM, "medianfee",
2451  "Truncated median fee in the block"},
2452  {RPCResult::Type::NUM, "medianfeerate",
2453  "Truncated median feerate (in " + ticker + " per byte)"},
2454  {RPCResult::Type::NUM, "mediantime",
2455  "The block median time past"},
2456  {RPCResult::Type::NUM, "mediantxsize",
2457  "Truncated median transaction size"},
2458  {RPCResult::Type::NUM, "minfee", "Minimum fee in the block"},
2459  {RPCResult::Type::NUM, "minfeerate",
2460  "Minimum feerate (in satoshis per virtual byte)"},
2461  {RPCResult::Type::NUM, "mintxsize", "Minimum transaction size"},
2462  {RPCResult::Type::NUM, "outs", "The number of outputs"},
2463  {RPCResult::Type::NUM, "subsidy", "The block subsidy"},
2464  {RPCResult::Type::NUM, "time", "The block time"},
2465  {RPCResult::Type::NUM, "total_out",
2466  "Total amount in all outputs (excluding coinbase and thus "
2467  "reward [ie subsidy + totalfee])"},
2468  {RPCResult::Type::NUM, "total_size",
2469  "Total size of all non-coinbase transactions"},
2470  {RPCResult::Type::NUM, "totalfee", "The fee total"},
2471  {RPCResult::Type::NUM, "txs",
2472  "The number of transactions (including coinbase)"},
2473  {RPCResult::Type::NUM, "utxo_increase",
2474  "The increase/decrease in the number of unspent outputs"},
2475  {RPCResult::Type::NUM, "utxo_size_inc",
2476  "The increase/decrease in size for the utxo index (not "
2477  "discounting op_return and similar)"},
2478  }},
2479  RPCExamples{
2481  "getblockstats",
2482  R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") +
2483  HelpExampleCli("getblockstats",
2484  R"(1000 '["minfeerate","avgfeerate"]')") +
2486  "getblockstats",
2487  R"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") +
2488  HelpExampleRpc("getblockstats",
2489  R"(1000, ["minfeerate","avgfeerate"])")},
2490  [&](const RPCHelpMan &self, const Config &config,
2491  const JSONRPCRequest &request) -> UniValue {
2492  ChainstateManager &chainman = EnsureAnyChainman(request.context);
2493  const CBlockIndex &pindex{*CHECK_NONFATAL(
2494  ParseHashOrHeight(request.params[0], chainman))};
2495 
2496  std::set<std::string> stats;
2497  if (!request.params[1].isNull()) {
2498  const UniValue stats_univalue = request.params[1].get_array();
2499  for (unsigned int i = 0; i < stats_univalue.size(); i++) {
2500  const std::string stat = stats_univalue[i].get_str();
2501  stats.insert(stat);
2502  }
2503  }
2504 
2505  const CBlock &block =
2506  GetBlockChecked(config, chainman.m_blockman, &pindex);
2507  const CBlockUndo &blockUndo =
2508  GetUndoChecked(chainman.m_blockman, &pindex);
2509 
2510  // Calculate everything if nothing selected (default)
2511  const bool do_all = stats.size() == 0;
2512  const bool do_mediantxsize =
2513  do_all || stats.count("mediantxsize") != 0;
2514  const bool do_medianfee = do_all || stats.count("medianfee") != 0;
2515  const bool do_medianfeerate =
2516  do_all || stats.count("medianfeerate") != 0;
2517  const bool loop_inputs =
2518  do_all || do_medianfee || do_medianfeerate ||
2519  SetHasKeys(stats, "utxo_size_inc", "totalfee", "avgfee",
2520  "avgfeerate", "minfee", "maxfee", "minfeerate",
2521  "maxfeerate");
2522  const bool loop_outputs =
2523  do_all || loop_inputs || stats.count("total_out");
2524  const bool do_calculate_size =
2525  do_mediantxsize || loop_inputs ||
2526  SetHasKeys(stats, "total_size", "avgtxsize", "mintxsize",
2527  "maxtxsize");
2528 
2529  const int64_t blockMaxSize = config.GetMaxBlockSize();
2530  Amount maxfee = Amount::zero();
2531  Amount maxfeerate = Amount::zero();
2532  Amount minfee = MAX_MONEY;
2533  Amount minfeerate = MAX_MONEY;
2534  Amount total_out = Amount::zero();
2535  Amount totalfee = Amount::zero();
2536  int64_t inputs = 0;
2537  int64_t maxtxsize = 0;
2538  int64_t mintxsize = blockMaxSize;
2539  int64_t outputs = 0;
2540  int64_t total_size = 0;
2541  int64_t utxo_size_inc = 0;
2542  std::vector<Amount> fee_array;
2543  std::vector<Amount> feerate_array;
2544  std::vector<int64_t> txsize_array;
2545 
2546  for (size_t i = 0; i < block.vtx.size(); ++i) {
2547  const auto &tx = block.vtx.at(i);
2548  outputs += tx->vout.size();
2549  Amount tx_total_out = Amount::zero();
2550  if (loop_outputs) {
2551  for (const CTxOut &out : tx->vout) {
2552  tx_total_out += out.nValue;
2553  utxo_size_inc +=
2556  }
2557  }
2558 
2559  if (tx->IsCoinBase()) {
2560  continue;
2561  }
2562 
2563  // Don't count coinbase's fake input
2564  inputs += tx->vin.size();
2565  // Don't count coinbase reward
2566  total_out += tx_total_out;
2567 
2568  int64_t tx_size = 0;
2569  if (do_calculate_size) {
2570  tx_size = tx->GetTotalSize();
2571  if (do_mediantxsize) {
2572  txsize_array.push_back(tx_size);
2573  }
2574  maxtxsize = std::max(maxtxsize, tx_size);
2575  mintxsize = std::min(mintxsize, tx_size);
2576  total_size += tx_size;
2577  }
2578 
2579  if (loop_inputs) {
2580  Amount tx_total_in = Amount::zero();
2581  const auto &txundo = blockUndo.vtxundo.at(i - 1);
2582  for (const Coin &coin : txundo.vprevout) {
2583  const CTxOut &prevoutput = coin.GetTxOut();
2584 
2585  tx_total_in += prevoutput.nValue;
2586  utxo_size_inc -=
2587  GetSerializeSize(prevoutput, PROTOCOL_VERSION) +
2589  }
2590 
2591  Amount txfee = tx_total_in - tx_total_out;
2592  CHECK_NONFATAL(MoneyRange(txfee));
2593  if (do_medianfee) {
2594  fee_array.push_back(txfee);
2595  }
2596  maxfee = std::max(maxfee, txfee);
2597  minfee = std::min(minfee, txfee);
2598  totalfee += txfee;
2599 
2600  Amount feerate = txfee / tx_size;
2601  if (do_medianfeerate) {
2602  feerate_array.push_back(feerate);
2603  }
2604  maxfeerate = std::max(maxfeerate, feerate);
2605  minfeerate = std::min(minfeerate, feerate);
2606  }
2607  }
2608 
2609  UniValue ret_all(UniValue::VOBJ);
2610  ret_all.pushKV("avgfee",
2611  block.vtx.size() > 1
2612  ? (totalfee / int((block.vtx.size() - 1)))
2613  : Amount::zero());
2614  ret_all.pushKV("avgfeerate", total_size > 0
2615  ? (totalfee / total_size)
2616  : Amount::zero());
2617  ret_all.pushKV("avgtxsize",
2618  (block.vtx.size() > 1)
2619  ? total_size / (block.vtx.size() - 1)
2620  : 0);
2621  ret_all.pushKV("blockhash", pindex.GetBlockHash().GetHex());
2622  ret_all.pushKV("height", (int64_t)pindex.nHeight);
2623  ret_all.pushKV("ins", inputs);
2624  ret_all.pushKV("maxfee", maxfee);
2625  ret_all.pushKV("maxfeerate", maxfeerate);
2626  ret_all.pushKV("maxtxsize", maxtxsize);
2627  ret_all.pushKV("medianfee", CalculateTruncatedMedian(fee_array));
2628  ret_all.pushKV("medianfeerate",
2629  CalculateTruncatedMedian(feerate_array));
2630  ret_all.pushKV("mediantime", pindex.GetMedianTimePast());
2631  ret_all.pushKV("mediantxsize",
2632  CalculateTruncatedMedian(txsize_array));
2633  ret_all.pushKV("minfee",
2634  minfee == MAX_MONEY ? Amount::zero() : minfee);
2635  ret_all.pushKV("minfeerate", minfeerate == MAX_MONEY
2636  ? Amount::zero()
2637  : minfeerate);
2638  ret_all.pushKV("mintxsize",
2639  mintxsize == blockMaxSize ? 0 : mintxsize);
2640  ret_all.pushKV("outs", outputs);
2641  ret_all.pushKV("subsidy", GetBlockSubsidy(pindex.nHeight,
2642  Params().GetConsensus()));
2643  ret_all.pushKV("time", pindex.GetBlockTime());
2644  ret_all.pushKV("total_out", total_out);
2645  ret_all.pushKV("total_size", total_size);
2646  ret_all.pushKV("totalfee", totalfee);
2647  ret_all.pushKV("txs", (int64_t)block.vtx.size());
2648  ret_all.pushKV("utxo_increase", outputs - inputs);
2649  ret_all.pushKV("utxo_size_inc", utxo_size_inc);
2650 
2651  if (do_all) {
2652  return ret_all;
2653  }
2654 
2655  UniValue ret(UniValue::VOBJ);
2656  for (const std::string &stat : stats) {
2657  const UniValue &value = ret_all[stat];
2658  if (value.isNull()) {
2659  throw JSONRPCError(
2661  strprintf("Invalid selected statistic %s", stat));
2662  }
2663  ret.pushKV(stat, value);
2664  }
2665  return ret;
2666  },
2667  };
2668 }
2669 
2671  return RPCHelpMan{
2672  "savemempool",
2673  "Dumps the mempool to disk. It will fail until the previous dump is "
2674  "fully loaded.\n",
2675  {},
2677  "",
2678  "",
2679  {
2680  {RPCResult::Type::STR, "filename",
2681  "the directory and file where the mempool was saved"},
2682  }},
2683  RPCExamples{HelpExampleCli("savemempool", "") +
2684  HelpExampleRpc("savemempool", "")},
2685  [&](const RPCHelpMan &self, const Config &config,
2686  const JSONRPCRequest &request) -> UniValue {
2687  const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
2688 
2689  const NodeContext &node = EnsureAnyNodeContext(request.context);
2690 
2691  if (!mempool.IsLoaded()) {
2693  "The mempool was not loaded yet");
2694  }
2695 
2696  if (!DumpMempool(mempool)) {
2698  "Unable to dump mempool to disk");
2699  }
2700 
2701  UniValue ret(UniValue::VOBJ);
2702  ret.pushKV("filename",
2703  fs::path((node.args->GetDataDirNet() / "mempool.dat"))
2704  .u8string());
2705 
2706  return ret;
2707  },
2708  };
2709 }
2710 
2711 namespace {
2713 static bool FindScriptPubKey(std::atomic<int> &scan_progress,
2714  const std::atomic<bool> &should_abort,
2715  int64_t &count, CCoinsViewCursor *cursor,
2716  const std::set<CScript> &needles,
2717  std::map<COutPoint, Coin> &out_results,
2718  std::function<void()> &interruption_point) {
2719  scan_progress = 0;
2720  count = 0;
2721  while (cursor->Valid()) {
2722  COutPoint key;
2723  Coin coin;
2724  if (!cursor->GetKey(key) || !cursor->GetValue(coin)) {
2725  return false;
2726  }
2727  if (++count % 8192 == 0) {
2728  interruption_point();
2729  if (should_abort) {
2730  // allow to abort the scan via the abort reference
2731  return false;
2732  }
2733  }
2734  if (count % 256 == 0) {
2735  // update progress reference every 256 item
2736  const TxId &txid = key.GetTxId();
2737  uint32_t high = 0x100 * *txid.begin() + *(txid.begin() + 1);
2738  scan_progress = int(high * 100.0 / 65536.0 + 0.5);
2739  }
2740  if (needles.count(coin.GetTxOut().scriptPubKey)) {
2741  out_results.emplace(key, coin);
2742  }
2743  cursor->Next();
2744  }
2745  scan_progress = 100;
2746  return true;
2747 }
2748 } // namespace
2749 
2751 static std::atomic<int> g_scan_progress;
2752 static std::atomic<bool> g_scan_in_progress;
2753 static std::atomic<bool> g_should_abort_scan;
2755 private:
2757 
2758 public:
2760 
2761  bool reserve() {
2763  if (g_scan_in_progress.exchange(true)) {
2764  return false;
2765  }
2766  m_could_reserve = true;
2767  return true;
2768  }
2769 
2771  if (m_could_reserve) {
2772  g_scan_in_progress = false;
2773  }
2774  }
2775 };
2776 
2778  const auto &ticker = Currency::get().ticker;
2779  return RPCHelpMan{
2780  "scantxoutset",
2781  "Scans the unspent transaction output set for entries that match "
2782  "certain output descriptors.\n"
2783  "Examples of output descriptors are:\n"
2784  " addr(<address>) Outputs whose scriptPubKey "
2785  "corresponds to the specified address (does not include P2PK)\n"
2786  " raw(<hex script>) Outputs whose scriptPubKey "
2787  "equals the specified hex scripts\n"
2788  " combo(<pubkey>) P2PK and P2PKH outputs for "
2789  "the given pubkey\n"
2790  " pkh(<pubkey>) P2PKH outputs for the given "
2791  "pubkey\n"
2792  " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for "
2793  "the given threshold and pubkeys\n"
2794  "\nIn the above, <pubkey> either refers to a fixed public key in "
2795  "hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
2796  "or more path elements separated by \"/\", and optionally ending in "
2797  "\"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
2798  "unhardened or hardened child keys.\n"
2799  "In the latter case, a range needs to be specified by below if "
2800  "different from 1000.\n"
2801  "For more information on output descriptors, see the documentation in "
2802  "the doc/descriptors.md file.\n",
2803  {
2805  "The action to execute\n"
2806  " \"start\" for starting a "
2807  "scan\n"
2808  " \"abort\" for aborting the "
2809  "current scan (returns true when abort was successful)\n"
2810  " \"status\" for "
2811  "progress report (in %) of the current scan"},
2812  {"scanobjects",
2815  "Array of scan objects. Required for \"start\" action\n"
2816  " Every scan object is either a "
2817  "string descriptor or an object:",
2818  {
2820  "An output descriptor"},
2821  {
2822  "",
2825  "An object with output descriptor and metadata",
2826  {
2828  "An output descriptor"},
2829  {"range", RPCArg::Type::RANGE, /* default */ "1000",
2830  "The range of HD chain indexes to explore (either "
2831  "end or [begin,end])"},
2832  },
2833  },
2834  },
2835  "[scanobjects,...]"},
2836  },
2837  {
2838  RPCResult{"When action=='abort'", RPCResult::Type::BOOL, "", ""},
2839  RPCResult{"When action=='status' and no scan is in progress",
2840  RPCResult::Type::NONE, "", ""},
2841  RPCResult{
2842  "When action=='status' and scan is in progress",
2844  "",
2845  "",
2846  {
2847  {RPCResult::Type::NUM, "progress", "The scan progress"},
2848  }},
2849  RPCResult{
2850  "When action=='start'",
2852  "",
2853  "",
2854  {
2855  {RPCResult::Type::BOOL, "success",
2856  "Whether the scan was completed"},
2857  {RPCResult::Type::NUM, "txouts",
2858  "The number of unspent transaction outputs scanned"},
2859  {RPCResult::Type::NUM, "height",
2860  "The current block height (index)"},
2861  {RPCResult::Type::STR_HEX, "bestblock",
2862  "The hash of the block at the tip of the chain"},
2864  "unspents",
2865  "",
2866  {
2868  "",
2869  "",
2870  {
2871  {RPCResult::Type::STR_HEX, "txid",
2872  "The transaction id"},
2873  {RPCResult::Type::NUM, "vout", "The vout value"},
2874  {RPCResult::Type::STR_HEX, "scriptPubKey",
2875  "The script key"},
2876  {RPCResult::Type::STR, "desc",
2877  "A specialized descriptor for the matched "
2878  "scriptPubKey"},
2879  {RPCResult::Type::STR_AMOUNT, "amount",
2880  "The total amount in " + ticker +
2881  " of the unspent output"},
2882  {RPCResult::Type::NUM, "height",
2883  "Height of the unspent transaction output"},
2884  }},
2885  }},
2886  {RPCResult::Type::STR_AMOUNT, "total_amount",
2887  "The total amount of all found unspent outputs in " +
2888  ticker},
2889  }},
2890  },
2891  RPCExamples{""},
2892  [&](const RPCHelpMan &self, const Config &config,
2893  const JSONRPCRequest &request) -> UniValue {
2894  RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
2895 
2896  UniValue result(UniValue::VOBJ);
2897  if (request.params[0].get_str() == "status") {
2898  CoinsViewScanReserver reserver;
2899  if (reserver.reserve()) {
2900  // no scan in progress
2901  return NullUniValue;
2902  }
2903  result.pushKV("progress", g_scan_progress.load());
2904  return result;
2905  } else if (request.params[0].get_str() == "abort") {
2906  CoinsViewScanReserver reserver;
2907  if (reserver.reserve()) {
2908  // reserve was possible which means no scan was running
2909  return false;
2910  }
2911  // set the abort flag
2912  g_should_abort_scan = true;
2913  return true;
2914  } else if (request.params[0].get_str() == "start") {
2915  CoinsViewScanReserver reserver;
2916  if (!reserver.reserve()) {
2918  "Scan already in progress, use action "
2919  "\"abort\" or \"status\"");
2920  }
2921 
2922  if (request.params.size() < 2) {
2924  "scanobjects argument is required for "
2925  "the start action");
2926  }
2927 
2928  std::set<CScript> needles;
2929  std::map<CScript, std::string> descriptors;
2930  Amount total_in = Amount::zero();
2931 
2932  // loop through the scan objects
2933  for (const UniValue &scanobject :
2934  request.params[1].get_array().getValues()) {
2935  FlatSigningProvider provider;
2936  auto scripts =
2937  EvalDescriptorStringOrObject(scanobject, provider);
2938  for (const auto &script : scripts) {
2939  std::string inferred =
2940  InferDescriptor(script, provider)->ToString();
2941  needles.emplace(script);
2942  descriptors.emplace(std::move(script),
2943  std::move(inferred));
2944  }
2945  }
2946 
2947  // Scan the unspent transaction output set for inputs
2948  UniValue unspents(UniValue::VARR);
2949  std::vector<CTxOut> input_txos;
2950  std::map<COutPoint, Coin> coins;
2951  g_should_abort_scan = false;
2952  g_scan_progress = 0;
2953  int64_t count = 0;
2954  std::unique_ptr<CCoinsViewCursor> pcursor;
2955  const CBlockIndex *tip;
2956  NodeContext &node = EnsureAnyNodeContext(request.context);
2957  {
2958  ChainstateManager &chainman = EnsureChainman(node);
2959  LOCK(cs_main);
2960  Chainstate &active_chainstate = chainman.ActiveChainstate();
2961  active_chainstate.ForceFlushStateToDisk();
2962  pcursor = CHECK_NONFATAL(std::unique_ptr<CCoinsViewCursor>(
2963  active_chainstate.CoinsDB().Cursor()));
2964  tip = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
2965  }
2966  bool res = FindScriptPubKey(
2967  g_scan_progress, g_should_abort_scan, count, pcursor.get(),
2968  needles, coins, node.rpc_interruption_point);
2969  result.pushKV("success", res);
2970  result.pushKV("txouts", count);
2971  result.pushKV("height", tip->nHeight);
2972  result.pushKV("bestblock", tip->GetBlockHash().GetHex());
2973 
2974  for (const auto &it : coins) {
2975  const COutPoint &outpoint = it.first;
2976  const Coin &coin = it.second;
2977  const CTxOut &txo = coin.GetTxOut();
2978  input_txos.push_back(txo);
2979  total_in += txo.nValue;
2980 
2981  UniValue unspent(UniValue::VOBJ);
2982  unspent.pushKV("txid", outpoint.GetTxId().GetHex());
2983  unspent.pushKV("vout", int32_t(outpoint.GetN()));
2984  unspent.pushKV("scriptPubKey", HexStr(txo.scriptPubKey));
2985  unspent.pushKV("desc", descriptors[txo.scriptPubKey]);
2986  unspent.pushKV("amount", txo.nValue);
2987  unspent.pushKV("height", int32_t(coin.GetHeight()));
2988 
2989  unspents.push_back(unspent);
2990  }
2991  result.pushKV("unspents", unspents);
2992  result.pushKV("total_amount", total_in);
2993  } else {
2994  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid command");
2995  }
2996  return result;
2997  },
2998  };
2999 }
3000 
3002  return RPCHelpMan{
3003  "getblockfilter",
3004  "Retrieve a BIP 157 content filter for a particular block.\n",
3005  {
3007  "The hash of the block"},
3008  {"filtertype", RPCArg::Type::STR, /*default*/ "basic",
3009  "The type name of the filter"},
3010  },
3012  "",
3013  "",
3014  {
3015  {RPCResult::Type::STR_HEX, "filter",
3016  "the hex-encoded filter data"},
3017  {RPCResult::Type::STR_HEX, "header",
3018  "the hex-encoded filter header"},
3019  }},
3020  RPCExamples{
3021  HelpExampleCli("getblockfilter",
3022  "\"00000000c937983704a73af28acdec37b049d214a"
3023  "dbda81d7e2a3dd146f6ed09\" \"basic\"") +
3024  HelpExampleRpc("getblockfilter",
3025  "\"00000000c937983704a73af28acdec37b049d214adbda81d7"
3026  "e2a3dd146f6ed09\", \"basic\"")},
3027  [&](const RPCHelpMan &self, const Config &config,
3028  const JSONRPCRequest &request) -> UniValue {
3029  const BlockHash block_hash(
3030  ParseHashV(request.params[0], "blockhash"));
3031  std::string filtertype_name = "basic";
3032  if (!request.params[1].isNull()) {
3033  filtertype_name = request.params[1].get_str();
3034  }
3035 
3036  BlockFilterType filtertype;
3037  if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
3039  "Unknown filtertype");
3040  }
3041 
3042  BlockFilterIndex *index = GetBlockFilterIndex(filtertype);
3043  if (!index) {
3045  "Index is not enabled for filtertype " +
3046  filtertype_name);
3047  }
3048 
3049  const CBlockIndex *block_index;
3050  bool block_was_connected;
3051  {
3052  ChainstateManager &chainman =
3053  EnsureAnyChainman(request.context);
3054  LOCK(cs_main);
3055  block_index = chainman.m_blockman.LookupBlockIndex(block_hash);
3056  if (!block_index) {
3058  "Block not found");
3059  }
3060  block_was_connected =
3061  block_index->IsValid(BlockValidity::SCRIPTS);
3062  }
3063 
3064  bool index_ready = index->BlockUntilSyncedToCurrentChain();
3065 
3066  BlockFilter filter;
3067  uint256 filter_header;
3068  if (!index->LookupFilter(block_index, filter) ||
3069  !index->LookupFilterHeader(block_index, filter_header)) {
3070  int err_code;
3071  std::string errmsg = "Filter not found.";
3072 
3073  if (!block_was_connected) {
3074  err_code = RPC_INVALID_ADDRESS_OR_KEY;
3075  errmsg += " Block was not connected to active chain.";
3076  } else if (!index_ready) {
3077  err_code = RPC_MISC_ERROR;
3078  errmsg += " Block filters are still in the process of "
3079  "being indexed.";
3080  } else {
3081  err_code = RPC_INTERNAL_ERROR;
3082  errmsg += " This error is unexpected and indicates index "
3083  "corruption.";
3084  }
3085 
3086  throw JSONRPCError(err_code, errmsg);
3087  }
3088 
3089  UniValue ret(UniValue::VOBJ);
3090  ret.pushKV("filter", HexStr(filter.GetEncodedFilter()));
3091  ret.pushKV("header", filter_header.GetHex());
3092  return ret;
3093  },
3094  };
3095 }
3096 
3103  return RPCHelpMan{
3104  "dumptxoutset",
3105  "Write the serialized UTXO set to disk.\n",
3106  {
3108  "path to the output file. If relative, will be prefixed by "
3109  "datadir."},
3110  },
3112  "",
3113  "",
3114  {
3115  {RPCResult::Type::NUM, "coins_written",
3116  "the number of coins written in the snapshot"},
3117  {RPCResult::Type::STR_HEX, "base_hash",
3118  "the hash of the base of the snapshot"},
3119  {RPCResult::Type::NUM, "base_height",
3120  "the height of the base of the snapshot"},
3121  {RPCResult::Type::STR, "path",
3122  "the absolute path that the snapshot was written to"},
3123  }},
3124  RPCExamples{HelpExampleCli("dumptxoutset", "utxo.dat")},
3125  [&](const RPCHelpMan &self, const Config &config,
3126  const JSONRPCRequest &request) -> UniValue {
3127  const fs::path path = fsbridge::AbsPathJoin(
3128  gArgs.GetDataDirNet(), fs::u8path(request.params[0].get_str()));
3129  // Write to a temporary path and then move into `path` on completion
3130  // to avoid confusion due to an interruption.
3131  const fs::path temppath = fsbridge::AbsPathJoin(
3132  gArgs.GetDataDirNet(),
3133  fs::u8path(request.params[0].get_str() + ".incomplete"));
3134 
3135  if (fs::exists(path)) {
3137  path.u8string() +
3138  " already exists. If you are sure this "
3139  "is what you want, "
3140  "move it out of the way first");
3141  }
3142 
3143  FILE *file{fsbridge::fopen(temppath, "wb")};
3144  CAutoFile afile{file, SER_DISK, CLIENT_VERSION};
3145  NodeContext &node = EnsureAnyNodeContext(request.context);
3146  UniValue result = CreateUTXOSnapshot(
3147  node, node.chainman->ActiveChainstate(), afile);
3148  fs::rename(temppath, path);
3149 
3150  result.pushKV("path", path.u8string());
3151  return result;
3152  },
3153  };
3154 }
3155 
3157  CAutoFile &afile) {
3158  std::unique_ptr<CCoinsViewCursor> pcursor;
3160  const CBlockIndex *tip;
3161 
3162  {
3163  // We need to lock cs_main to ensure that the coinsdb isn't
3164  // written to between (i) flushing coins cache to disk
3165  // (coinsdb), (ii) getting stats based upon the coinsdb, and
3166  // (iii) constructing a cursor to the coinsdb for use below this
3167  // block.
3168  //
3169  // Cursors returned by leveldb iterate over snapshots, so the
3170  // contents of the pcursor will not be affected by simultaneous
3171  // writes during use below this block.
3172  //
3173  // See discussion here:
3174  // https://github.com/bitcoin/bitcoin/pull/15606#discussion_r274479369
3175  //
3176  LOCK(::cs_main);
3177 
3178  chainstate.ForceFlushStateToDisk();
3179 
3180  if (!GetUTXOStats(&chainstate.CoinsDB(), chainstate.m_blockman, stats,
3181  node.rpc_interruption_point)) {
3182  throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
3183  }
3184 
3185  pcursor =
3186  std::unique_ptr<CCoinsViewCursor>(chainstate.CoinsDB().Cursor());
3187  tip = CHECK_NONFATAL(
3188  chainstate.m_blockman.LookupBlockIndex(stats.hashBlock));
3189  }
3190 
3191  SnapshotMetadata metadata{tip->GetBlockHash(), stats.coins_count,
3192  uint64_t(tip->GetChainTxCount())};
3193 
3194  afile << metadata;
3195 
3196  COutPoint key;
3197  Coin coin;
3198  unsigned int iter{0};
3199 
3200  while (pcursor->Valid()) {
3201  if (iter % 5000 == 0) {
3202  node.rpc_interruption_point();
3203  }
3204  ++iter;
3205  if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
3206  afile << key;
3207  afile << coin;
3208  }
3209 
3210  pcursor->Next();
3211  }
3212 
3213  afile.fclose();
3214 
3215  UniValue result(UniValue::VOBJ);
3216  result.pushKV("coins_written", stats.coins_count);
3217  result.pushKV("base_hash", tip->GetBlockHash().ToString());
3218  result.pushKV("base_height", tip->nHeight);
3219  return result;
3220 }
3221 
3223  // clang-format off
3224  static const CRPCCommand commands[] = {
3225  // category actor (function)
3226  // ------------------ ----------------------
3227  { "blockchain", getbestblockhash, },
3228  { "blockchain", getblock, },
3229  { "blockchain", getblockfrompeer, },
3230  { "blockchain", getblockchaininfo, },
3231  { "blockchain", getblockcount, },
3232  { "blockchain", getblockhash, },
3233  { "blockchain", getblockheader, },
3234  { "blockchain", getblockstats, },
3235  { "blockchain", getchaintips, },
3236  { "blockchain", getchaintxstats, },
3237  { "blockchain", getdifficulty, },
3238  { "blockchain", getmempoolancestors, },
3239  { "blockchain", getmempooldescendants, },
3240  { "blockchain", getmempoolentry, },
3241  { "blockchain", getmempoolinfo, },
3242  { "blockchain", getrawmempool, },
3243  { "blockchain", gettxout, },
3244  { "blockchain", gettxoutsetinfo, },
3245  { "blockchain", pruneblockchain, },
3246  { "blockchain", savemempool, },
3247  { "blockchain", verifychain, },
3248  { "blockchain", preciousblock, },
3249  { "blockchain", scantxoutset, },
3250  { "blockchain", getblockfilter, },
3251 
3252  /* Not shown in help */
3253  { "hidden", invalidateblock, },
3254  { "hidden", parkblock, },
3255  { "hidden", reconsiderblock, },
3256  { "hidden", syncwithvalidationinterfacequeue, },
3257  { "hidden", dumptxoutset, },
3258  { "hidden", unparkblock, },
3259  { "hidden", waitfornewblock, },
3260  { "hidden", waitforblock, },
3261  { "hidden", waitforblockheight, },
3262  };
3263  // clang-format on
3264  for (const auto &c : commands) {
3265  t.appendCommand(c.name, &c);
3266  }
3267 }
bool MoneyRange(const Amount nValue)
Definition: amount.h:166
static constexpr Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:165
RPCHelpMan gettxout()
static RPCHelpMan getblock()
static int ComputeNextBlockAndDepth(const CBlockIndex *tip, const CBlockIndex *blockindex, const CBlockIndex *&next)
Definition: blockchain.cpp:87
static RPCHelpMan getdifficulty()
Definition: blockchain.cpp:438
static std::atomic< bool > g_scan_in_progress
static bool SetHasKeys(const std::set< T > &set)
static RPCHelpMan reconsiderblock()
static T CalculateTruncatedMedian(std::vector< T > &scores)
static RPCHelpMan invalidateblock()
static RPCHelpMan getmempoolinfo()
static RPCHelpMan syncwithvalidationinterfacequeue()
Definition: blockchain.cpp:421
static RPCHelpMan getchaintips()
static RPCHelpMan gettxoutsetinfo()
UniValue CreateUTXOSnapshot(NodeContext &node, Chainstate &chainstate, CAutoFile &afile)
Helper to create UTXO snapshots given a chainstate and a file handle.
static void entryToJSON(const CTxMemPool &pool, UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
Definition: blockchain.cpp:496
static RPCHelpMan getblockstats()
static CoinStatsHashType ParseHashType(const std::string &hash_type_input)
static std::vector< RPCResult > MempoolEntryDescription()
Definition: blockchain.cpp:458
static RPCHelpMan preciousblock()
static constexpr size_t PER_UTXO_OVERHEAD
double GetDifficulty(const CBlockIndex *blockindex)
Calculate the difficulty for a given block index.
Definition: blockchain.cpp:69
static RPCHelpMan getrawmempool()
Definition: blockchain.cpp:577
static RPCHelpMan scantxoutset()
static RPCHelpMan getmempoolentry()
Definition: blockchain.cpp:788
static std::condition_variable cond_blockchange
Definition: blockchain.cpp:63
static Mutex cs_blockchange
Definition: blockchain.cpp:62
static std::atomic< int > g_scan_progress
RAII object to prevent concurrency issue when scanning the txout set.
static CBlockUndo GetUndoChecked(BlockManager &blockman, const CBlockIndex *pblockindex)
UniValue MempoolInfoToJSON(const CTxMemPool &pool)
Mempool information to JSON.
static RPCHelpMan getblockfilter()
static RPCHelpMan getbestblockhash()
Definition: blockchain.cpp:215
RPCHelpMan getblockchaininfo()
UniValue blockToJSON(BlockManager &blockman, const CBlock &block, const CBlockIndex *tip, const CBlockIndex *blockindex, bool txDetails)
Block description to JSON.
Definition: blockchain.cpp:164
static RPCHelpMan getchaintxstats()
static RPCHelpMan waitforblock()
Definition: blockchain.cpp:299
static RPCHelpMan getblockfrompeer()
Definition: blockchain.cpp:820
static const CBlockIndex * ParseHashOrHeight(const UniValue &param, ChainstateManager &chainman)
Definition: blockchain.cpp:98
static RPCHelpMan getblockhash()
Definition: blockchain.cpp:872
void RegisterBlockchainRPCCommands(CRPCTable &t)
UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose, bool include_mempool_sequence)
Mempool to JSON.
Definition: blockchain.cpp:533
static RPCHelpMan verifychain()
static std::atomic< bool > g_should_abort_scan
RPCHelpMan unparkblock()
UniValue blockheaderToJSON(const CBlockIndex *tip, const CBlockIndex *blockindex)
Block header to JSON.
Definition: blockchain.cpp:130
static RPCHelpMan waitforblockheight()
Definition: blockchain.cpp:361
static RPCHelpMan pruneblockchain()
static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange)
static RPCHelpMan getblockheader()
Definition: blockchain.cpp:901
static CBlock GetBlockChecked(const Config &config, BlockManager &blockman, const CBlockIndex *pblockindex)
Definition: blockchain.cpp:997
RPCHelpMan parkblock()
static RPCHelpMan getmempooldescendants()
Definition: blockchain.cpp:714
static RPCHelpMan dumptxoutset()
Serialize the UTXO set to a file for loading elsewhere.
static RPCHelpMan getblockcount()
Definition: blockchain.cpp:197
static RPCHelpMan waitfornewblock()
Definition: blockchain.cpp:242
static RPCHelpMan getmempoolancestors()
Definition: blockchain.cpp:643
static RPCHelpMan savemempool()
void RPCNotifyBlockChange(const CBlockIndex *pindex)
Callback for when block tip changed.
Definition: blockchain.cpp:233
bool BlockFilterTypeByName(const std::string &name, BlockFilterType &filter_type)
Find a filter type by its human-readable name.
BlockFilterType
Definition: blockfilter.h:88
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:112
@ SCRIPTS
Scripts & signatures ok.
@ TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
Definition: chain.cpp:115
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:36
const CChainParams & Params()
Return the currently selected parameters.
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:52
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: system.h:270
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: system.cpp:591
Complete block filter struct as defined in BIP 157.
Definition: blockfilter.h:111
const std::vector< uint8_t > & GetEncodedFilter() const
Definition: blockfilter.h:134
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out)
Get a single filter header by block.
bool LookupFilter(const CBlockIndex *block_index, BlockFilter &filter_out) const
Get a single filter by block.
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:581
void fclose()
Definition: streams.h:600
Definition: block.h:55
std::vector< CTransactionRef > vtx
Definition: block.h:58
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:26
bool IsValid(enum BlockValidity nUpTo=BlockValidity::TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
Definition: blockindex.h:209
uint256 hashMerkleRoot
Definition: blockindex.h:92
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: blockindex.h:33
CBlockHeader GetBlockHeader() const
Definition: blockindex.h:134
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
Definition: blockindex.h:52
int64_t GetChainTxCount() const
Get the number of transaction in the chain so far.
Definition: blockindex.h:152
uint32_t nTime
Definition: blockindex.h:93
uint32_t nNonce
Definition: blockindex.h:95
int64_t GetBlockTime() const
Definition: blockindex.h:174
int64_t GetMedianTimePast() const
Definition: blockindex.h:186
uint32_t nBits
Definition: blockindex.h:94
unsigned int nTx
Number of transactions in this block.
Definition: blockindex.h:61
int32_t nVersion
block header
Definition: blockindex.h:91
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: blockindex.cpp:71
BlockHash GetBlockHash() const
Definition: blockindex.h:147
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: blockindex.h:39
Undo information for a CBlock.
Definition: undo.h:73
std::vector< CTxUndo > vtxundo
Definition: undo.h:76
An in-memory indexed chain of blocks.
Definition: chain.h:141
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:157
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:65
int Height() const
Return the maximal height in the chain.
Definition: chain.h:193
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Find the last common block between this chain and a block index entry.
Definition: chain.cpp:52
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:173
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:74
std::string NetworkIDString() const
Return the BIP70 network string (main, test or regtest)
Definition: chainparams.h:121
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:86
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:203
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:210
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:91
Cursor for iterating over CoinsView state.
Definition: coins.h:127
virtual void Next()=0
virtual bool Valid() const =0
virtual bool GetKey(COutPoint &key) const =0
virtual bool GetValue(Coin &coin) const =0
CCoinsViewCursor * Cursor() const override
Get a cursor to iterate over the whole state.
Definition: txdb.cpp:214
Abstract view on the open txout dataset.
Definition: coins.h:147
virtual BlockHash GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:16
CCoinsView that brings transactions from a mempool into view.
Definition: txmempool.h:704
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: txmempool.cpp:654
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:197
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
uint32_t GetN() const
Definition: transaction.h:38
const TxId & GetTxId() const
Definition: transaction.h:37
RPC command dispatcher.
Definition: server.h:183
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:325
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:194
const std::vector< CTxIn > vin
Definition: transaction.h:212
const TxId GetId() const
Definition: transaction.h:246
An input of a transaction.
Definition: transaction.h:61
COutPoint prevout
Definition: transaction.h:63
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
Definition: txmempool.h:84
const CTransaction & GetTx() const
Definition: txmempool.h:128
const Children & GetMemPoolChildrenConst() const
Definition: txmempool.h:152
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:305
std::set< txiter, CompareIteratorById > setEntries
Definition: txmempool.h:395
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition: txmempool.h:391
CFeeRate GetMinFee(size_t sizelimit) const
The minimum fee to get into the mempool, which may itself not be enough for larger-sized transactions...
Definition: txmempool.cpp:776
Amount GetTotalFee() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:607
void getAllTxIds(std::vector< TxId > &vtxid) const
Definition: txmempool.cpp:520
size_t DynamicMemoryUsage() const
Definition: txmempool.cpp:684
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:655
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
Definition: txmempool.h:394
bool IsLoaded() const
Definition: txmempool.cpp:852
std::set< TxId > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
Definition: txmempool.h:639
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
Definition: txmempool.cpp:259
unsigned long size() const
Definition: txmempool.h:597
bool CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, bool fSearchForParents=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Try to calculate all in-mempool ancestors of entry.
Definition: txmempool.cpp:96
uint64_t GetTotalTxSize() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:602
bool isSpent(const COutPoint &outpoint) const
Definition: txmempool.cpp:160
An output of a transaction.
Definition: transaction.h:130
CScript scriptPubKey
Definition: transaction.h:133
Amount nValue
Definition: transaction.h:132
Restore the UTXO in a Coin at a given COutPoint.
Definition: undo.h:62
RAII wrapper for VerifyDB: Verify consistency of the block and coin databases.
Definition: validation.h:573
bool VerifyDB(Chainstate &chainstate, const Config &config, 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:647
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:745
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
bool PreciousBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex) LOCKS_EXCLUDED(cs_main)
Mark a block as precious and reorganize.
CCoinsViewDB & CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:778
void ForceFlushStateToDisk()
Unconditionally flush all changes to disk.
void UnparkBlockAndChildren(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove parked status from a block and its descendants.
bool InvalidateBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
Mark a block as invalid.
void ResetBlockFailureFlags(CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Remove invalidity status from a block and its descendants.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:771
node::BlockManager & m_blockman
Reference to a BlockManager instance which itself is shared across all Chainstate instances.
Definition: validation.h:706
bool ParkBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
Park a block.
bool IsBlockAvalancheFinalized(const CBlockIndex *pindex) const
Checks if a block is finalized by avalanche voting.
void ClearAvalancheFinalizedBlock()
Clear avalanche finalization.
bool ActivateBestChain(const Config &config, BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex) LOCKS_EXCLUDED(cs_main)
Find the best known block, and make it the tip of the block chain.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1062
int ActiveHeight() const
Definition: validation.h:1202
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:1205
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:1156
CBlockIndex * ActiveTip() const
Definition: validation.h:1203
CChain & ActiveChain() const
Definition: validation.h:1201
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1129
A UTXO entry.
Definition: coins.h:27
uint32_t GetHeight() const
Definition: coins.h:44
bool IsCoinBase() const
Definition: coins.h:45
CTxOut & GetTxOut()
Definition: coins.h:48
Definition: config.h:17
virtual const CChainParams & GetChainParams() const =0
virtual std::optional< std::string > FetchBlock(const Config &config, NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
const std::string & get_str() const
@ VOBJ
Definition: univalue.h:27
@ VARR
Definition: univalue.h:27
bool isNull() const
Definition: univalue.h:89
void __pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:127
size_t size() const
Definition: univalue.h:80
const std::vector< UniValue > & getValues() const
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
const UniValue & get_array() const
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
bool isNum() const
Definition: univalue.h:94
bool get_bool() const
int get_int() const
bool IsValid() const
Definition: validation.h:120
std::string GetRejectReason() const
Definition: validation.h:124
std::string ToString() const
Definition: validation.h:126
uint8_t * begin()
Definition: uint256.h:83
std::string ToString() const
Definition: uint256.h:78
std::string GetHex() const
Definition: uint256.cpp:16
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:29
Maintains a tree of blocks (stored in m_block_index) which is consulted to determine where the most-w...
Definition: blockstorage.h:68
CBlockIndex * LookupBlockIndex(const BlockHash &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:15
256-bit opaque blob.
Definition: uint256.h:127
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
std::unique_ptr< CoinStatsIndex > g_coin_stats_index
The global UTXO set hash object.
void TxToUniv(const CTransaction &tx, const BlockHash &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0, const CTxUndo *txundo=nullptr)
Definition: core_write.cpp:217
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
Definition: core_write.cpp:190
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
#define LogPrint(category,...)
Definition: logging.h:209
unsigned int nHeight
@ RPC
Definition: logging.h:47
@ NONE
Definition: logging.h:39
static bool exists(const path &p)
Definition: fs.h:89
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:28
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:37
Definition: init.h:28
const CBlockIndex * GetFirstStoredBlock(const CBlockIndex *start_block)
bool fPruneMode
Pruning-related variables and constants.
CoinStatsHashType
Definition: coinstats.h:25
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &params)
Functions for disk access for blocks.
static bool GetUTXOStats(CCoinsView *view, BlockManager &blockman, CCoinsStats &stats, T hash_obj, const std::function< void()> &interruption_point, const CBlockIndex *pindex)
Calculate statistics about the unspent transaction output set.
Definition: coinstats.cpp:91
uint64_t nPruneTarget
Number of MiB of block files that we're trying to stay below.
bool UndoReadFromDisk(CBlockUndo &blockundo, const CBlockIndex *pindex)
int64_t NodeId
Definition: nodeid.h:10
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE
Default for -maxmempool, maximum megabytes of mempool memory usage.
Definition: policy.h:48
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:321
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:57
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
Definition: protocol.h:38
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
@ RPC_INTERNAL_ERROR
Definition: protocol.h:33
@ RPC_DATABASE_ERROR
Database error.
Definition: protocol.h:48
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
void RPCTypeCheck(const UniValue &params, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: util.cpp:27
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:178
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:1030
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:195
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:23
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:101
@ SER_DISK
Definition: serialize.h:167
@ SER_NETWORK
Definition: serialize.h:166
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1259
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
Definition: server.cpp:405
bool IsRPCRunning()
Query whether RPC is running.
Definition: server.cpp:376
int RPCSerializationFlags()
Retrieves any serialization flags requested in command line argument.
Definition: server.cpp:603
ChainstateManager & EnsureAnyChainman(const std::any &context)
Definition: server_util.cpp:46
CTxMemPool & EnsureAnyMemPool(const std::any &context)
Definition: server_util.cpp:35
NodeContext & EnsureAnyNodeContext(const std::any &context)
Definition: server_util.cpp:19
PeerManager & EnsurePeerman(const NodeContext &node)
Definition: server_util.cpp:59
CTxMemPool & EnsureMemPool(const NodeContext &node)
Definition: server_util.cpp:27
ChainstateManager & EnsureChainman(const NodeContext &node)
Definition: server_util.cpp:39
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:46
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
BlockHash hash
Definition: blockchain.cpp:58
Comparison function for sorting the getchaintips heads.
bool operator()(const CBlockIndex *a, const CBlockIndex *b) const
static const Currency & get()
Definition: amount.cpp:18
std::string ticker
Definition: amount.h:150
@ RANGE
Special type that is a NUM or [NUM,NUM].
@ STR_HEX
Special type that is a STR with only hex chars.
@ 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.
@ 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.
@ OBJ_EMPTY
Special type to allow empty OBJ.
A TxId is the identifier of a transaction.
Definition: txid.h:14
bool index_requested
Signals if the coinstatsindex should be used (when available).
Definition: coinstats.h:46
NodeContext struct containing references to chain state and connection state.
Definition: context.h:38
#define WAIT_LOCK(cs, name)
Definition: sync.h:251
#define AssertLockNotHeld(cs)
Definition: sync.h:97
#define LOCK(cs)
Definition: sync.h:243
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:276
ArgsManager gArgs
Definition: system.cpp:79
static int count
Definition: tests.c:31
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
constexpr int64_t count_seconds(std::chrono::seconds t)
Helper to count the seconds of a duration.
Definition: time.h:29
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:55
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coins to signify they are only in the memory pool(since 0....
Definition: txmempool.h:43
uint256 uint256S(const char *str)
uint256 from const char *.
Definition: uint256.h:141
const UniValue NullUniValue
Definition: univalue.cpp:13
Amount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
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...
bool DumpMempool(const CTxMemPool &pool)
Dump the mempool to disk.
CFeeRate minRelayTxFee
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation)
Definition: validation.cpp:125
const std::vector< std::string > CHECKLEVEL_DOC
Documentation for argument 'checklevel'.
Definition: validation.cpp:91
void PruneBlockFilesManual(Chainstate &active_chainstate, int nManualPruneHeight)
Prune block files up to a given height.
AssertLockHeld(pool.cs)
static const unsigned int DEFAULT_CHECKLEVEL
Definition: validation.h:105
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:103
static const signed int DEFAULT_CHECKBLOCKS
Definition: validation.h:104
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:11
bilingual_str GetWarnings(bool verbose)
Format a string that describes several potential problems detected by the core.
Definition: warnings.cpp:41