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