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