Bitcoin ABC  0.22.12
P2P Digital Currency
blockchain.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2019 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <rpc/blockchain.h>
7 
8 #include <amount.h>
9 #include <blockdb.h>
10 #include <blockfilter.h>
11 #include <chain.h>
12 #include <chainparams.h>
13 #include <checkpoints.h>
14 #include <coins.h>
15 #include <config.h>
16 #include <consensus/validation.h>
17 #include <core_io.h>
18 #include <hash.h>
19 #include <index/blockfilterindex.h>
20 #include <network.h>
21 #include <node/coinstats.h>
22 #include <node/context.h>
23 #include <node/utxo_snapshot.h>
24 #include <policy/policy.h>
25 #include <primitives/transaction.h>
26 #include <rpc/server.h>
27 #include <rpc/util.h>
28 #include <script/descriptor.h>
29 #include <streams.h>
30 #include <txdb.h>
31 #include <txmempool.h>
32 #include <undo.h>
33 #include <util/ref.h>
34 #include <util/strencodings.h>
35 #include <util/system.h>
36 #include <validation.h>
37 #include <validationinterface.h>
38 #include <versionbitsinfo.h> // For VersionBitsDeploymentInfo
39 #include <warnings.h>
40 
41 #include <condition_variable>
42 #include <cstdint>
43 #include <memory>
44 #include <mutex>
45 
46 struct CUpdatedBlock {
48  int height;
49 };
50 
52 static std::condition_variable cond_blockchange;
53 static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange);
54 
56  if (!context.Has<NodeContext>()) {
57  throw JSONRPCError(RPC_INTERNAL_ERROR, "Node context not found");
58  }
59  return context.Get<NodeContext>();
60 }
61 
63  NodeContext &node = EnsureNodeContext(context);
64  if (!node.mempool) {
66  "Mempool disabled or instance not found");
67  }
68  return *node.mempool;
69 }
70 
72  NodeContext &node = EnsureNodeContext(context);
73  if (!node.chainman) {
74  throw JSONRPCError(RPC_INTERNAL_ERROR, "Node chainman not found");
75  }
76  return *node.chainman;
77 }
78 
82 double GetDifficulty(const CBlockIndex *blockindex) {
83  CHECK_NONFATAL(blockindex);
84 
85  int nShift = (blockindex->nBits >> 24) & 0xff;
86  double dDiff = double(0x0000ffff) / double(blockindex->nBits & 0x00ffffff);
87 
88  while (nShift < 29) {
89  dDiff *= 256.0;
90  nShift++;
91  }
92  while (nShift > 29) {
93  dDiff /= 256.0;
94  nShift--;
95  }
96 
97  return dDiff;
98 }
99 
100 static int ComputeNextBlockAndDepth(const CBlockIndex *tip,
101  const CBlockIndex *blockindex,
102  const CBlockIndex *&next) {
103  next = tip->GetAncestor(blockindex->nHeight + 1);
104  if (next && next->pprev == blockindex) {
105  return tip->nHeight - blockindex->nHeight + 1;
106  }
107  next = nullptr;
108  return blockindex == tip ? 1 : -1;
109 }
110 
112  const CBlockIndex *blockindex) {
113  // Serialize passed information without accessing chain state of the active
114  // chain!
115  // For performance reasons
117 
118  UniValue result(UniValue::VOBJ);
119  result.pushKV("hash", blockindex->GetBlockHash().GetHex());
120  const CBlockIndex *pnext;
121  int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
122  result.pushKV("confirmations", confirmations);
123  result.pushKV("height", blockindex->nHeight);
124  result.pushKV("version", blockindex->nVersion);
125  result.pushKV("versionHex", strprintf("%08x", blockindex->nVersion));
126  result.pushKV("merkleroot", blockindex->hashMerkleRoot.GetHex());
127  result.pushKV("time", int64_t(blockindex->nTime));
128  result.pushKV("mediantime", int64_t(blockindex->GetMedianTimePast()));
129  result.pushKV("nonce", uint64_t(blockindex->nNonce));
130  result.pushKV("bits", strprintf("%08x", blockindex->nBits));
131  result.pushKV("difficulty", GetDifficulty(blockindex));
132  result.pushKV("chainwork", blockindex->nChainWork.GetHex());
133  result.pushKV("nTx", uint64_t(blockindex->nTx));
134 
135  if (blockindex->pprev) {
136  result.pushKV("previousblockhash",
137  blockindex->pprev->GetBlockHash().GetHex());
138  }
139  if (pnext) {
140  result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
141  }
142  return result;
143 }
144 
145 UniValue blockToJSON(const CBlock &block, const CBlockIndex *tip,
146  const CBlockIndex *blockindex, bool txDetails) {
147  // Serialize passed information without accessing chain state of the active
148  // chain!
149  // For performance reasons
151 
152  UniValue result(UniValue::VOBJ);
153  result.pushKV("hash", blockindex->GetBlockHash().GetHex());
154  const CBlockIndex *pnext;
155  int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
156  result.pushKV("confirmations", confirmations);
157  result.pushKV("size", (int)::GetSerializeSize(block, PROTOCOL_VERSION));
158  result.pushKV("height", blockindex->nHeight);
159  result.pushKV("version", block.nVersion);
160  result.pushKV("versionHex", strprintf("%08x", block.nVersion));
161  result.pushKV("merkleroot", block.hashMerkleRoot.GetHex());
163  for (const auto &tx : block.vtx) {
164  if (txDetails) {
165  UniValue objTx(UniValue::VOBJ);
166  TxToUniv(*tx, uint256(), objTx, true, RPCSerializationFlags());
167  txs.push_back(objTx);
168  } else {
169  txs.push_back(tx->GetId().GetHex());
170  }
171  }
172  result.pushKV("tx", txs);
173  result.pushKV("time", block.GetBlockTime());
174  result.pushKV("mediantime", int64_t(blockindex->GetMedianTimePast()));
175  result.pushKV("nonce", uint64_t(block.nNonce));
176  result.pushKV("bits", strprintf("%08x", block.nBits));
177  result.pushKV("difficulty", GetDifficulty(blockindex));
178  result.pushKV("chainwork", blockindex->nChainWork.GetHex());
179  result.pushKV("nTx", uint64_t(blockindex->nTx));
180 
181  if (blockindex->pprev) {
182  result.pushKV("previousblockhash",
183  blockindex->pprev->GetBlockHash().GetHex());
184  }
185  if (pnext) {
186  result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
187  }
188  return result;
189 }
190 
191 static UniValue getblockcount(const Config &config,
192  const JSONRPCRequest &request) {
193  RPCHelpMan{
194  "getblockcount",
195  "\nReturns the height of the most-work fully-validated chain.\n"
196  "The genesis block has height 0.\n",
197  {},
198  RPCResult{RPCResult::Type::NUM, "", "The current block count"},
199  RPCExamples{HelpExampleCli("getblockcount", "") +
200  HelpExampleRpc("getblockcount", "")},
201  }
202  .Check(request);
203 
204  LOCK(cs_main);
206 }
207 
208 static UniValue getbestblockhash(const Config &config,
209  const JSONRPCRequest &request) {
210  RPCHelpMan{
211  "getbestblockhash",
212  "Returns the hash of the best (tip) block in the "
213  "most-work fully-validated chain.\n",
214  {},
215  RPCResult{RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"},
216  RPCExamples{HelpExampleCli("getbestblockhash", "") +
217  HelpExampleRpc("getbestblockhash", "")},
218  }
219  .Check(request);
220 
221  LOCK(cs_main);
223 }
224 
226  const JSONRPCRequest &request) {
227  RPCHelpMan{
228  "getfinalizedblockhash",
229  "Returns the hash of the currently finalized block\n",
230  {},
231  RPCResult{RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"},
232  RPCExamples{HelpExampleCli("getfinalizedblockhash", "") +
233  HelpExampleRpc("getfinalizedblockhash", "")},
234  }
235  .Check(request);
236 
237  LOCK(cs_main);
238  const CBlockIndex *blockIndexFinalized =
240  if (blockIndexFinalized) {
241  return blockIndexFinalized->GetBlockHash().GetHex();
242  }
243  return UniValue(UniValue::VSTR);
244 }
245 
246 void RPCNotifyBlockChange(const CBlockIndex *pindex) {
247  if (pindex) {
248  LOCK(cs_blockchange);
249  latestblock.hash = pindex->GetBlockHash();
250  latestblock.height = pindex->nHeight;
251  }
252  cond_blockchange.notify_all();
253 }
254 
255 static UniValue waitfornewblock(const Config &config,
256  const JSONRPCRequest &request) {
257  RPCHelpMan{
258  "waitfornewblock",
259  "Waits for a specific new block and returns useful info about it.\n"
260  "\nReturns the current block on timeout or exit.\n",
261  {
262  {"timeout", RPCArg::Type::NUM, /* default */ "0",
263  "Time in milliseconds to wait for a response. 0 indicates no "
264  "timeout."},
265  },
267  "",
268  "",
269  {
270  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
271  {RPCResult::Type::NUM, "height", "Block height"},
272  }},
273  RPCExamples{HelpExampleCli("waitfornewblock", "1000") +
274  HelpExampleRpc("waitfornewblock", "1000")},
275  }
276  .Check(request);
277 
278  int timeout = 0;
279  if (!request.params[0].isNull()) {
280  timeout = request.params[0].get_int();
281  }
282 
283  CUpdatedBlock block;
284  {
285  WAIT_LOCK(cs_blockchange, lock);
286  block = latestblock;
287  if (timeout) {
288  cond_blockchange.wait_for(
289  lock, std::chrono::milliseconds(timeout),
290  [&block]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {
291  return latestblock.height != block.height ||
292  latestblock.hash != block.hash || !IsRPCRunning();
293  });
294  } else {
295  cond_blockchange.wait(
296  lock, [&block]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {
297  return latestblock.height != block.height ||
298  latestblock.hash != block.hash || !IsRPCRunning();
299  });
300  }
301  block = latestblock;
302  }
304  ret.pushKV("hash", block.hash.GetHex());
305  ret.pushKV("height", block.height);
306  return ret;
307 }
308 
309 static UniValue waitforblock(const Config &config,
310  const JSONRPCRequest &request) {
311  RPCHelpMan{
312  "waitforblock",
313  "Waits for a specific new block and returns useful info about it.\n"
314  "\nReturns the current block on timeout or exit.\n",
315  {
317  "Block hash to wait for."},
318  {"timeout", RPCArg::Type::NUM, /* default */ "0",
319  "Time in milliseconds to wait for a response. 0 indicates no "
320  "timeout."},
321  },
323  "",
324  "",
325  {
326  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
327  {RPCResult::Type::NUM, "height", "Block height"},
328  }},
329  RPCExamples{HelpExampleCli("waitforblock",
330  "\"0000000000079f8ef3d2c688c244eb7a4570b24c9"
331  "ed7b4a8c619eb02596f8862\" 1000") +
332  HelpExampleRpc("waitforblock",
333  "\"0000000000079f8ef3d2c688c244eb7a4570b24c9"
334  "ed7b4a8c619eb02596f8862\", 1000")},
335  }
336  .Check(request);
337 
338  int timeout = 0;
339 
340  BlockHash hash(ParseHashV(request.params[0], "blockhash"));
341 
342  if (!request.params[1].isNull()) {
343  timeout = request.params[1].get_int();
344  }
345 
346  CUpdatedBlock block;
347  {
348  WAIT_LOCK(cs_blockchange, lock);
349  if (timeout) {
350  cond_blockchange.wait_for(
351  lock, std::chrono::milliseconds(timeout),
352  [&hash]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {
353  return latestblock.hash == hash || !IsRPCRunning();
354  });
355  } else {
356  cond_blockchange.wait(
357  lock, [&hash]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {
358  return latestblock.hash == hash || !IsRPCRunning();
359  });
360  }
361  block = latestblock;
362  }
363 
365  ret.pushKV("hash", block.hash.GetHex());
366  ret.pushKV("height", block.height);
367  return ret;
368 }
369 
370 static UniValue waitforblockheight(const Config &config,
371  const JSONRPCRequest &request) {
372  RPCHelpMan{
373  "waitforblockheight",
374  "Waits for (at least) block height and returns the height and "
375  "hash\nof the current tip.\n"
376  "\nReturns the current block on timeout or exit.\n",
377  {
379  "Block height to wait for."},
380  {"timeout", RPCArg::Type::NUM, /* default */ "0",
381  "Time in milliseconds to wait for a response. 0 indicates no "
382  "timeout."},
383  },
385  "",
386  "",
387  {
388  {RPCResult::Type::STR_HEX, "hash", "The blockhash"},
389  {RPCResult::Type::NUM, "height", "Block height"},
390  }},
391  RPCExamples{HelpExampleCli("waitforblockheight", "100 1000") +
392  HelpExampleRpc("waitforblockheight", "100, 1000")},
393  }
394  .Check(request);
395 
396  int timeout = 0;
397 
398  int height = request.params[0].get_int();
399 
400  if (!request.params[1].isNull()) {
401  timeout = request.params[1].get_int();
402  }
403 
404  CUpdatedBlock block;
405  {
406  WAIT_LOCK(cs_blockchange, lock);
407  if (timeout) {
408  cond_blockchange.wait_for(
409  lock, std::chrono::milliseconds(timeout),
410  [&height]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {
411  return latestblock.height >= height || !IsRPCRunning();
412  });
413  } else {
414  cond_blockchange.wait(
415  lock, [&height]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {
416  return latestblock.height >= height || !IsRPCRunning();
417  });
418  }
419  block = latestblock;
420  }
422  ret.pushKV("hash", block.hash.GetHex());
423  ret.pushKV("height", block.height);
424  return ret;
425 }
426 
427 static UniValue
429  const JSONRPCRequest &request) {
430  RPCHelpMan{
431  "syncwithvalidationinterfacequeue",
432  "Waits for the validation interface queue to catch up on everything "
433  "that was there when we entered this function.\n",
434  {},
436  RPCExamples{HelpExampleCli("syncwithvalidationinterfacequeue", "") +
437  HelpExampleRpc("syncwithvalidationinterfacequeue", "")},
438  }
439  .Check(request);
440 
442  return NullUniValue;
443 }
444 
445 static UniValue getdifficulty(const Config &config,
446  const JSONRPCRequest &request) {
447  RPCHelpMan{
448  "getdifficulty",
449  "Returns the proof-of-work difficulty as a multiple of the minimum "
450  "difficulty.\n",
451  {},
453  "the proof-of-work difficulty as a multiple of the minimum "
454  "difficulty."},
455  RPCExamples{HelpExampleCli("getdifficulty", "") +
456  HelpExampleRpc("getdifficulty", "")},
457  }
458  .Check(request);
459 
460  LOCK(cs_main);
461  return GetDifficulty(::ChainActive().Tip());
462 }
463 
464 static std::vector<RPCResult> MempoolEntryDescription() {
465  return {
466  RPCResult{RPCResult::Type::NUM, "size", "transaction size."},
468  "transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)"},
469  RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee",
470  "transaction fee with fee deltas used for mining priority "
471  "(DEPRECATED)"},
473  "local time transaction entered pool in seconds since 1 Jan "
474  "1970 GMT"},
476  "block height when transaction entered pool"},
477  RPCResult{RPCResult::Type::NUM, "descendantcount",
478  "number of in-mempool descendant transactions (including "
479  "this one)"},
480  RPCResult{RPCResult::Type::NUM, "descendantsize",
481  "transaction size of in-mempool descendants "
482  "(including this one)"},
483  RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees",
484  "modified fees (see above) of in-mempool descendants "
485  "(including this one) (DEPRECATED)"},
486  RPCResult{
487  RPCResult::Type::NUM, "ancestorcount",
488  "number of in-mempool ancestor transactions (including this one)"},
489  RPCResult{
490  RPCResult::Type::NUM, "ancestorsize",
491  "transaction size of in-mempool ancestors (including this one)"},
492  RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees",
493  "modified fees (see above) of in-mempool ancestors "
494  "(including this one) (DEPRECATED)"},
496  "fees",
497  "",
498  {
500  "transaction fee in " + CURRENCY_UNIT},
502  "transaction fee with fee deltas used for "
503  "mining priority in " +
504  CURRENCY_UNIT},
506  "modified fees (see above) of in-mempool "
507  "ancestors (including this one) in " +
508  CURRENCY_UNIT},
510  "modified fees (see above) of in-mempool "
511  "descendants (including this one) in " +
512  CURRENCY_UNIT},
513  }},
514  RPCResult{
516  "depends",
517  "unconfirmed transactions used as inputs for this transaction",
518  {RPCResult{RPCResult::Type::STR_HEX, "transactionid",
519  "parent transaction id"}}},
520  RPCResult{
522  "spentby",
523  "unconfirmed transactions spending outputs from this transaction",
524  {RPCResult{RPCResult::Type::STR_HEX, "transactionid",
525  "child transaction id"}}},
526  };
527 }
528 
529 static void entryToJSON(const CTxMemPool &pool, UniValue &info,
530  const CTxMemPoolEntry &e)
531  EXCLUSIVE_LOCKS_REQUIRED(pool.cs) {
532  AssertLockHeld(pool.cs);
533 
534  UniValue fees(UniValue::VOBJ);
535  fees.pushKV("base", ValueFromAmount(e.GetFee()));
536  fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee()));
537  fees.pushKV("ancestor", ValueFromAmount(e.GetModFeesWithAncestors()));
538  fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants()));
539  info.pushKV("fees", fees);
540 
541  info.pushKV("size", (int)e.GetTxSize());
542  info.pushKV("fee", ValueFromAmount(e.GetFee()));
543  info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
544  info.pushKV("time", count_seconds(e.GetTime()));
545  info.pushKV("height", (int)e.GetHeight());
546  info.pushKV("descendantcount", e.GetCountWithDescendants());
547  info.pushKV("descendantsize", e.GetSizeWithDescendants());
548  info.pushKV("descendantfees", e.GetModFeesWithDescendants() / SATOSHI);
549  info.pushKV("ancestorcount", e.GetCountWithAncestors());
550  info.pushKV("ancestorsize", e.GetSizeWithAncestors());
551  info.pushKV("ancestorfees", e.GetModFeesWithAncestors() / SATOSHI);
552  const CTransaction &tx = e.GetTx();
553  std::set<std::string> setDepends;
554  for (const CTxIn &txin : tx.vin) {
555  if (pool.exists(txin.prevout.GetTxId())) {
556  setDepends.insert(txin.prevout.GetTxId().ToString());
557  }
558  }
559 
560  UniValue depends(UniValue::VARR);
561  for (const std::string &dep : setDepends) {
562  depends.push_back(dep);
563  }
564 
565  info.pushKV("depends", depends);
566 
567  UniValue spent(UniValue::VARR);
568  const CTxMemPool::txiter &it = pool.mapTx.find(tx.GetId());
569  const CTxMemPool::setEntries &setChildren = pool.GetMemPoolChildren(it);
570  for (CTxMemPool::txiter childiter : setChildren) {
571  spent.push_back(childiter->GetTx().GetId().ToString());
572  }
573 
574  info.pushKV("spentby", spent);
575 }
576 
577 UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose) {
578  if (verbose) {
579  LOCK(pool.cs);
581  for (const CTxMemPoolEntry &e : pool.mapTx) {
582  const uint256 &txid = e.GetTx().GetId();
583  UniValue info(UniValue::VOBJ);
584  entryToJSON(pool, info, e);
585  // Mempool has unique entries so there is no advantage in using
586  // UniValue::pushKV, which checks if the key already exists in O(N).
587  // UniValue::__pushKV is used instead which currently is O(1).
588  o.__pushKV(txid.ToString(), info);
589  }
590  return o;
591  } else {
592  std::vector<uint256> vtxids;
593  pool.queryHashes(vtxids);
594 
596  for (const uint256 &txid : vtxids) {
597  a.push_back(txid.ToString());
598  }
599 
600  return a;
601  }
602 }
603 
604 static UniValue getrawmempool(const Config &config,
605  const JSONRPCRequest &request) {
606  RPCHelpMan{
607  "getrawmempool",
608  "Returns all transaction ids in memory pool as a json array of "
609  "string transaction ids.\n"
610  "\nHint: use getmempoolentry to fetch a specific transaction from the "
611  "mempool.\n",
612  {
613  {"verbose", RPCArg::Type::BOOL, /* default */ "false",
614  "True for a json object, false for array of transaction ids"},
615  },
616  {
617  RPCResult{"for verbose = false",
619  "",
620  "",
621  {
622  {RPCResult::Type::STR_HEX, "", "The transaction id"},
623  }},
624  RPCResult{"for verbose = true",
626  "",
627  "",
628  {
629  {RPCResult::Type::OBJ_DYN, "transactionid", "",
631  }},
632  },
633  RPCExamples{HelpExampleCli("getrawmempool", "true") +
634  HelpExampleRpc("getrawmempool", "true")},
635  }
636  .Check(request);
637 
638  bool fVerbose = false;
639  if (!request.params[0].isNull()) {
640  fVerbose = request.params[0].get_bool();
641  }
642 
643  return MempoolToJSON(EnsureMemPool(request.context), fVerbose);
644 }
645 
646 static UniValue getmempoolancestors(const Config &config,
647  const JSONRPCRequest &request) {
648  RPCHelpMan{
649  "getmempoolancestors",
650  "If txid is in the mempool, returns all in-mempool ancestors.\n",
651  {
653  "The transaction id (must be in mempool)"},
654  {"verbose", RPCArg::Type::BOOL, /* default */ "false",
655  "True for a json object, false for array of transaction ids"},
656  },
657  {
658  RPCResult{
659  "for verbose = false",
661  "",
662  "",
664  "The transaction id of an in-mempool ancestor transaction"}}},
665  RPCResult{"for verbose = true", RPCResult::Type::OBJ_DYN,
666  "transactionid", "", MempoolEntryDescription()},
667  },
668  RPCExamples{HelpExampleCli("getmempoolancestors", "\"mytxid\"") +
669  HelpExampleRpc("getmempoolancestors", "\"mytxid\"")},
670  }
671  .Check(request);
672 
673  bool fVerbose = false;
674  if (!request.params[1].isNull()) {
675  fVerbose = request.params[1].get_bool();
676  }
677 
678  TxId txid(ParseHashV(request.params[0], "parameter 1"));
679 
680  const CTxMemPool &mempool = EnsureMemPool(request.context);
681  LOCK(mempool.cs);
682 
683  CTxMemPool::txiter it = mempool.mapTx.find(txid);
684  if (it == mempool.mapTx.end()) {
686  "Transaction not in mempool");
687  }
688 
689  CTxMemPool::setEntries setAncestors;
690  uint64_t noLimit = std::numeric_limits<uint64_t>::max();
691  std::string dummy;
692  mempool.CalculateMemPoolAncestors(*it, setAncestors, noLimit, noLimit,
693  noLimit, noLimit, dummy, false);
694 
695  if (!fVerbose) {
697  for (CTxMemPool::txiter ancestorIt : setAncestors) {
698  o.push_back(ancestorIt->GetTx().GetId().ToString());
699  }
700 
701  return o;
702  } else {
704  for (CTxMemPool::txiter ancestorIt : setAncestors) {
705  const CTxMemPoolEntry &e = *ancestorIt;
706  const TxId &_txid = e.GetTx().GetId();
707  UniValue info(UniValue::VOBJ);
708  entryToJSON(mempool, info, e);
709  o.pushKV(_txid.ToString(), info);
710  }
711  return o;
712  }
713 }
714 
715 static UniValue getmempooldescendants(const Config &config,
716  const JSONRPCRequest &request) {
717  RPCHelpMan{
718  "getmempooldescendants",
719  "If txid is in the mempool, returns all in-mempool descendants.\n",
720  {
722  "The transaction id (must be in mempool)"},
723  {"verbose", RPCArg::Type::BOOL, /* default */ "false",
724  "True for a json object, false for array of transaction ids"},
725  },
726  {
727  RPCResult{"for verbose = false",
729  "",
730  "",
732  "The transaction id of an in-mempool descendant "
733  "transaction"}}},
734  RPCResult{"for verbose = true",
736  "",
737  "",
738  {
739  {RPCResult::Type::OBJ_DYN, "transactionid", "",
741  }},
742  },
743  RPCExamples{HelpExampleCli("getmempooldescendants", "\"mytxid\"") +
744  HelpExampleRpc("getmempooldescendants", "\"mytxid\"")},
745  }
746  .Check(request);
747 
748  bool fVerbose = false;
749  if (!request.params[1].isNull()) {
750  fVerbose = request.params[1].get_bool();
751  }
752 
753  TxId txid(ParseHashV(request.params[0], "parameter 1"));
754 
755  const CTxMemPool &mempool = EnsureMemPool(request.context);
756  LOCK(mempool.cs);
757 
758  CTxMemPool::txiter it = mempool.mapTx.find(txid);
759  if (it == mempool.mapTx.end()) {
761  "Transaction not in mempool");
762  }
763 
764  CTxMemPool::setEntries setDescendants;
765  mempool.CalculateDescendants(it, setDescendants);
766  // CTxMemPool::CalculateDescendants will include the given tx
767  setDescendants.erase(it);
768 
769  if (!fVerbose) {
771  for (CTxMemPool::txiter descendantIt : setDescendants) {
772  o.push_back(descendantIt->GetTx().GetId().ToString());
773  }
774 
775  return o;
776  } else {
778  for (CTxMemPool::txiter descendantIt : setDescendants) {
779  const CTxMemPoolEntry &e = *descendantIt;
780  const TxId &_txid = e.GetTx().GetId();
781  UniValue info(UniValue::VOBJ);
782  entryToJSON(mempool, info, e);
783  o.pushKV(_txid.ToString(), info);
784  }
785  return o;
786  }
787 }
788 
789 static UniValue getmempoolentry(const Config &config,
790  const JSONRPCRequest &request) {
791  RPCHelpMan{
792  "getmempoolentry",
793  "Returns mempool data for given transaction\n",
794  {
796  "The transaction id (must be in mempool)"},
797  },
799  RPCExamples{HelpExampleCli("getmempoolentry", "\"mytxid\"") +
800  HelpExampleRpc("getmempoolentry", "\"mytxid\"")},
801  }
802  .Check(request);
803 
804  TxId txid(ParseHashV(request.params[0], "parameter 1"));
805 
806  const CTxMemPool &mempool = EnsureMemPool(request.context);
807  LOCK(mempool.cs);
808 
809  CTxMemPool::txiter it = mempool.mapTx.find(txid);
810  if (it == mempool.mapTx.end()) {
812  "Transaction not in mempool");
813  }
814 
815  const CTxMemPoolEntry &e = *it;
816  UniValue info(UniValue::VOBJ);
817  entryToJSON(mempool, info, e);
818  return info;
819 }
820 
821 static UniValue getblockhash(const Config &config,
822  const JSONRPCRequest &request) {
823  RPCHelpMan{
824  "getblockhash",
825  "Returns hash of block in best-block-chain at height provided.\n",
826  {
828  "The height index"},
829  },
830  RPCResult{RPCResult::Type::STR_HEX, "", "The block hash"},
831  RPCExamples{HelpExampleCli("getblockhash", "1000") +
832  HelpExampleRpc("getblockhash", "1000")},
833  }
834  .Check(request);
835 
836  LOCK(cs_main);
837 
838  int nHeight = request.params[0].get_int();
840  throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
841  }
842 
843  CBlockIndex *pblockindex = ::ChainActive()[nHeight];
844  return pblockindex->GetBlockHash().GetHex();
845 }
846 
847 static UniValue getblockheader(const Config &config,
848  const JSONRPCRequest &request) {
849  RPCHelpMan{
850  "getblockheader",
851  "If verbose is false, returns a string that is serialized, hex-encoded "
852  "data for blockheader 'hash'.\n"
853  "If verbose is true, returns an Object with information about "
854  "blockheader <hash>.\n",
855  {
857  "The block hash"},
858  {"verbose", RPCArg::Type::BOOL, /* default */ "true",
859  "true for a json object, false for the hex-encoded data"},
860  },
861  {
862  RPCResult{
863  "for verbose = true",
865  "",
866  "",
867  {
868  {RPCResult::Type::STR_HEX, "hash",
869  "the block hash (same as provided)"},
870  {RPCResult::Type::NUM, "confirmations",
871  "The number of confirmations, or -1 if the block is not "
872  "on the main chain"},
873  {RPCResult::Type::NUM, "height",
874  "The block height or index"},
875  {RPCResult::Type::NUM, "version", "The block version"},
876  {RPCResult::Type::STR_HEX, "versionHex",
877  "The block version formatted in hexadecimal"},
878  {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
879  {RPCResult::Type::NUM_TIME, "time",
880  "The block time expressed in " + UNIX_EPOCH_TIME},
881  {RPCResult::Type::NUM_TIME, "mediantime",
882  "The median block time expressed in " + UNIX_EPOCH_TIME},
883  {RPCResult::Type::NUM, "nonce", "The nonce"},
884  {RPCResult::Type::STR_HEX, "bits", "The bits"},
885  {RPCResult::Type::NUM, "difficulty", "The difficulty"},
886  {RPCResult::Type::STR_HEX, "chainwork",
887  "Expected number of hashes required to produce the "
888  "current chain"},
889  {RPCResult::Type::NUM, "nTx",
890  "The number of transactions in the block"},
891  {RPCResult::Type::STR_HEX, "previousblockhash",
892  "The hash of the previous block"},
893  {RPCResult::Type::STR_HEX, "nextblockhash",
894  "The hash of the next block"},
895  }},
896  RPCResult{"for verbose=false", RPCResult::Type::STR_HEX, "",
897  "A string that is serialized, hex-encoded data for block "
898  "'hash'"},
899  },
900  RPCExamples{HelpExampleCli("getblockheader",
901  "\"00000000c937983704a73af28acdec37b049d214a"
902  "dbda81d7e2a3dd146f6ed09\"") +
903  HelpExampleRpc("getblockheader",
904  "\"00000000c937983704a73af28acdec37b049d214a"
905  "dbda81d7e2a3dd146f6ed09\"")},
906  }
907  .Check(request);
908 
909  BlockHash hash(ParseHashV(request.params[0], "hash"));
910 
911  bool fVerbose = true;
912  if (!request.params[1].isNull()) {
913  fVerbose = request.params[1].get_bool();
914  }
915 
916  const CBlockIndex *pblockindex;
917  const CBlockIndex *tip;
918  {
919  LOCK(cs_main);
920  pblockindex = LookupBlockIndex(hash);
921  tip = ::ChainActive().Tip();
922  }
923 
924  if (!pblockindex) {
925  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
926  }
927 
928  if (!fVerbose) {
930  ssBlock << pblockindex->GetBlockHeader();
931  std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
932  return strHex;
933  }
934 
935  return blockheaderToJSON(tip, pblockindex);
936 }
937 
938 static CBlock GetBlockChecked(const Config &config,
939  const CBlockIndex *pblockindex) {
940  CBlock block;
941  if (IsBlockPruned(pblockindex)) {
942  throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
943  }
944 
945  if (!ReadBlockFromDisk(block, pblockindex,
946  config.GetChainParams().GetConsensus())) {
947  // Block not found on disk. This could be because we have the block
948  // header in our index but don't have the block (for example if a
949  // non-whitelisted node sends us an unrequested long chain of valid
950  // blocks, we add the headers to our index, but don't accept the block).
951  throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
952  }
953 
954  return block;
955 }
956 
957 static CBlockUndo GetUndoChecked(const CBlockIndex *pblockindex) {
958  CBlockUndo blockUndo;
959  if (IsBlockPruned(pblockindex)) {
961  "Undo data not available (pruned data)");
962  }
963 
964  if (!UndoReadFromDisk(blockUndo, pblockindex)) {
965  throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk");
966  }
967 
968  return blockUndo;
969 }
970 
971 static UniValue getblock(const Config &config, const JSONRPCRequest &request) {
972  RPCHelpMan{
973  "getblock",
974  "If verbosity is 0 or false, returns a string that is serialized, "
975  "hex-encoded data for block 'hash'.\n"
976  "If verbosity is 1 or true, returns an Object with information about "
977  "block <hash>.\n"
978  "If verbosity is 2, returns an Object with information about block "
979  "<hash> and information about each transaction.\n",
980  {
982  "The block hash"},
983  {"verbosity|verbose", RPCArg::Type::NUM, /* default */ "1",
984  "0 for hex-encoded data, 1 for a json object, and 2 for json "
985  "object with transaction data"},
986  },
987  {
988  RPCResult{"for verbosity = 0", RPCResult::Type::STR_HEX, "",
989  "A string that is serialized, hex-encoded data for block "
990  "'hash'"},
991  RPCResult{
992  "for verbosity = 1",
994  "",
995  "",
996  {
997  {RPCResult::Type::STR_HEX, "hash",
998  "the block hash (same as provided)"},
999  {RPCResult::Type::NUM, "confirmations",
1000  "The number of confirmations, or -1 if the block is not "
1001  "on the main chain"},
1002  {RPCResult::Type::NUM, "size", "The block size"},
1003  {RPCResult::Type::NUM, "height",
1004  "The block height or index"},
1005  {RPCResult::Type::NUM, "version", "The block version"},
1006  {RPCResult::Type::STR_HEX, "versionHex",
1007  "The block version formatted in hexadecimal"},
1008  {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"},
1010  "tx",
1011  "The transaction ids",
1012  {{RPCResult::Type::STR_HEX, "", "The transaction id"}}},
1013  {RPCResult::Type::NUM_TIME, "time",
1014  "The block time expressed in " + UNIX_EPOCH_TIME},
1015  {RPCResult::Type::NUM_TIME, "mediantime",
1016  "The median block time expressed in " + UNIX_EPOCH_TIME},
1017  {RPCResult::Type::NUM, "nonce", "The nonce"},
1018  {RPCResult::Type::STR_HEX, "bits", "The bits"},
1019  {RPCResult::Type::NUM, "difficulty", "The difficulty"},
1020  {RPCResult::Type::STR_HEX, "chainwork",
1021  "Expected number of hashes required to produce the chain "
1022  "up to this block (in hex)"},
1023  {RPCResult::Type::NUM, "nTx",
1024  "The number of transactions in the block"},
1025  {RPCResult::Type::STR_HEX, "previousblockhash",
1026  "The hash of the previous block"},
1027  {RPCResult::Type::STR_HEX, "nextblockhash",
1028  "The hash of the next block"},
1029  }},
1030  RPCResult{"for verbosity = 2",
1032  "",
1033  "",
1034  {
1036  "Same output as verbosity = 1"},
1038  "tx",
1039  "",
1040  {
1042  "",
1043  "",
1044  {
1046  "The transactions in the format of the "
1047  "getrawtransaction RPC. Different from "
1048  "verbosity = 1 \"tx\" result"},
1049  }},
1050  }},
1052  "Same output as verbosity = 1"},
1053  }},
1054  },
1055  RPCExamples{
1056  HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d"
1057  "214adbda81d7e2a3dd146f6ed09\"") +
1058  HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d"
1059  "214adbda81d7e2a3dd146f6ed09\"")},
1060  }
1061  .Check(request);
1062 
1063  BlockHash hash(ParseHashV(request.params[0], "blockhash"));
1064 
1065  int verbosity = 1;
1066  if (!request.params[1].isNull()) {
1067  if (request.params[1].isNum()) {
1068  verbosity = request.params[1].get_int();
1069  } else {
1070  verbosity = request.params[1].get_bool() ? 1 : 0;
1071  }
1072  }
1073 
1074  CBlock block;
1075  const CBlockIndex *pblockindex;
1076  const CBlockIndex *tip;
1077  {
1078  LOCK(cs_main);
1079  pblockindex = LookupBlockIndex(hash);
1080  tip = ::ChainActive().Tip();
1081 
1082  if (!pblockindex) {
1083  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1084  }
1085 
1086  block = GetBlockChecked(config, pblockindex);
1087  }
1088 
1089  if (verbosity <= 0) {
1090  CDataStream ssBlock(SER_NETWORK,
1092  ssBlock << block;
1093  std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
1094  return strHex;
1095  }
1096 
1097  return blockToJSON(block, tip, pblockindex, verbosity >= 2);
1098 }
1099 
1100 static UniValue pruneblockchain(const Config &config,
1101  const JSONRPCRequest &request) {
1102  RPCHelpMan{
1103  "pruneblockchain",
1104  "",
1105  {
1107  "The block height to prune up to. May be set to a discrete "
1108  "height, or to a " +
1109  UNIX_EPOCH_TIME +
1110  "\n"
1111  " to prune blocks whose block time is at "
1112  "least 2 hours older than the provided timestamp."},
1113  },
1114  RPCResult{RPCResult::Type::NUM, "", "Height of the last block pruned"},
1115  RPCExamples{HelpExampleCli("pruneblockchain", "1000") +
1116  HelpExampleRpc("pruneblockchain", "1000")},
1117  }
1118  .Check(request);
1119 
1120  if (!fPruneMode) {
1121  throw JSONRPCError(
1123  "Cannot prune blocks because node is not in prune mode.");
1124  }
1125 
1126  LOCK(cs_main);
1127 
1128  int heightParam = request.params[0].get_int();
1129  if (heightParam < 0) {
1130  throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative block height.");
1131  }
1132 
1133  // Height value more than a billion is too high to be a block height, and
1134  // too low to be a block time (corresponds to timestamp from Sep 2001).
1135  if (heightParam > 1000000000) {
1136  // Add a 2 hour buffer to include blocks which might have had old
1137  // timestamps
1139  heightParam - TIMESTAMP_WINDOW, 0);
1140  if (!pindex) {
1141  throw JSONRPCError(
1143  "Could not find block with at least the specified timestamp.");
1144  }
1145  heightParam = pindex->nHeight;
1146  }
1147 
1148  unsigned int height = (unsigned int)heightParam;
1149  unsigned int chainHeight = (unsigned int)::ChainActive().Height();
1150  if (chainHeight < config.GetChainParams().PruneAfterHeight()) {
1152  "Blockchain is too short for pruning.");
1153  } else if (height > chainHeight) {
1154  throw JSONRPCError(
1156  "Blockchain is shorter than the attempted prune height.");
1157  } else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) {
1158  LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. "
1159  "Retaining the minimum number of blocks.\n");
1160  height = chainHeight - MIN_BLOCKS_TO_KEEP;
1161  }
1162 
1163  PruneBlockFilesManual(height);
1164  const CBlockIndex *block = ::ChainActive().Tip();
1165  CHECK_NONFATAL(block);
1166  while (block->pprev && (block->pprev->nStatus.hasData())) {
1167  block = block->pprev;
1168  }
1169  return uint64_t(block->nHeight);
1170 }
1171 
1172 static UniValue gettxoutsetinfo(const Config &config,
1173  const JSONRPCRequest &request) {
1174  RPCHelpMan{
1175  "gettxoutsetinfo",
1176  "Returns statistics about the unspent transaction output set.\n"
1177  "Note this call may take some time.\n",
1178  {},
1180  "",
1181  "",
1182  {
1183  {RPCResult::Type::NUM, "height",
1184  "The current block height (index)"},
1185  {RPCResult::Type::STR_HEX, "bestblock",
1186  "The hash of the block at the tip of the chain"},
1187  {RPCResult::Type::NUM, "transactions",
1188  "The number of transactions with unspent outputs"},
1189  {RPCResult::Type::NUM, "txouts",
1190  "The number of unspent transaction outputs"},
1191  {RPCResult::Type::NUM, "bogosize",
1192  "A meaningless metric for UTXO set size"},
1193  {RPCResult::Type::STR_HEX, "hash_serialized",
1194  "The serialized hash"},
1195  {RPCResult::Type::NUM, "disk_size",
1196  "The estimated size of the chainstate on disk"},
1197  {RPCResult::Type::STR_AMOUNT, "total_amount",
1198  "The total amount"},
1199  }},
1200  RPCExamples{HelpExampleCli("gettxoutsetinfo", "") +
1201  HelpExampleRpc("gettxoutsetinfo", "")},
1202  }
1203  .Check(request);
1204 
1205  UniValue ret(UniValue::VOBJ);
1206 
1207  CCoinsStats stats;
1209 
1210  CCoinsView *coins_view =
1211  WITH_LOCK(cs_main, return &ChainstateActive().CoinsDB());
1212  NodeContext &node = EnsureNodeContext(request.context);
1213  if (GetUTXOStats(coins_view, stats, node.rpc_interruption_point)) {
1214  ret.pushKV("height", int64_t(stats.nHeight));
1215  ret.pushKV("bestblock", stats.hashBlock.GetHex());
1216  ret.pushKV("transactions", int64_t(stats.nTransactions));
1217  ret.pushKV("txouts", int64_t(stats.nTransactionOutputs));
1218  ret.pushKV("bogosize", int64_t(stats.nBogoSize));
1219  ret.pushKV("hash_serialized", stats.hashSerialized.GetHex());
1220  ret.pushKV("disk_size", stats.nDiskSize);
1221  ret.pushKV("total_amount", ValueFromAmount(stats.nTotalAmount));
1222  } else {
1223  throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
1224  }
1225  return ret;
1226 }
1227 
1228 UniValue gettxout(const Config &config, const JSONRPCRequest &request) {
1229  RPCHelpMan{
1230  "gettxout",
1231  "Returns details about an unspent transaction output.\n",
1232  {
1234  "The transaction id"},
1235  {"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"},
1236  {"include_mempool", RPCArg::Type::BOOL, /* default */ "true",
1237  "Whether to include the mempool. Note that an unspent output that "
1238  "is spent in the mempool won't appear."},
1239  },
1240  RPCResult{
1242  "",
1243  "",
1244  {
1245  {RPCResult::Type::STR_HEX, "bestblock",
1246  "The hash of the block at the tip of the chain"},
1247  {RPCResult::Type::NUM, "confirmations",
1248  "The number of confirmations"},
1249  {RPCResult::Type::STR_AMOUNT, "value",
1250  "The transaction value in " + CURRENCY_UNIT},
1252  "scriptPubKey",
1253  "",
1254  {
1255  {RPCResult::Type::STR_HEX, "asm", ""},
1256  {RPCResult::Type::STR_HEX, "hex", ""},
1257  {RPCResult::Type::NUM, "reqSigs",
1258  "Number of required signatures"},
1259  {RPCResult::Type::STR_HEX, "type",
1260  "The type, eg pubkeyhash"},
1262  "addresses",
1263  "array of bitcoin addresses",
1264  {{RPCResult::Type::STR, "address", "bitcoin address"}}},
1265  }},
1266  {RPCResult::Type::BOOL, "coinbase", "Coinbase or not"},
1267  }},
1268  RPCExamples{"\nGet unspent transactions\n" +
1269  HelpExampleCli("listunspent", "") + "\nView the details\n" +
1270  HelpExampleCli("gettxout", "\"txid\" 1") +
1271  "\nAs a JSON-RPC call\n" +
1272  HelpExampleRpc("gettxout", "\"txid\", 1")},
1273  }
1274  .Check(request);
1275 
1276  LOCK(cs_main);
1277 
1278  UniValue ret(UniValue::VOBJ);
1279 
1280  TxId txid(ParseHashV(request.params[0], "txid"));
1281  int n = request.params[1].get_int();
1282  COutPoint out(txid, n);
1283  bool fMempool = true;
1284  if (!request.params[2].isNull()) {
1285  fMempool = request.params[2].get_bool();
1286  }
1287 
1288  Coin coin;
1289  CCoinsViewCache *coins_view = &::ChainstateActive().CoinsTip();
1290 
1291  if (fMempool) {
1292  const CTxMemPool &mempool = EnsureMemPool(request.context);
1293  LOCK(mempool.cs);
1294  CCoinsViewMemPool view(coins_view, mempool);
1295  if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
1296  return NullUniValue;
1297  }
1298  } else {
1299  if (!coins_view->GetCoin(out, coin)) {
1300  return NullUniValue;
1301  }
1302  }
1303 
1304  const CBlockIndex *pindex = LookupBlockIndex(coins_view->GetBestBlock());
1305  ret.pushKV("bestblock", pindex->GetBlockHash().GetHex());
1306  if (coin.GetHeight() == MEMPOOL_HEIGHT) {
1307  ret.pushKV("confirmations", 0);
1308  } else {
1309  ret.pushKV("confirmations",
1310  int64_t(pindex->nHeight - coin.GetHeight() + 1));
1311  }
1312  ret.pushKV("value", ValueFromAmount(coin.GetTxOut().nValue));
1314  ScriptPubKeyToUniv(coin.GetTxOut().scriptPubKey, o, true);
1315  ret.pushKV("scriptPubKey", o);
1316  ret.pushKV("coinbase", coin.IsCoinBase());
1317 
1318  return ret;
1319 }
1320 
1321 static UniValue verifychain(const Config &config,
1322  const JSONRPCRequest &request) {
1323  RPCHelpMan{
1324  "verifychain",
1325  "Verifies blockchain database.\n",
1326  {
1327  {"checklevel", RPCArg::Type::NUM,
1328  /* default */ strprintf("%d, range=0-4", DEFAULT_CHECKLEVEL),
1329  "How thorough the block verification is."},
1330  {"nblocks", RPCArg::Type::NUM,
1331  /* default */ strprintf("%d, 0=all", DEFAULT_CHECKBLOCKS),
1332  "The number of blocks to check."},
1333  },
1334  RPCResult{RPCResult::Type::BOOL, "", "Verified or not"},
1335  RPCExamples{HelpExampleCli("verifychain", "") +
1336  HelpExampleRpc("verifychain", "")},
1337  }
1338  .Check(request);
1339 
1340  const int check_level(request.params[0].isNull()
1342  : request.params[0].get_int());
1343  const int check_depth{request.params[1].isNull()
1345  : request.params[1].get_int()};
1346 
1347  LOCK(cs_main);
1348 
1349  return CVerifyDB().VerifyDB(config, &::ChainstateActive().CoinsTip(),
1350  check_level, check_depth);
1351 }
1352 
1353 static void BIP9SoftForkDescPushBack(UniValue &softforks,
1354  const Consensus::Params &consensusParams,
1357  // For BIP9 deployments.
1358  // Deployments (e.g. testdummy) with timeout value before Jan 1, 2009 are
1359  // hidden. A timeout value of 0 guarantees a softfork will never be
1360  // activated. This is used when merging logic to implement a proposed
1361  // softfork without a specified deployment schedule.
1362  if (consensusParams.vDeployments[id].nTimeout <= 1230768000) {
1363  return;
1364  }
1365 
1366  UniValue bip9(UniValue::VOBJ);
1367  const ThresholdState thresholdState =
1368  VersionBitsTipState(consensusParams, id);
1369  switch (thresholdState) {
1371  bip9.pushKV("status", "defined");
1372  break;
1374  bip9.pushKV("status", "started");
1375  break;
1377  bip9.pushKV("status", "locked_in");
1378  break;
1380  bip9.pushKV("status", "active");
1381  break;
1383  bip9.pushKV("status", "failed");
1384  break;
1385  }
1386  if (ThresholdState::STARTED == thresholdState) {
1387  bip9.pushKV("bit", consensusParams.vDeployments[id].bit);
1388  }
1389  bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
1390  bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
1391  int64_t since_height = VersionBitsTipStateSinceHeight(consensusParams, id);
1392  bip9.pushKV("since", since_height);
1393  if (ThresholdState::STARTED == thresholdState) {
1394  UniValue statsUV(UniValue::VOBJ);
1395  BIP9Stats statsStruct = VersionBitsTipStatistics(consensusParams, id);
1396  statsUV.pushKV("period", statsStruct.period);
1397  statsUV.pushKV("threshold", statsStruct.threshold);
1398  statsUV.pushKV("elapsed", statsStruct.elapsed);
1399  statsUV.pushKV("count", statsStruct.count);
1400  statsUV.pushKV("possible", statsStruct.possible);
1401  bip9.pushKV("statistics", statsUV);
1402  }
1403 
1405  rv.pushKV("type", "bip9");
1406  rv.pushKV("bip9", bip9);
1407  if (ThresholdState::ACTIVE == thresholdState) {
1408  rv.pushKV("height", since_height);
1409  }
1410  rv.pushKV("active", ThresholdState::ACTIVE == thresholdState);
1411 
1412  softforks.pushKV(VersionBitsDeploymentInfo[id].name, rv);
1413 }
1414 
1416  const JSONRPCRequest &request) {
1417  RPCHelpMan{
1418  "getblockchaininfo",
1419  "Returns an object containing various state info regarding blockchain "
1420  "processing.\n",
1421  {},
1422  RPCResult{
1424  "",
1425  "",
1426  {
1427  {RPCResult::Type::STR, "chain",
1428  "current network name (main, test, regtest)"},
1429  {RPCResult::Type::NUM, "blocks",
1430  "the height of the most-work fully-validated chain. The "
1431  "genesis block has height 0"},
1432  {RPCResult::Type::NUM, "headers",
1433  "the current number of headers we have validated"},
1434  {RPCResult::Type::STR, "bestblockhash",
1435  "the hash of the currently best block"},
1436  {RPCResult::Type::NUM, "difficulty", "the current difficulty"},
1437  {RPCResult::Type::NUM, "mediantime",
1438  "median time for the current best block"},
1439  {RPCResult::Type::NUM, "verificationprogress",
1440  "estimate of verification progress [0..1]"},
1441  {RPCResult::Type::BOOL, "initialblockdownload",
1442  "(debug information) estimate of whether this node is in "
1443  "Initial Block Download mode"},
1444  {RPCResult::Type::STR_HEX, "chainwork",
1445  "total amount of work in active chain, in hexadecimal"},
1446  {RPCResult::Type::NUM, "size_on_disk",
1447  "the estimated size of the block and undo files on disk"},
1448  {RPCResult::Type::BOOL, "pruned",
1449  "if the blocks are subject to pruning"},
1450  {RPCResult::Type::NUM, "pruneheight",
1451  "lowest-height complete block stored (only present if pruning "
1452  "is enabled)"},
1453  {RPCResult::Type::BOOL, "automatic_pruning",
1454  "whether automatic pruning is enabled (only present if "
1455  "pruning is enabled)"},
1456  {RPCResult::Type::NUM, "prune_target_size",
1457  "the target size used by pruning (only present if automatic "
1458  "pruning is enabled)"},
1460  "softforks",
1461  "status of softforks",
1462  {
1464  "xxxx",
1465  "name of the softfork",
1466  {
1467  {RPCResult::Type::STR, "type",
1468  "one of \"buried\", \"bip9\""},
1470  "bip9",
1471  "status of bip9 softforks (only for \"bip9\" type)",
1472  {
1473  {RPCResult::Type::STR, "status",
1474  "one of \"defined\", \"started\", "
1475  "\"locked_in\", \"active\", \"failed\""},
1476  {RPCResult::Type::NUM, "bit",
1477  "the bit (0-28) in the block version field "
1478  "used to signal this softfork (only for "
1479  "\"started\" status)"},
1480  {RPCResult::Type::NUM_TIME, "start_time",
1481  "the minimum median time past of a block at "
1482  "which the bit gains its meaning"},
1483  {RPCResult::Type::NUM_TIME, "timeout",
1484  "the median time past of a block at which the "
1485  "deployment is considered failed if not yet "
1486  "locked in"},
1487  {RPCResult::Type::NUM, "since",
1488  "height of the first block to which the status "
1489  "applies"},
1491  "statistics",
1492  "numeric statistics about BIP9 signalling for "
1493  "a softfork",
1494  {
1495  {RPCResult::Type::NUM, "period",
1496  "the length in blocks of the BIP9 "
1497  "signalling period"},
1498  {RPCResult::Type::NUM, "threshold",
1499  "the number of blocks with the version "
1500  "bit set required to activate the "
1501  "feature"},
1502  {RPCResult::Type::NUM, "elapsed",
1503  "the number of blocks elapsed since the "
1504  "beginning of the current period"},
1505  {RPCResult::Type::NUM, "count",
1506  "the number of blocks with the version "
1507  "bit set in the current period"},
1508  {RPCResult::Type::BOOL, "possible",
1509  "returns false if there are not enough "
1510  "blocks left in this period to pass "
1511  "activation threshold"},
1512  }},
1513  }},
1514  {RPCResult::Type::NUM, "height",
1515  "height of the first block which the rules are or "
1516  "will be enforced (only for \"buried\" type, or "
1517  "\"bip9\" type with \"active\" status)"},
1518  {RPCResult::Type::BOOL, "active",
1519  "true if the rules are enforced for the mempool and "
1520  "the next block"},
1521  }},
1522  }},
1523  {RPCResult::Type::STR, "warnings",
1524  "any network and blockchain warnings"},
1525  }},
1526  RPCExamples{HelpExampleCli("getblockchaininfo", "") +
1527  HelpExampleRpc("getblockchaininfo", "")},
1528  }
1529  .Check(request);
1530 
1531  LOCK(cs_main);
1532 
1533  const CChainParams &chainparams = config.GetChainParams();
1534 
1535  const CBlockIndex *tip = ::ChainActive().Tip();
1536  UniValue obj(UniValue::VOBJ);
1537  obj.pushKV("chain", chainparams.NetworkIDString());
1538  obj.pushKV("blocks", int(::ChainActive().Height()));
1539  obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1);
1540  obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
1541  obj.pushKV("difficulty", double(GetDifficulty(tip)));
1542  obj.pushKV("mediantime", int64_t(tip->GetMedianTimePast()));
1543  obj.pushKV("verificationprogress",
1544  GuessVerificationProgress(Params().TxData(), tip));
1545  obj.pushKV("initialblockdownload",
1546  ::ChainstateActive().IsInitialBlockDownload());
1547  obj.pushKV("chainwork", tip->nChainWork.GetHex());
1548  obj.pushKV("size_on_disk", CalculateCurrentUsage());
1549  obj.pushKV("pruned", fPruneMode);
1550 
1551  if (fPruneMode) {
1552  const CBlockIndex *block = tip;
1553  CHECK_NONFATAL(block);
1554  while (block->pprev && (block->pprev->nStatus.hasData())) {
1555  block = block->pprev;
1556  }
1557 
1558  obj.pushKV("pruneheight", block->nHeight);
1559 
1560  // if 0, execution bypasses the whole if block.
1561  bool automatic_pruning = (gArgs.GetArg("-prune", 0) != 1);
1562  obj.pushKV("automatic_pruning", automatic_pruning);
1563  if (automatic_pruning) {
1564  obj.pushKV("prune_target_size", nPruneTarget);
1565  }
1566  }
1567 
1568  UniValue softforks(UniValue::VOBJ);
1569  for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
1570  BIP9SoftForkDescPushBack(softforks, chainparams.GetConsensus(),
1572  }
1573  obj.pushKV("softforks", softforks);
1574 
1575  obj.pushKV("warnings", GetWarnings(false));
1576  return obj;
1577 }
1578 
1581  bool operator()(const CBlockIndex *a, const CBlockIndex *b) const {
1582  // Make sure that unequal blocks with the same height do not compare
1583  // equal. Use the pointers themselves to make a distinction.
1584  if (a->nHeight != b->nHeight) {
1585  return (a->nHeight > b->nHeight);
1586  }
1587 
1588  return a < b;
1589  }
1590 };
1591 
1592 static UniValue getchaintips(const Config &config,
1593  const JSONRPCRequest &request) {
1594  RPCHelpMan{
1595  "getchaintips",
1596  "Return information about all known tips in the block tree, including "
1597  "the main chain as well as orphaned branches.\n",
1598  {},
1599  RPCResult{
1601  "",
1602  "",
1604  "",
1605  "",
1606  {
1607  {RPCResult::Type::NUM, "height", "height of the chain tip"},
1608  {RPCResult::Type::STR_HEX, "hash", "block hash of the tip"},
1609  {RPCResult::Type::NUM, "branchlen",
1610  "zero for main chain, otherwise length of branch connecting "
1611  "the tip to the main chain"},
1612  {RPCResult::Type::STR, "status",
1613  "status of the chain, \"active\" for the main chain\n"
1614  "Possible values for status:\n"
1615  "1. \"invalid\" This branch contains at "
1616  "least one invalid block\n"
1617  "2. \"parked\" This branch contains at "
1618  "least one parked block\n"
1619  "3. \"headers-only\" Not all blocks for this "
1620  "branch are available, but the headers are valid\n"
1621  "4. \"valid-headers\" All blocks are available for "
1622  "this branch, but they were never fully validated\n"
1623  "5. \"valid-fork\" This branch is not part of "
1624  "the active chain, but is fully validated\n"
1625  "6. \"active\" This is the tip of the "
1626  "active main chain, which is certainly valid"},
1627  }}}},
1628  RPCExamples{HelpExampleCli("getchaintips", "") +
1629  HelpExampleRpc("getchaintips", "")},
1630  }
1631  .Check(request);
1632 
1633  LOCK(cs_main);
1634 
1644  std::set<const CBlockIndex *, CompareBlocksByHeight> setTips;
1645  std::set<const CBlockIndex *> setOrphans;
1646  std::set<const CBlockIndex *> setPrevs;
1647 
1648  for (const std::pair<const BlockHash, CBlockIndex *> &item :
1649  ::BlockIndex()) {
1650  if (!::ChainActive().Contains(item.second)) {
1651  setOrphans.insert(item.second);
1652  setPrevs.insert(item.second->pprev);
1653  }
1654  }
1655 
1656  for (std::set<const CBlockIndex *>::iterator it = setOrphans.begin();
1657  it != setOrphans.end(); ++it) {
1658  if (setPrevs.erase(*it) == 0) {
1659  setTips.insert(*it);
1660  }
1661  }
1662 
1663  // Always report the currently active tip.
1664  setTips.insert(::ChainActive().Tip());
1665 
1666  /* Construct the output array. */
1667  UniValue res(UniValue::VARR);
1668  for (const CBlockIndex *block : setTips) {
1669  UniValue obj(UniValue::VOBJ);
1670  obj.pushKV("height", block->nHeight);
1671  obj.pushKV("hash", block->phashBlock->GetHex());
1672 
1673  const int branchLen =
1674  block->nHeight - ::ChainActive().FindFork(block)->nHeight;
1675  obj.pushKV("branchlen", branchLen);
1676 
1677  std::string status;
1678  if (::ChainActive().Contains(block)) {
1679  // This block is part of the currently active chain.
1680  status = "active";
1681  } else if (block->nStatus.isInvalid()) {
1682  // This block or one of its ancestors is invalid.
1683  status = "invalid";
1684  } else if (block->nStatus.isOnParkedChain()) {
1685  // This block or one of its ancestors is parked.
1686  status = "parked";
1687  } else if (!block->HaveTxsDownloaded()) {
1688  // This block cannot be connected because full block data for it or
1689  // one of its parents is missing.
1690  status = "headers-only";
1691  } else if (block->IsValid(BlockValidity::SCRIPTS)) {
1692  // This block is fully validated, but no longer part of the active
1693  // chain. It was probably the active block once, but was
1694  // reorganized.
1695  status = "valid-fork";
1696  } else if (block->IsValid(BlockValidity::TREE)) {
1697  // The headers for this block are valid, but it has not been
1698  // validated. It was probably never part of the most-work chain.
1699  status = "valid-headers";
1700  } else {
1701  // No clue.
1702  status = "unknown";
1703  }
1704  obj.pushKV("status", status);
1705 
1706  res.push_back(obj);
1707  }
1708 
1709  return res;
1710 }
1711 
1713  // Make sure this call is atomic in the pool.
1714  LOCK(pool.cs);
1715  UniValue ret(UniValue::VOBJ);
1716  ret.pushKV("loaded", pool.IsLoaded());
1717  ret.pushKV("size", (int64_t)pool.size());
1718  ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
1719  ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
1720  size_t maxmempool =
1721  gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
1722  ret.pushKV("maxmempool", (int64_t)maxmempool);
1723  ret.pushKV(
1724  "mempoolminfee",
1725  ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee)
1726  .GetFeePerK()));
1727  ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
1728 
1729  return ret;
1730 }
1731 
1732 static UniValue getmempoolinfo(const Config &config,
1733  const JSONRPCRequest &request) {
1734  RPCHelpMan{
1735  "getmempoolinfo",
1736  "Returns details on the active state of the TX memory pool.\n",
1737  {},
1738  RPCResult{
1740  "",
1741  "",
1742  {
1743  {RPCResult::Type::BOOL, "loaded",
1744  "True if the mempool is fully loaded"},
1745  {RPCResult::Type::NUM, "size", "Current tx count"},
1746  {RPCResult::Type::NUM, "bytes", "Sum of all transaction sizes"},
1747  {RPCResult::Type::NUM, "usage",
1748  "Total memory usage for the mempool"},
1749  {RPCResult::Type::NUM, "maxmempool",
1750  "Maximum memory usage for the mempool"},
1751  {RPCResult::Type::STR_AMOUNT, "mempoolminfee",
1752  "Minimum fee rate in " + CURRENCY_UNIT +
1753  "/kB for tx to be accepted. Is the maximum of "
1754  "minrelaytxfee and minimum mempool fee"},
1755  {RPCResult::Type::STR_AMOUNT, "minrelaytxfee",
1756  "Current minimum relay fee for transactions"},
1757  }},
1758  RPCExamples{HelpExampleCli("getmempoolinfo", "") +
1759  HelpExampleRpc("getmempoolinfo", "")},
1760  }
1761  .Check(request);
1762 
1763  return MempoolInfoToJSON(EnsureMemPool(request.context));
1764 }
1765 
1766 static UniValue preciousblock(const Config &config,
1767  const JSONRPCRequest &request) {
1768  RPCHelpMan{
1769  "preciousblock",
1770  "Treats a block as if it were received before others with the same "
1771  "work.\n"
1772  "\nA later preciousblock call can override the effect of an earlier "
1773  "one.\n"
1774  "\nThe effects of preciousblock are not retained across restarts.\n",
1775  {
1777  "the hash of the block to mark as precious"},
1778  },
1780  RPCExamples{HelpExampleCli("preciousblock", "\"blockhash\"") +
1781  HelpExampleRpc("preciousblock", "\"blockhash\"")},
1782  }
1783  .Check(request);
1784 
1785  BlockHash hash(ParseHashV(request.params[0], "blockhash"));
1786  CBlockIndex *pblockindex;
1787 
1788  {
1789  LOCK(cs_main);
1790  pblockindex = LookupBlockIndex(hash);
1791  if (!pblockindex) {
1792  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1793  }
1794  }
1795 
1796  BlockValidationState state;
1797  PreciousBlock(config, state, pblockindex);
1798 
1799  if (!state.IsValid()) {
1801  }
1802 
1803  return NullUniValue;
1804 }
1805 
1806 UniValue finalizeblock(const Config &config, const JSONRPCRequest &request) {
1807  RPCHelpMan{
1808  "finalizeblock",
1809  "Treats a block as final. It cannot be reorged. Any chain\n"
1810  "that does not contain this block is invalid. Used on a less\n"
1811  "work chain, it can effectively PUT YOU OUT OF CONSENSUS.\n"
1812  "USE WITH CAUTION!\n",
1813  {
1815  "the hash of the block to mark as invalid"},
1816  },
1818  RPCExamples{HelpExampleCli("finalizeblock", "\"blockhash\"") +
1819  HelpExampleRpc("finalizeblock", "\"blockhash\"")},
1820  }
1821  .Check(request);
1822 
1823  std::string strHash = request.params[0].get_str();
1824  BlockHash hash(uint256S(strHash));
1825  BlockValidationState state;
1826 
1827  CBlockIndex *pblockindex = nullptr;
1828  {
1829  LOCK(cs_main);
1830  pblockindex = LookupBlockIndex(hash);
1831  if (!pblockindex) {
1832  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1833  }
1834  } // end of locked cs_main scope
1835 
1836  ::ChainstateActive().FinalizeBlock(config, state, pblockindex);
1837 
1838  if (state.IsValid()) {
1839  ActivateBestChain(config, state);
1840  }
1841 
1842  if (!state.IsValid()) {
1843  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
1844  }
1845 
1846  return NullUniValue;
1847 }
1848 
1849 static UniValue invalidateblock(const Config &config,
1850  const JSONRPCRequest &request) {
1851  RPCHelpMan{
1852  "invalidateblock",
1853  "Permanently marks a block as invalid, as if it violated a consensus "
1854  "rule.\n",
1855  {
1857  "the hash of the block to mark as invalid"},
1858  },
1860  RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") +
1861  HelpExampleRpc("invalidateblock", "\"blockhash\"")},
1862  }
1863  .Check(request);
1864 
1865  const BlockHash hash(ParseHashV(request.params[0], "blockhash"));
1866  BlockValidationState state;
1867 
1868  CBlockIndex *pblockindex;
1869  {
1870  LOCK(cs_main);
1871  pblockindex = LookupBlockIndex(hash);
1872  if (!pblockindex) {
1873  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1874  }
1875  }
1876  ::ChainstateActive().InvalidateBlock(config, state, pblockindex);
1877 
1878  if (state.IsValid()) {
1879  ActivateBestChain(config, state);
1880  }
1881 
1882  if (!state.IsValid()) {
1883  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
1884  }
1885 
1886  return NullUniValue;
1887 }
1888 
1889 UniValue parkblock(const Config &config, const JSONRPCRequest &request) {
1890  RPCHelpMan{
1891  "parkblock",
1892  "Marks a block as parked.\n",
1893  {
1895  "the hash of the block to park"},
1896  },
1898  RPCExamples{HelpExampleCli("parkblock", "\"blockhash\"") +
1899  HelpExampleRpc("parkblock", "\"blockhash\"")},
1900  }
1901  .Check(request);
1902 
1903  const std::string strHash = request.params[0].get_str();
1904  const BlockHash hash(uint256S(strHash));
1905  BlockValidationState state;
1906 
1907  CBlockIndex *pblockindex = nullptr;
1908  {
1909  LOCK(cs_main);
1910  pblockindex = LookupBlockIndex(hash);
1911  if (!pblockindex) {
1912  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1913  }
1914  }
1915  ::ChainstateActive().ParkBlock(config, state, pblockindex);
1916 
1917  if (state.IsValid()) {
1918  ActivateBestChain(config, state);
1919  }
1920 
1921  if (!state.IsValid()) {
1923  }
1924 
1925  return NullUniValue;
1926 }
1927 
1928 static UniValue reconsiderblock(const Config &config,
1929  const JSONRPCRequest &request) {
1930  RPCHelpMan{
1931  "reconsiderblock",
1932  "Removes invalidity status of a block, its ancestors and its"
1933  "descendants, reconsider them for activation.\n"
1934  "This can be used to undo the effects of invalidateblock.\n",
1935  {
1937  "the hash of the block to reconsider"},
1938  },
1940  RPCExamples{HelpExampleCli("reconsiderblock", "\"blockhash\"") +
1941  HelpExampleRpc("reconsiderblock", "\"blockhash\"")},
1942  }
1943  .Check(request);
1944 
1945  const BlockHash hash(ParseHashV(request.params[0], "blockhash"));
1946 
1947  {
1948  LOCK(cs_main);
1949  CBlockIndex *pblockindex = LookupBlockIndex(hash);
1950  if (!pblockindex) {
1951  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1952  }
1953 
1954  ResetBlockFailureFlags(pblockindex);
1955  }
1956 
1957  BlockValidationState state;
1958  ActivateBestChain(config, state);
1959 
1960  if (!state.IsValid()) {
1961  throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
1962  }
1963 
1964  return NullUniValue;
1965 }
1966 
1967 UniValue unparkblock(const Config &config, const JSONRPCRequest &request) {
1968  RPCHelpMan{
1969  "unparkblock",
1970  "Removes parked status of a block and its descendants, reconsider "
1971  "them for activation.\n"
1972  "This can be used to undo the effects of parkblock.\n",
1973  {
1975  "the hash of the block to unpark"},
1976  },
1978  RPCExamples{HelpExampleCli("unparkblock", "\"blockhash\"") +
1979  HelpExampleRpc("unparkblock", "\"blockhash\"")},
1980  }
1981  .Check(request);
1982 
1983  const std::string strHash = request.params[0].get_str();
1984  const BlockHash hash(uint256S(strHash));
1985 
1986  {
1987  LOCK(cs_main);
1988 
1989  CBlockIndex *pblockindex = LookupBlockIndex(hash);
1990  if (!pblockindex) {
1991  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1992  }
1993 
1994  UnparkBlockAndChildren(pblockindex);
1995  }
1996 
1997  BlockValidationState state;
1998  ActivateBestChain(config, state);
1999 
2000  if (!state.IsValid()) {
2002  }
2003 
2004  return NullUniValue;
2005 }
2006 
2007 static UniValue getchaintxstats(const Config &config,
2008  const JSONRPCRequest &request) {
2009  RPCHelpMan{
2010  "getchaintxstats",
2011  "Compute statistics about the total number and rate of transactions "
2012  "in the chain.\n",
2013  {
2014  {"nblocks", RPCArg::Type::NUM, /* default */ "one month",
2015  "Size of the window in number of blocks"},
2016  {"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip",
2017  "The hash of the block that ends the window."},
2018  },
2020  "",
2021  "",
2022  {
2023  {RPCResult::Type::NUM_TIME, "time",
2024  "The timestamp for the final block in the window, "
2025  "expressed in " +
2026  UNIX_EPOCH_TIME},
2027  {RPCResult::Type::NUM, "txcount",
2028  "The total number of transactions in the chain up to "
2029  "that point"},
2030  {RPCResult::Type::STR_HEX, "window_final_block_hash",
2031  "The hash of the final block in the window"},
2032  {RPCResult::Type::NUM, "window_final_block_height",
2033  "The height of the final block in the window."},
2034  {RPCResult::Type::NUM, "window_block_count",
2035  "Size of the window in number of blocks"},
2036  {RPCResult::Type::NUM, "window_tx_count",
2037  "The number of transactions in the window. Only "
2038  "returned if \"window_block_count\" is > 0"},
2039  {RPCResult::Type::NUM, "window_interval",
2040  "The elapsed time in the window in seconds. Only "
2041  "returned if \"window_block_count\" is > 0"},
2042  {RPCResult::Type::NUM, "txrate",
2043  "The average rate of transactions per second in the "
2044  "window. Only returned if \"window_interval\" is > 0"},
2045  }},
2046  RPCExamples{HelpExampleCli("getchaintxstats", "") +
2047  HelpExampleRpc("getchaintxstats", "2016")},
2048  }
2049  .Check(request);
2050 
2051  const CBlockIndex *pindex;
2052 
2053  // By default: 1 month
2054  int blockcount = 30 * 24 * 60 * 60 /
2056 
2057  if (request.params[1].isNull()) {
2058  LOCK(cs_main);
2059  pindex = ::ChainActive().Tip();
2060  } else {
2061  BlockHash hash(ParseHashV(request.params[1], "blockhash"));
2062  LOCK(cs_main);
2063  pindex = LookupBlockIndex(hash);
2064  if (!pindex) {
2065  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
2066  }
2067  if (!::ChainActive().Contains(pindex)) {
2069  "Block is not in main chain");
2070  }
2071  }
2072 
2073  CHECK_NONFATAL(pindex != nullptr);
2074 
2075  if (request.params[0].isNull()) {
2076  blockcount = std::max(0, std::min(blockcount, pindex->nHeight - 1));
2077  } else {
2078  blockcount = request.params[0].get_int();
2079 
2080  if (blockcount < 0 ||
2081  (blockcount > 0 && blockcount >= pindex->nHeight)) {
2082  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: "
2083  "should be between 0 and "
2084  "the block's height - 1");
2085  }
2086  }
2087 
2088  const CBlockIndex *pindexPast =
2089  pindex->GetAncestor(pindex->nHeight - blockcount);
2090  int nTimeDiff =
2091  pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast();
2092  int nTxDiff = pindex->GetChainTxCount() - pindexPast->GetChainTxCount();
2093 
2094  UniValue ret(UniValue::VOBJ);
2095  ret.pushKV("time", pindex->GetBlockTime());
2096  ret.pushKV("txcount", pindex->GetChainTxCount());
2097  ret.pushKV("window_final_block_hash", pindex->GetBlockHash().GetHex());
2098  ret.pushKV("window_final_block_height", pindex->nHeight);
2099  ret.pushKV("window_block_count", blockcount);
2100  if (blockcount > 0) {
2101  ret.pushKV("window_tx_count", nTxDiff);
2102  ret.pushKV("window_interval", nTimeDiff);
2103  if (nTimeDiff > 0) {
2104  ret.pushKV("txrate", double(nTxDiff) / nTimeDiff);
2105  }
2106  }
2107 
2108  return ret;
2109 }
2110 
2111 template <typename T>
2112 static T CalculateTruncatedMedian(std::vector<T> &scores) {
2113  size_t size = scores.size();
2114  if (size == 0) {
2115  return T();
2116  }
2117 
2118  std::sort(scores.begin(), scores.end());
2119  if (size % 2 == 0) {
2120  return (scores[size / 2 - 1] + scores[size / 2]) / 2;
2121  } else {
2122  return scores[size / 2];
2123  }
2124 }
2125 
2126 template <typename T> static inline bool SetHasKeys(const std::set<T> &set) {
2127  return false;
2128 }
2129 template <typename T, typename Tk, typename... Args>
2130 static inline bool SetHasKeys(const std::set<T> &set, const Tk &key,
2131  const Args &... args) {
2132  return (set.count(key) != 0) || SetHasKeys(set, args...);
2133 }
2134 
2135 // outpoint (needed for the utxo index) + nHeight + fCoinBase
2136 static constexpr size_t PER_UTXO_OVERHEAD =
2137  sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool);
2138 
2139 static UniValue getblockstats(const Config &config,
2140  const JSONRPCRequest &request) {
2141  RPCHelpMan{
2142  "getblockstats",
2143  "Compute per block statistics for a given window. All amounts are "
2144  "in " +
2145  CURRENCY_UNIT +
2146  ".\n"
2147  "It won't work for some heights with pruning.\n",
2148  {
2149  {"hash_or_height",
2152  "The block hash or height of the target block",
2153  "",
2154  {"", "string or numeric"}},
2155  {"stats",
2157  /* default */ "all values",
2158  "Values to plot (see result below)",
2159  {
2161  "Selected statistic"},
2163  "Selected statistic"},
2164  },
2165  "stats"},
2166  },
2167  RPCResult{
2169  "",
2170  "",
2171  {
2172  {RPCResult::Type::NUM, "avgfee", "Average fee in the block"},
2173  {RPCResult::Type::NUM, "avgfeerate",
2174  "Average feerate (in satoshis per virtual byte)"},
2175  {RPCResult::Type::NUM, "avgtxsize", "Average transaction size"},
2176  {RPCResult::Type::STR_HEX, "blockhash",
2177  "The block hash (to check for potential reorgs)"},
2178  {RPCResult::Type::NUM, "height", "The height of the block"},
2179  {RPCResult::Type::NUM, "ins",
2180  "The number of inputs (excluding coinbase)"},
2181  {RPCResult::Type::NUM, "maxfee", "Maximum fee in the block"},
2182  {RPCResult::Type::NUM, "maxfeerate",
2183  "Maximum feerate (in satoshis per virtual byte)"},
2184  {RPCResult::Type::NUM, "maxtxsize", "Maximum transaction size"},
2185  {RPCResult::Type::NUM, "medianfee",
2186  "Truncated median fee in the block"},
2187  {RPCResult::Type::NUM, "medianfeerate",
2188  "Truncated median feerate (in " + CURRENCY_UNIT +
2189  " per byte)"},
2190  {RPCResult::Type::NUM, "mediantime",
2191  "The block median time past"},
2192  {RPCResult::Type::NUM, "mediantxsize",
2193  "Truncated median transaction size"},
2194  {RPCResult::Type::NUM, "minfee", "Minimum fee in the block"},
2195  {RPCResult::Type::NUM, "minfeerate",
2196  "Minimum feerate (in satoshis per virtual byte)"},
2197  {RPCResult::Type::NUM, "mintxsize", "Minimum transaction size"},
2198  {RPCResult::Type::NUM, "outs", "The number of outputs"},
2199  {RPCResult::Type::NUM, "subsidy", "The block subsidy"},
2200  {RPCResult::Type::NUM, "time", "The block time"},
2201  {RPCResult::Type::NUM, "total_out",
2202  "Total amount in all outputs (excluding coinbase and thus "
2203  "reward [ie subsidy + totalfee])"},
2204  {RPCResult::Type::NUM, "total_size",
2205  "Total size of all non-coinbase transactions"},
2206  {RPCResult::Type::NUM, "totalfee", "The fee total"},
2207  {RPCResult::Type::NUM, "txs",
2208  "The number of transactions (excluding coinbase)"},
2209  {RPCResult::Type::NUM, "utxo_increase",
2210  "The increase/decrease in the number of unspent outputs"},
2211  {RPCResult::Type::NUM, "utxo_size_inc",
2212  "The increase/decrease in size for the utxo index (not "
2213  "discounting op_return and similar)"},
2214  }},
2215  RPCExamples{
2217  "getblockstats",
2218  R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") +
2219  HelpExampleCli("getblockstats",
2220  R"(1000 '["minfeerate","avgfeerate"]')") +
2222  "getblockstats",
2223  R"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") +
2224  HelpExampleRpc("getblockstats",
2225  R"(1000, ["minfeerate","avgfeerate"])")},
2226  }
2227  .Check(request);
2228 
2229  LOCK(cs_main);
2230 
2231  CBlockIndex *pindex;
2232  if (request.params[0].isNum()) {
2233  const int height = request.params[0].get_int();
2234  const int current_tip = ::ChainActive().Height();
2235  if (height < 0) {
2236  throw JSONRPCError(
2238  strprintf("Target block height %d is negative", height));
2239  }
2240  if (height > current_tip) {
2241  throw JSONRPCError(
2243  strprintf("Target block height %d after current tip %d", height,
2244  current_tip));
2245  }
2246 
2247  pindex = ::ChainActive()[height];
2248  } else {
2249  const BlockHash hash(ParseHashV(request.params[0], "hash_or_height"));
2250  pindex = LookupBlockIndex(hash);
2251  if (!pindex) {
2252  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
2253  }
2254  if (!::ChainActive().Contains(pindex)) {
2256  strprintf("Block is not in chain %s",
2257  Params().NetworkIDString()));
2258  }
2259  }
2260 
2261  CHECK_NONFATAL(pindex != nullptr);
2262 
2263  std::set<std::string> stats;
2264  if (!request.params[1].isNull()) {
2265  const UniValue stats_univalue = request.params[1].get_array();
2266  for (unsigned int i = 0; i < stats_univalue.size(); i++) {
2267  const std::string stat = stats_univalue[i].get_str();
2268  stats.insert(stat);
2269  }
2270  }
2271 
2272  const CBlock block = GetBlockChecked(config, pindex);
2273  const CBlockUndo blockUndo = GetUndoChecked(pindex);
2274 
2275  // Calculate everything if nothing selected (default)
2276  const bool do_all = stats.size() == 0;
2277  const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0;
2278  const bool do_medianfee = do_all || stats.count("medianfee") != 0;
2279  const bool do_medianfeerate = do_all || stats.count("medianfeerate") != 0;
2280  const bool loop_inputs =
2281  do_all || do_medianfee || do_medianfeerate ||
2282  SetHasKeys(stats, "utxo_size_inc", "totalfee", "avgfee", "avgfeerate",
2283  "minfee", "maxfee", "minfeerate", "maxfeerate");
2284  const bool loop_outputs = do_all || loop_inputs || stats.count("total_out");
2285  const bool do_calculate_size =
2286  do_mediantxsize || loop_inputs ||
2287  SetHasKeys(stats, "total_size", "avgtxsize", "mintxsize", "maxtxsize");
2288 
2289  const int64_t blockMaxSize = config.GetMaxBlockSize();
2290  Amount maxfee = Amount::zero();
2291  Amount maxfeerate = Amount::zero();
2292  Amount minfee = MAX_MONEY;
2293  Amount minfeerate = MAX_MONEY;
2294  Amount total_out = Amount::zero();
2295  Amount totalfee = Amount::zero();
2296  int64_t inputs = 0;
2297  int64_t maxtxsize = 0;
2298  int64_t mintxsize = blockMaxSize;
2299  int64_t outputs = 0;
2300  int64_t total_size = 0;
2301  int64_t utxo_size_inc = 0;
2302  std::vector<Amount> fee_array;
2303  std::vector<Amount> feerate_array;
2304  std::vector<int64_t> txsize_array;
2305 
2306  for (size_t i = 0; i < block.vtx.size(); ++i) {
2307  const auto &tx = block.vtx.at(i);
2308  outputs += tx->vout.size();
2309  Amount tx_total_out = Amount::zero();
2310  if (loop_outputs) {
2311  for (const CTxOut &out : tx->vout) {
2312  tx_total_out += out.nValue;
2313  utxo_size_inc +=
2315  }
2316  }
2317 
2318  if (tx->IsCoinBase()) {
2319  continue;
2320  }
2321 
2322  // Don't count coinbase's fake input
2323  inputs += tx->vin.size();
2324  // Don't count coinbase reward
2325  total_out += tx_total_out;
2326 
2327  int64_t tx_size = 0;
2328  if (do_calculate_size) {
2329  tx_size = tx->GetTotalSize();
2330  if (do_mediantxsize) {
2331  txsize_array.push_back(tx_size);
2332  }
2333  maxtxsize = std::max(maxtxsize, tx_size);
2334  mintxsize = std::min(mintxsize, tx_size);
2335  total_size += tx_size;
2336  }
2337 
2338  if (loop_inputs) {
2339  Amount tx_total_in = Amount::zero();
2340  const auto &txundo = blockUndo.vtxundo.at(i - 1);
2341  for (const Coin &coin : txundo.vprevout) {
2342  const CTxOut &prevoutput = coin.GetTxOut();
2343 
2344  tx_total_in += prevoutput.nValue;
2345  utxo_size_inc -=
2346  GetSerializeSize(prevoutput, PROTOCOL_VERSION) +
2348  }
2349 
2350  Amount txfee = tx_total_in - tx_total_out;
2351  CHECK_NONFATAL(MoneyRange(txfee));
2352  if (do_medianfee) {
2353  fee_array.push_back(txfee);
2354  }
2355  maxfee = std::max(maxfee, txfee);
2356  minfee = std::min(minfee, txfee);
2357  totalfee += txfee;
2358 
2359  Amount feerate = txfee / tx_size;
2360  if (do_medianfeerate) {
2361  feerate_array.push_back(feerate);
2362  }
2363  maxfeerate = std::max(maxfeerate, feerate);
2364  minfeerate = std::min(minfeerate, feerate);
2365  }
2366  }
2367 
2368  UniValue ret_all(UniValue::VOBJ);
2369  ret_all.pushKV("avgfee",
2370  ValueFromAmount((block.vtx.size() > 1)
2371  ? totalfee / int((block.vtx.size() - 1))
2372  : Amount::zero()));
2373  ret_all.pushKV("avgfeerate",
2374  ValueFromAmount((total_size > 0) ? totalfee / total_size
2375  : Amount::zero()));
2376  ret_all.pushKV("avgtxsize", (block.vtx.size() > 1)
2377  ? total_size / (block.vtx.size() - 1)
2378  : 0);
2379  ret_all.pushKV("blockhash", pindex->GetBlockHash().GetHex());
2380  ret_all.pushKV("height", (int64_t)pindex->nHeight);
2381  ret_all.pushKV("ins", inputs);
2382  ret_all.pushKV("maxfee", ValueFromAmount(maxfee));
2383  ret_all.pushKV("maxfeerate", ValueFromAmount(maxfeerate));
2384  ret_all.pushKV("maxtxsize", maxtxsize);
2385  ret_all.pushKV("medianfee",
2387  ret_all.pushKV("medianfeerate",
2388  ValueFromAmount(CalculateTruncatedMedian(feerate_array)));
2389  ret_all.pushKV("mediantime", pindex->GetMedianTimePast());
2390  ret_all.pushKV("mediantxsize", CalculateTruncatedMedian(txsize_array));
2391  ret_all.pushKV(
2392  "minfee",
2393  ValueFromAmount((minfee == MAX_MONEY) ? Amount::zero() : minfee));
2394  ret_all.pushKV("minfeerate",
2395  ValueFromAmount((minfeerate == MAX_MONEY) ? Amount::zero()
2396  : minfeerate));
2397  ret_all.pushKV("mintxsize", mintxsize == blockMaxSize ? 0 : mintxsize);
2398  ret_all.pushKV("outs", outputs);
2399  ret_all.pushKV("subsidy", ValueFromAmount(GetBlockSubsidy(
2400  pindex->nHeight, Params().GetConsensus())));
2401  ret_all.pushKV("time", pindex->GetBlockTime());
2402  ret_all.pushKV("total_out", ValueFromAmount(total_out));
2403  ret_all.pushKV("total_size", total_size);
2404  ret_all.pushKV("totalfee", ValueFromAmount(totalfee));
2405  ret_all.pushKV("txs", (int64_t)block.vtx.size());
2406  ret_all.pushKV("utxo_increase", outputs - inputs);
2407  ret_all.pushKV("utxo_size_inc", utxo_size_inc);
2408 
2409  if (do_all) {
2410  return ret_all;
2411  }
2412 
2413  UniValue ret(UniValue::VOBJ);
2414  for (const std::string &stat : stats) {
2415  const UniValue &value = ret_all[stat];
2416  if (value.isNull()) {
2417  throw JSONRPCError(
2419  strprintf("Invalid selected statistic %s", stat));
2420  }
2421  ret.pushKV(stat, value);
2422  }
2423  return ret;
2424 }
2425 
2426 static UniValue savemempool(const Config &config,
2427  const JSONRPCRequest &request) {
2428  RPCHelpMan{
2429  "savemempool",
2430  "Dumps the mempool to disk. It will fail until the previous dump is "
2431  "fully loaded.\n",
2432  {},
2434  RPCExamples{HelpExampleCli("savemempool", "") +
2435  HelpExampleRpc("savemempool", "")},
2436  }
2437  .Check(request);
2438 
2439  const CTxMemPool &mempool = EnsureMemPool(request.context);
2440 
2441  if (!mempool.IsLoaded()) {
2442  throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
2443  }
2444 
2445  if (!DumpMempool(mempool)) {
2446  throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
2447  }
2448 
2449  return NullUniValue;
2450 }
2451 
2452 namespace {
2454 static bool FindScriptPubKey(std::atomic<int> &scan_progress,
2455  const std::atomic<bool> &should_abort,
2456  int64_t &count, CCoinsViewCursor *cursor,
2457  const std::set<CScript> &needles,
2458  std::map<COutPoint, Coin> &out_results,
2459  std::function<void()> &interruption_point) {
2460  scan_progress = 0;
2461  count = 0;
2462  while (cursor->Valid()) {
2463  COutPoint key;
2464  Coin coin;
2465  if (!cursor->GetKey(key) || !cursor->GetValue(coin)) {
2466  return false;
2467  }
2468  if (++count % 8192 == 0) {
2469  interruption_point();
2470  if (should_abort) {
2471  // allow to abort the scan via the abort reference
2472  return false;
2473  }
2474  }
2475  if (count % 256 == 0) {
2476  // update progress reference every 256 item
2477  const TxId &txid = key.GetTxId();
2478  uint32_t high = 0x100 * *txid.begin() + *(txid.begin() + 1);
2479  scan_progress = int(high * 100.0 / 65536.0 + 0.5);
2480  }
2481  if (needles.count(coin.GetTxOut().scriptPubKey)) {
2482  out_results.emplace(key, coin);
2483  }
2484  cursor->Next();
2485  }
2486  scan_progress = 100;
2487  return true;
2488 }
2489 } // namespace
2490 
2492 static std::atomic<int> g_scan_progress;
2493 static std::atomic<bool> g_scan_in_progress;
2494 static std::atomic<bool> g_should_abort_scan;
2496 private:
2498 
2499 public:
2500  explicit CoinsViewScanReserver() : m_could_reserve(false) {}
2501 
2502  bool reserve() {
2503  CHECK_NONFATAL(!m_could_reserve);
2504  if (g_scan_in_progress.exchange(true)) {
2505  return false;
2506  }
2507  m_could_reserve = true;
2508  return true;
2509  }
2510 
2512  if (m_could_reserve) {
2513  g_scan_in_progress = false;
2514  }
2515  }
2516 };
2517 
2518 static UniValue scantxoutset(const Config &config,
2519  const JSONRPCRequest &request) {
2520  RPCHelpMan{
2521  "scantxoutset",
2522  "EXPERIMENTAL warning: this call may be removed or changed in future "
2523  "releases.\n"
2524  "\nScans the unspent transaction output set for entries that match "
2525  "certain output descriptors.\n"
2526  "Examples of output descriptors are:\n"
2527  " addr(<address>) Outputs whose scriptPubKey "
2528  "corresponds to the specified address (does not include P2PK)\n"
2529  " raw(<hex script>) Outputs whose scriptPubKey "
2530  "equals the specified hex scripts\n"
2531  " combo(<pubkey>) P2PK and P2PKH outputs for "
2532  "the given pubkey\n"
2533  " pkh(<pubkey>) P2PKH outputs for the given "
2534  "pubkey\n"
2535  " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for "
2536  "the given threshold and pubkeys\n"
2537  "\nIn the above, <pubkey> either refers to a fixed public key in "
2538  "hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
2539  "or more path elements separated by \"/\", and optionally ending in "
2540  "\"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
2541  "unhardened or hardened child keys.\n"
2542  "In the latter case, a range needs to be specified by below if "
2543  "different from 1000.\n"
2544  "For more information on output descriptors, see the documentation in "
2545  "the doc/descriptors.md file.\n",
2546  {
2548  "The action to execute\n"
2549  " \"start\" for starting a "
2550  "scan\n"
2551  " \"abort\" for aborting the "
2552  "current scan (returns true when abort was successful)\n"
2553  " \"status\" for "
2554  "progress report (in %) of the current scan"},
2555  {"scanobjects",
2558  "Array of scan objects. Required for \"start\" action\n"
2559  " Every scan object is either a "
2560  "string descriptor or an object:",
2561  {
2563  "An output descriptor"},
2564  {
2565  "",
2568  "An object with output descriptor and metadata",
2569  {
2571  "An output descriptor"},
2572  {"range", RPCArg::Type::RANGE, /* default */ "1000",
2573  "The range of HD chain indexes to explore (either "
2574  "end or [begin,end])"},
2575  },
2576  },
2577  },
2578  "[scanobjects,...]"},
2579  },
2580  RPCResult{
2582  "",
2583  "",
2584  {
2585  {RPCResult::Type::BOOL, "success",
2586  "Whether the scan was completed"},
2587  {RPCResult::Type::NUM, "txouts",
2588  "The number of unspent transaction outputs scanned"},
2589  {RPCResult::Type::NUM, "height",
2590  "The current block height (index)"},
2591  {RPCResult::Type::STR_HEX, "bestblock",
2592  "The hash of the block at the tip of the chain"},
2594  "unspents",
2595  "",
2596  {
2598  "",
2599  "",
2600  {
2601  {RPCResult::Type::STR_HEX, "txid",
2602  "The transaction id"},
2603  {RPCResult::Type::NUM, "vout", "The vout value"},
2604  {RPCResult::Type::STR_HEX, "scriptPubKey",
2605  "The script key"},
2606  {RPCResult::Type::STR, "desc",
2607  "A specialized descriptor for the matched "
2608  "scriptPubKey"},
2609  {RPCResult::Type::STR_AMOUNT, "amount",
2610  "The total amount in " + CURRENCY_UNIT +
2611  " of the unspent output"},
2612  {RPCResult::Type::NUM, "height",
2613  "Height of the unspent transaction output"},
2614  }},
2615  }},
2616  {RPCResult::Type::STR_AMOUNT, "total_amount",
2617  "The total amount of all found unspent outputs in " +
2618  CURRENCY_UNIT},
2619  }},
2620  RPCExamples{""},
2621  }
2622  .Check(request);
2623 
2624  RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
2625 
2626  UniValue result(UniValue::VOBJ);
2627  if (request.params[0].get_str() == "status") {
2628  CoinsViewScanReserver reserver;
2629  if (reserver.reserve()) {
2630  // no scan in progress
2631  return NullUniValue;
2632  }
2633  result.pushKV("progress", g_scan_progress.load());
2634  return result;
2635  } else if (request.params[0].get_str() == "abort") {
2636  CoinsViewScanReserver reserver;
2637  if (reserver.reserve()) {
2638  // reserve was possible which means no scan was running
2639  return false;
2640  }
2641  // set the abort flag
2642  g_should_abort_scan = true;
2643  return true;
2644  } else if (request.params[0].get_str() == "start") {
2645  CoinsViewScanReserver reserver;
2646  if (!reserver.reserve()) {
2647  throw JSONRPCError(
2649  "Scan already in progress, use action \"abort\" or \"status\"");
2650  }
2651 
2652  if (request.params.size() < 2) {
2653  throw JSONRPCError(
2655  "scanobjects argument is required for the start action");
2656  }
2657 
2658  std::set<CScript> needles;
2659  std::map<CScript, std::string> descriptors;
2660  Amount total_in = Amount::zero();
2661 
2662  // loop through the scan objects
2663  for (const UniValue &scanobject :
2664  request.params[1].get_array().getValues()) {
2665  FlatSigningProvider provider;
2666  auto scripts = EvalDescriptorStringOrObject(scanobject, provider);
2667  for (const auto &script : scripts) {
2668  std::string inferred =
2669  InferDescriptor(script, provider)->ToString();
2670  needles.emplace(script);
2671  descriptors.emplace(std::move(script), std::move(inferred));
2672  }
2673  }
2674 
2675  // Scan the unspent transaction output set for inputs
2676  UniValue unspents(UniValue::VARR);
2677  std::vector<CTxOut> input_txos;
2678  std::map<COutPoint, Coin> coins;
2679  g_should_abort_scan = false;
2680  g_scan_progress = 0;
2681  int64_t count = 0;
2682  std::unique_ptr<CCoinsViewCursor> pcursor;
2683  CBlockIndex *tip;
2684  {
2685  LOCK(cs_main);
2687  pcursor = std::unique_ptr<CCoinsViewCursor>(
2689  CHECK_NONFATAL(pcursor);
2690  tip = ::ChainActive().Tip();
2691  CHECK_NONFATAL(tip);
2692  }
2693  NodeContext &node = EnsureNodeContext(request.context);
2694  bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count,
2695  pcursor.get(), needles, coins,
2696  node.rpc_interruption_point);
2697  result.pushKV("success", res);
2698  result.pushKV("txouts", count);
2699  result.pushKV("height", tip->nHeight);
2700  result.pushKV("bestblock", tip->GetBlockHash().GetHex());
2701 
2702  for (const auto &it : coins) {
2703  const COutPoint &outpoint = it.first;
2704  const Coin &coin = it.second;
2705  const CTxOut &txo = coin.GetTxOut();
2706  input_txos.push_back(txo);
2707  total_in += txo.nValue;
2708 
2709  UniValue unspent(UniValue::VOBJ);
2710  unspent.pushKV("txid", outpoint.GetTxId().GetHex());
2711  unspent.pushKV("vout", int32_t(outpoint.GetN()));
2712  unspent.pushKV("scriptPubKey", HexStr(txo.scriptPubKey.begin(),
2713  txo.scriptPubKey.end()));
2714  unspent.pushKV("desc", descriptors[txo.scriptPubKey]);
2715  unspent.pushKV("amount", ValueFromAmount(txo.nValue));
2716  unspent.pushKV("height", int32_t(coin.GetHeight()));
2717 
2718  unspents.push_back(unspent);
2719  }
2720  result.pushKV("unspents", unspents);
2721  result.pushKV("total_amount", ValueFromAmount(total_in));
2722  } else {
2723  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid command");
2724  }
2725  return result;
2726 }
2727 
2728 static UniValue getblockfilter(const Config &config,
2729  const JSONRPCRequest &request) {
2730  RPCHelpMan{
2731  "getblockfilter",
2732  "Retrieve a BIP 157 content filter for a particular block.\n",
2733  {
2735  "The hash of the block"},
2736  {"filtertype", RPCArg::Type::STR, /*default*/ "basic",
2737  "The type name of the filter"},
2738  },
2740  "",
2741  "",
2742  {
2743  {RPCResult::Type::STR_HEX, "filter",
2744  "the hex-encoded filter data"},
2745  {RPCResult::Type::STR_HEX, "header",
2746  "the hex-encoded filter header"},
2747  }},
2748  RPCExamples{
2749  HelpExampleCli("getblockfilter",
2750  "\"00000000c937983704a73af28acdec37b049d214a"
2751  "dbda81d7e2a3dd146f6ed09\" \"basic\"") +
2752  HelpExampleRpc("getblockfilter",
2753  "\"00000000c937983704a73af28acdec37b049d214adbda81d7"
2754  "e2a3dd146f6ed09\", \"basic\"")}}
2755  .Check(request);
2756 
2757  const BlockHash block_hash(ParseHashV(request.params[0], "blockhash"));
2758  std::string filtertype_name = "basic";
2759  if (!request.params[1].isNull()) {
2760  filtertype_name = request.params[1].get_str();
2761  }
2762 
2763  BlockFilterType filtertype;
2764  if (!BlockFilterTypeByName(filtertype_name, filtertype)) {
2765  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown filtertype");
2766  }
2767 
2768  BlockFilterIndex *index = GetBlockFilterIndex(filtertype);
2769  if (!index) {
2771  "Index is not enabled for filtertype " +
2772  filtertype_name);
2773  }
2774 
2775  const CBlockIndex *block_index;
2776  bool block_was_connected;
2777  {
2778  LOCK(cs_main);
2779  block_index = LookupBlockIndex(block_hash);
2780  if (!block_index) {
2781  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
2782  }
2783  block_was_connected = block_index->IsValid(BlockValidity::SCRIPTS);
2784  }
2785 
2786  bool index_ready = index->BlockUntilSyncedToCurrentChain();
2787 
2788  BlockFilter filter;
2789  uint256 filter_header;
2790  if (!index->LookupFilter(block_index, filter) ||
2791  !index->LookupFilterHeader(block_index, filter_header)) {
2792  int err_code;
2793  std::string errmsg = "Filter not found.";
2794 
2795  if (!block_was_connected) {
2796  err_code = RPC_INVALID_ADDRESS_OR_KEY;
2797  errmsg += " Block was not connected to active chain.";
2798  } else if (!index_ready) {
2799  err_code = RPC_MISC_ERROR;
2800  errmsg +=
2801  " Block filters are still in the process of being indexed.";
2802  } else {
2803  err_code = RPC_INTERNAL_ERROR;
2804  errmsg +=
2805  " This error is unexpected and indicates index corruption.";
2806  }
2807 
2808  throw JSONRPCError(err_code, errmsg);
2809  }
2810 
2811  UniValue ret(UniValue::VOBJ);
2812  ret.pushKV("filter", HexStr(filter.GetEncodedFilter()));
2813  ret.pushKV("header", filter_header.GetHex());
2814  return ret;
2815 }
2816 
2822 static UniValue dumptxoutset(const Config &config,
2823  const JSONRPCRequest &request) {
2824  RPCHelpMan{
2825  "dumptxoutset",
2826  "\nWrite the serialized UTXO set to disk.\n"
2827  "Incidentally flushes the latest coinsdb (leveldb) to disk.\n",
2828  {
2830  /* default_val */ "",
2831  "path to the output file. If relative, will be prefixed by "
2832  "datadir."},
2833  },
2835  "",
2836  "",
2837  {
2838  {RPCResult::Type::NUM, "coins_written",
2839  "the number of coins written in the snapshot"},
2840  {RPCResult::Type::STR_HEX, "base_hash",
2841  "the hash of the base of the snapshot"},
2842  {RPCResult::Type::NUM, "base_height",
2843  "the height of the base of the snapshot"},
2844  {RPCResult::Type::STR, "path",
2845  "the absolute path that the snapshot was written to"},
2846  }},
2847  RPCExamples{HelpExampleCli("dumptxoutset", "utxo.dat")}}
2848  .Check(request);
2849 
2850  fs::path path = fs::absolute(request.params[0].get_str(), GetDataDir());
2851  // Write to a temporary path and then move into `path` on completion
2852  // to avoid confusion due to an interruption.
2853  fs::path temppath =
2854  fs::absolute(request.params[0].get_str() + ".incomplete", GetDataDir());
2855 
2856  if (fs::exists(path)) {
2857  throw JSONRPCError(
2859  path.string() +
2860  " already exists. If you are sure this is what you want, "
2861  "move it out of the way first");
2862  }
2863 
2864  FILE *file{fsbridge::fopen(temppath, "wb")};
2865  CAutoFile afile{file, SER_DISK, CLIENT_VERSION};
2866  std::unique_ptr<CCoinsViewCursor> pcursor;
2867  CCoinsStats stats;
2868  CBlockIndex *tip;
2869  NodeContext &node = EnsureNodeContext(request.context);
2870 
2871  {
2872  // We need to lock cs_main to ensure that the coinsdb isn't written to
2873  // between (i) flushing coins cache to disk (coinsdb), (ii) getting
2874  // stats based upon the coinsdb, and (iii) constructing a cursor to the
2875  // coinsdb for use below this block.
2876  //
2877  // Cursors returned by leveldb iterate over snapshots, so the contents
2878  // of the pcursor will not be affected by simultaneous writes during
2879  // use below this block.
2880  //
2881  // See discussion here:
2882  // https://github.com/bitcoin/bitcoin/pull/15606#discussion_r274479369
2883  //
2884  LOCK(::cs_main);
2885 
2887 
2888  if (!GetUTXOStats(&::ChainstateActive().CoinsDB(), stats,
2889  node.rpc_interruption_point)) {
2890  throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
2891  }
2892 
2893  pcursor = std::unique_ptr<CCoinsViewCursor>(
2895  tip = LookupBlockIndex(stats.hashBlock);
2896  CHECK_NONFATAL(tip);
2897  }
2898 
2899  SnapshotMetadata metadata{tip->GetBlockHash(), stats.coins_count,
2900  uint64_t(tip->GetChainTxCount())};
2901 
2902  afile << metadata;
2903 
2904  COutPoint key;
2905  Coin coin;
2906  unsigned int iter{0};
2907 
2908  while (pcursor->Valid()) {
2909  if (iter % 5000 == 0) {
2910  node.rpc_interruption_point();
2911  }
2912  ++iter;
2913  if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
2914  afile << key;
2915  afile << coin;
2916  }
2917 
2918  pcursor->Next();
2919  }
2920 
2921  afile.fclose();
2922  fs::rename(temppath, path);
2923 
2924  UniValue result(UniValue::VOBJ);
2925  result.pushKV("coins_written", stats.coins_count);
2926  result.pushKV("base_hash", tip->GetBlockHash().ToString());
2927  result.pushKV("base_height", tip->nHeight);
2928  result.pushKV("path", path.string());
2929  return result;
2930 }
2931 
2933  // clang-format off
2934  static const CRPCCommand commands[] = {
2935  // category name actor (function) argNames
2936  // ------------------- ------------------------ ---------------------- ----------
2937  { "blockchain", "getbestblockhash", getbestblockhash, {} },
2938  { "blockchain", "getblock", getblock, {"blockhash","verbosity|verbose"} },
2939  { "blockchain", "getblockchaininfo", getblockchaininfo, {} },
2940  { "blockchain", "getblockcount", getblockcount, {} },
2941  { "blockchain", "getblockhash", getblockhash, {"height"} },
2942  { "blockchain", "getblockheader", getblockheader, {"blockhash","verbose"} },
2943  { "blockchain", "getblockstats", getblockstats, {"hash_or_height","stats"} },
2944  { "blockchain", "getchaintips", getchaintips, {} },
2945  { "blockchain", "getchaintxstats", getchaintxstats, {"nblocks", "blockhash"} },
2946  { "blockchain", "getdifficulty", getdifficulty, {} },
2947  { "blockchain", "getmempoolancestors", getmempoolancestors, {"txid","verbose"} },
2948  { "blockchain", "getmempooldescendants", getmempooldescendants, {"txid","verbose"} },
2949  { "blockchain", "getmempoolentry", getmempoolentry, {"txid"} },
2950  { "blockchain", "getmempoolinfo", getmempoolinfo, {} },
2951  { "blockchain", "getrawmempool", getrawmempool, {"verbose"} },
2952  { "blockchain", "gettxout", gettxout, {"txid","n","include_mempool"} },
2953  { "blockchain", "gettxoutsetinfo", gettxoutsetinfo, {} },
2954  { "blockchain", "pruneblockchain", pruneblockchain, {"height"} },
2955  { "blockchain", "savemempool", savemempool, {} },
2956  { "blockchain", "verifychain", verifychain, {"checklevel","nblocks"} },
2957  { "blockchain", "preciousblock", preciousblock, {"blockhash"} },
2958  { "blockchain", "scantxoutset", scantxoutset, {"action", "scanobjects"} },
2959  { "blockchain", "getblockfilter", getblockfilter, {"blockhash", "filtertype"} },
2960 
2961  /* Not shown in help */
2962  { "hidden", "getfinalizedblockhash", getfinalizedblockhash, {} },
2963  { "hidden", "finalizeblock", finalizeblock, {"blockhash"} },
2964  { "hidden", "invalidateblock", invalidateblock, {"blockhash"} },
2965  { "hidden", "parkblock", parkblock, {"blockhash"} },
2966  { "hidden", "reconsiderblock", reconsiderblock, {"blockhash"} },
2967  { "hidden", "syncwithvalidationinterfacequeue", syncwithvalidationinterfacequeue, {} },
2968  { "hidden", "dumptxoutset", dumptxoutset, {"path"} },
2969  { "hidden", "unparkblock", unparkblock, {"blockhash"} },
2970  { "hidden", "waitfornewblock", waitfornewblock, {"timeout"} },
2971  { "hidden", "waitforblock", waitforblock, {"blockhash","timeout"} },
2972  { "hidden", "waitforblockheight", waitforblockheight, {"height","timeout"} },
2973  };
2974  // clang-format on
2975 
2976  for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) {
2977  t.appendCommand(commands[vcidx].name, &commands[vcidx]);
2978  }
2979 }
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:849
uint32_t GetN() const
Definition: transaction.h:44
bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats, const std::function< void()> &interruption_point)
Calculate statistics about the unspent transaction output set.
Definition: coinstats.cpp:39
uint32_t nNonce
Definition: block.h:30
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
Definition: blockindex.h:49
static UniValue scantxoutset(const Config &config, const JSONRPCRequest &request)
static UniValue getrawmempool(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:604
std::string NetworkIDString() const
Return the BIP70 network string (main, test or regtest)
Definition: chainparams.h:86
void queryHashes(std::vector< uint256 > &vtxid) const
Definition: txmempool.cpp:890
bool LookupFilter(const CBlockIndex *block_index, BlockFilter &filter_out) const
Get a single filter by block.
Display status of an in-progress BIP9 softfork.
Definition: versionbits.h:44
static UniValue getmempooldescendants(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:715
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
const util::Ref & context
Definition: request.h:42
bool InvalidateBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main
Mark a block as invalid.
bool IsCoinBase() const
Definition: coins.h:45
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
uint64_t nTransactionOutputs
Definition: coinstats.h:22
const std::string CURRENCY_UNIT
Definition: network.cpp:8
bool fPruneMode
True if we&#39;re running in -prune mode.
Definition: validation.cpp:104
static constexpr Amount zero()
Definition: amount.h:35
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &params)
Functions for disk access for blocks.
Definition: blockdb.cpp:33
const std::vector< UniValue > & getValues() const
Bitcoin RPC command dispatcher.
Definition: server.h:198
#define LogPrint(category,...)
Definition: logging.h:192
static UniValue preciousblock(const Config &config, const JSONRPCRequest &request)
int64_t GetBlockTime() const
Definition: blockindex.h:160
indexed_transaction_set::nth_index< 0 >::type::const_iterator txiter
Definition: txmempool.h:548
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:22
CScript scriptPubKey
Definition: transaction.h:144
bool ActivateBestChain(const Config &config, BlockValidationState &state, std::shared_ptr< const CBlock > pblock)
Find the best known block, and make it the tip of the block chain.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: blockindex.h:30
static UniValue getblockhash(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:821
bool get_bool() const
bool IsRPCRunning()
Query whether RPC is running.
Definition: server.cpp:358
Required arg.
A UTXO entry.
Definition: coins.h:27
static UniValue getblockcount(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:191
int nHeight
Definition: coinstats.h:19
Definition: block.h:62
bool BlockFilterTypeByName(const std::string &name, BlockFilterType &filter_type)
Find a filter type by its human-readable name.
CChain & ChainActive()
Definition: validation.cpp:78
UniValue parkblock(const Config &config, const JSONRPCRequest &request)
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE
Default for -maxmempool, maximum megabytes of mempool memory usage.
Definition: policy.h:48
ChainstateManager & EnsureChainman(const util::Ref &context)
Definition: blockchain.cpp:71
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1023
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
Definition: txmempool.cpp:508
size_t DynamicMemoryUsage() const
Definition: txmempool.cpp:1058
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: txmempool.cpp:1042
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
virtual void Next()=0
BlockStatus nStatus
Verification status of this block. See enum BlockStatus.
Definition: blockindex.h:76
Comparison function for sorting the getchaintips heads.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ChainActive().Tip() will not be pr...
Definition: validation.h:109
unsigned int nHeight
bool hasData() const
Definition: blockstatus.h:54
#define ARRAYLEN(array)
Utilities for converting data from/to strings.
Definition: strencodings.h:19
CBlockHeader GetBlockHeader() const
Definition: blockindex.h:120
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
Definition: check.h:34
int Height() const
Return the maximal height in the chain.
Definition: chain.h:210
void ForceFlushStateToDisk()
Unconditionally flush all changes to disk.
static UniValue dumptxoutset(const Config &config, const JSONRPCRequest &request)
Serialize the UTXO set to a file for loading elsewhere.
const CBlockIndex * GetFinalizedBlock() const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Return the currently finalized block index.
UniValue getfinalizedblockhash(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:225
Definition: amount.h:17
UniValue unparkblock(const Config &config, const JSONRPCRequest &request)
unsigned long size() const
Definition: txmempool.h:763
UniValue blockheaderToJSON(const CBlockIndex *tip, const CBlockIndex *blockindex)
Block header to JSON.
Definition: blockchain.cpp:111
uint64_t GetTotalTxSize() const
Definition: txmempool.h:768
BIP9Stats VersionBitsTipStatistics(const Consensus::Params &params, Consensus::DeploymentPos pos)
Get the numerical statistics for the BIP9 state for a given deployment at the current tip...
Amount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
Definition: validation.cpp:854
const TxId & GetTxId() const
Definition: transaction.h:43
uint64_t nTransactions
Definition: coinstats.h:21
const std::string & get_str() const
static constexpr Amount SATOSHI
Definition: amount.h:151
static void entryToJSON(const CTxMemPool &pool, UniValue &info, const CTxMemPoolEntry &e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
Definition: blockchain.cpp:529
static UniValue savemempool(const Config &config, const JSONRPCRequest &request)
static const Amount MAX_MONEY
No amount larger than this (in satoshi) is valid.
Definition: amount.h:165
uint64_t nDiskSize
Definition: coinstats.h:25
bool isNum() const
Definition: univalue.h:94
static UniValue getdifficulty(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:445
const UniValue & get_array() const
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
Definition: chainparams.h:47
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:196
uint32_t nTime
Definition: blockindex.h:81
double GetDifficulty(const CBlockIndex *blockindex)
Calculate the difficulty for a given block index.
Definition: blockchain.cpp:82
CCoinsViewDB & CoinsDB()
Definition: validation.h:781
ThresholdState
BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
Definition: versionbits.h:26
CTxMemPool & EnsureMemPool(const util::Ref &context)
Definition: blockchain.cpp:62
uint64_t nPruneTarget
Number of MiB of block files that we&#39;re trying to stay below.
Definition: validation.cpp:109
UniValue finalizeblock(const Config &config, const JSONRPCRequest &request)
bool appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:316
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:36
static UniValue gettxoutsetinfo(const Config &config, const JSONRPCRequest &request)
bool DumpMempool(const CTxMemPool &pool)
Dump the mempool to disk.
uint64_t nBogoSize
Definition: coinstats.h:23
static UniValue getchaintips(const Config &config, const JSONRPCRequest &request)
int threshold
Number of blocks with the version bit set required to activate the softfork.
Definition: versionbits.h:51
bool IsLoaded() const
Definition: txmempool.cpp:1286
virtual const CChainParams & GetChainParams() const =0
void RPCNotifyBlockChange(const CBlockIndex *pindex)
Callback for when block tip changed.
Definition: blockchain.cpp:246
static UniValue pruneblockchain(const Config &config, const JSONRPCRequest &request)
static int ComputeNextBlockAndDepth(const CBlockIndex *tip, const CBlockIndex *blockindex, const CBlockIndex *&next)
Definition: blockchain.cpp:100
bool isSpent(const COutPoint &outpoint) const
Definition: txmempool.cpp:405
const std::vector< CTxIn > vin
Definition: transaction.h:227
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
ThresholdState VersionBitsTipState(const Consensus::Params &params, Consensus::DeploymentPos pos)
Get the BIP9 state for a given deployment at the current tip.
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1193
CChainState & ChainstateActive()
Definition: validation.cpp:72
std::function< void()> rpc_interruption_point
Definition: context.h:48
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
Definition: txmempool.h:65
const std::vector< uint8_t > & GetEncodedFilter() const
Definition: blockfilter.h:134
Metadata describing a serialized version of a UTXO set from which an assumeutxo CChainState can be co...
Definition: utxo_snapshot.h:14
uint256 hashSerialized
Definition: coinstats.h:24
static T CalculateTruncatedMedian(std::vector< T > &scores)
virtual bool GetValue(Coin &coin) const =0
bool MoneyRange(const Amount nValue)
Definition: amount.h:166
BlockHash GetBlockHash() const
Definition: blockindex.h:133
bool IsValid() const
Definition: validation.h:116
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:68
static UniValue getblock(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:971
iterator end()
Definition: prevector.h:390
static const uint32_t MEMPOOL_HEIGHT
Fake height value used in Coins to signify they are only in the memory pool(since 0...
Definition: txmempool.h:38
BlockFilterType
Definition: blockfilter.h:88
uint64_t PruneAfterHeight() const
Definition: chainparams.h:73
Special type that is a STR with only hex chars.
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:143
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
static std::atomic< bool > g_scan_in_progress
ChainstateManager * chainman
Definition: context.h:41
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:52
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
virtual uint64_t GetMaxBlockSize() const =0
bool operator()(const CBlockIndex *a, const CBlockIndex *b) const
Definition: config.h:19
void ResetBlockFailureFlags(CBlockIndex *pindex)
Remove invalidity status from a block and its descendants.
Special string with only hex chars.
NodeContext struct containing references to chain state and connection state.
Definition: context.h:35
virtual bool Valid() const =0
int64_t count_seconds(std::chrono::seconds t)
Helper to count the seconds of a duration.
Definition: time.h:22
uint256 hashMerkleRoot
Definition: block.h:27
void RegisterBlockchainRPCCommands(CRPCTable &t)
Register block chain RPC commands.
uint32_t nNonce
Definition: blockindex.h:83
Abstract view on the open txout dataset.
Definition: coins.h:175
CFeeRate minRelayTxFee
A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) ...
Definition: validation.cpp:115
UniValue params
Definition: request.h:37
CBlockIndex * pindexBestHeader
Best header we&#39;ve seen so far (used for getheaders queries&#39; starting points).
Definition: validation.cpp:97
DeploymentPos
Definition: params.h:16
static UniValue getblockstats(const Config &config, const JSONRPCRequest &request)
An input of a transaction.
Definition: transaction.h:67
int period
Length of blocks of the BIP9 signalling period.
Definition: versionbits.h:46
#define LOCK(cs)
Definition: sync.h:230
const char * name
Definition: rest.cpp:43
std::string ToString() const
Definition: validation.h:122
uint64_t coins_count
The number of coins contained.
Definition: coinstats.h:29
bool FinalizeBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main
Finalize a block.
static std::condition_variable cond_blockchange
Definition: blockchain.cpp:52
Complete block filter struct as defined in BIP 157.
Definition: blockfilter.h:111
bool IsBlockPruned(const CBlockIndex *pblockindex)
Check whether the block associated with this index entry is pruned or not.
static std::vector< RPCResult > MempoolEntryDescription()
Definition: blockchain.cpp:464
bool UndoReadFromDisk(CBlockUndo &blockundo, const CBlockIndex *pindex)
uint256 uint256S(const char *str)
uint256 from const char *.
Definition: uint256.h:131
int64_t nPowTargetSpacing
Definition: params.h:104
RAII wrapper for VerifyDB: Verify consistency of the block and coin databases.
Definition: validation.h:532
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:760
static UniValue getbestblockhash(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:208
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:95
bool Has() const
Definition: ref.h:33
uint256 hashMerkleRoot
Definition: blockindex.h:80
std::set< txiter, CompareIteratorById > setEntries
Definition: txmempool.h:557
bool VerifyDB(const Config &config, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
General application defined errors std::exception thrown in command handling.
Definition: protocol.h:38
int64_t GetChainTxCount() const
Get the number of transaction in the chain so far.
Definition: blockindex.h:138
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
int VersionBitsTipStateSinceHeight(const Consensus::Params &params, Consensus::DeploymentPos pos)
Get the block height at which the BIP9 deployment switched into the state for the block building on t...
int count
Number of blocks with the version bit set since the beginning of the current period.
Definition: versionbits.h:60
#define WAIT_LOCK(cs, name)
Definition: sync.h:238
An output of a transaction.
Definition: transaction.h:141
uint8_t * begin()
Definition: uint256.h:76
int get_int() const
std::string ToString() const
Definition: uint256.h:74
Invalid address or key.
Definition: protocol.h:42
Parameters that influence chain consensus.
Definition: params.h:59
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:185
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
UniValue gettxout(const Config &config, const JSONRPCRequest &request)
int64_t GetBlockTime() const
Definition: block.h:59
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:138
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:1167
bool isNull() const
Definition: univalue.h:89
Special numeric to denote unix epoch time.
T & Get() const
Definition: ref.h:25
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:261
UniValue blockToJSON(const CBlock &block, const CBlockIndex *tip, const CBlockIndex *blockindex, bool txDetails)
Block description to JSON.
Definition: blockchain.cpp:145
int64_t GetMedianTimePast() const
Definition: blockindex.h:172
static UniValue getchaintxstats(const Config &config, const JSONRPCRequest &request)
Type-safe dynamic reference.
Definition: ref.h:21
virtual bool GetKey(COutPoint &key) const =0
NodeContext & EnsureNodeContext(const util::Ref &context)
Definition: blockchain.cpp:55
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:99
static UniValue getmempoolancestors(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:646
Database error.
Definition: protocol.h:48
Special type that is a NUM or [NUM,NUM].
int32_t nVersion
block header
Definition: blockindex.h:79
256-bit opaque blob.
Definition: uint256.h:120
Optional argument with default value omitted because they are implicitly clear.
bool ParkBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main
Park a block.
bool IsValid(enum BlockValidity nUpTo=BlockValidity::TRANSACTIONS) const
Check whether this block index entry is valid up to the passed validity level.
Definition: blockindex.h:195
static std::atomic< bool > g_should_abort_scan
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
std::vector< CTransactionRef > vtx
Definition: block.h:65
const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
bool PreciousBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex)
Mark a block as precious and reorganize.
static UniValue getblockfilter(const Config &config, const JSONRPCRequest &request)
const_iterator end() const
Definition: streams.h:277
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:468
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
Definition: coins.cpp:94
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:44
const_iterator begin() const
Definition: streams.h:275
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...
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
Special string to represent a floating point amount.
UniValue MempoolInfoToJSON(const CTxMemPool &pool)
Mempool information to JSON.
static UniValue waitforblock(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:309
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: blockindex.h:23
const CChainParams & Params()
Return the currently selected parameters.
Undo information for a CBlock.
Definition: undo.h:73
int RPCSerializationFlags()
Retrieves any serialization flags requested in command line argument.
Definition: server.cpp:559
static const signed int DEFAULT_CHECKBLOCKS
Definition: validation.h:110
const CTransaction & GetTx() const
Definition: txmempool.h:116
A TxId is the identifier of a transaction.
Definition: txid.h:14
uint32_t GetHeight() const
Definition: coins.h:44
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11
static UniValue getblockheader(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:847
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...
CTxOut & GetTxOut()
Definition: coins.h:48
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:479
void PruneBlockFilesManual(int nManualPruneHeight)
Prune block files up to a given height.
void UnparkBlockAndChildren(CBlockIndex *pindex)
Remove parked status from a block and its descendants.
BlockMap & BlockIndex()
Definition: validation.cpp:931
BlockHash hashBlock
Definition: coinstats.h:20
static UniValue verifychain(const Config &config, const JSONRPCRequest &request)
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out)
Get a single filter header by block.
static Mutex cs_blockchange
Definition: blockchain.cpp:51
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:168
CBlockIndex * LookupBlockIndex(const BlockHash &hash)
Definition: validation.cpp:145
std::string GetHex() const
Definition: uint256.cpp:16
static constexpr size_t PER_UTXO_OVERHEAD
std::string HexStr(const T itbegin, const T itend)
Definition: strencodings.h:132
ArgsManager gArgs
Definition: system.cpp:76
const UniValue NullUniValue
Definition: univalue.cpp:13
#define AssertLockNotHeld(cs)
Definition: sync.h:88
Scripts & signatures ok.
static int count
Definition: tests.c:35
std::string GetWarnings(bool verbose)
Format a string that describes several potential problems detected by the core.
Definition: warnings.cpp:38
int elapsed
Number of blocks elapsed since the beginning of the current period.
Definition: versionbits.h:55
iterator begin()
Definition: prevector.h:388
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
Definition: core_write.cpp:193
bool possible
False if there are not enough blocks left in this period to pass activation threshold.
Definition: versionbits.h:65
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:198
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Definition: validation.h:775
static UniValue waitfornewblock(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:255
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0)
Definition: core_write.cpp:220
CCoinsViewCursor * Cursor() const override
Get a cursor to iterate over the whole state.
Definition: txdb.cpp:183
static UniValue reconsiderblock(const Config &config, const JSONRPCRequest &request)
std::string GetHex() const
size_t size() const
Definition: univalue.h:80
Amount nTotalAmount
Definition: coinstats.h:26
static CBlockUndo GetUndoChecked(const CBlockIndex *pblockindex)
Definition: blockchain.cpp:957
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:211
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: blockindex.h:36
UniValue getblockchaininfo(const Config &config, const JSONRPCRequest &request)
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:59
Special dictionary with keys that are not literals.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:231
static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange)
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: blockindex.cpp:71
std::string GetRejectReason() const
Definition: validation.h:120
static UniValue invalidateblock(const Config &config, const JSONRPCRequest &request)
static void BIP9SoftForkDescPushBack(UniValue &softforks, const Consensus::Params &consensusParams, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void __pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:127
AssertLockHeld(g_cs_orphans)
uint64_t CalculateCurrentUsage()
BLOCK PRUNING CODE.
static CBlock GetBlockChecked(const Config &config, const CBlockIndex *pblockindex)
Definition: blockchain.cpp:938
static UniValue getmempoolinfo(const Config &config, const JSONRPCRequest &request)
std::vector< CTxUndo > vtxundo
Definition: undo.h:76
COutPoint prevout
Definition: transaction.h:69
UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose)
Mempool to JSON.
Definition: blockchain.cpp:577
static UniValue getmempoolentry(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:789
const CBlockIndex * FindFork(const CBlockIndex *pindex) const
Find the last common block between this chain and a block index entry.
Definition: chain.cpp:55
CCoinsView that brings transactions from a mempool into view.
Definition: txmempool.h:914
int32_t nVersion
Definition: block.h:25
Amount nValue
Definition: transaction.h:143
uint32_t nBits
Definition: blockindex.h:82
unsigned int nTx
Number of transactions in this block.
Definition: blockindex.h:54
BlockHash hash
Definition: blockchain.cpp:47
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
bool BlockUntilSyncedToCurrentChain() const
Blocks the current thread until the index is caught up to the current state of the block chain...
Definition: base.cpp:280
static const unsigned int DEFAULT_CHECKLEVEL
Definition: validation.h:111
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:580
static UniValue syncwithvalidationinterfacequeue(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:428
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
Definition: txmempool.h:545
const TxId GetId() const
Definition: transaction.h:261
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:21
uint32_t nBits
Definition: block.h:29
Special type to denote elision (...)
static UniValue waitforblockheight(const Config &config, const JSONRPCRequest &request)
Definition: blockchain.cpp:370
UniValue ValueFromAmount(const Amount &amount)
Definition: core_write.cpp:20
void RPCTypeCheck(const UniValue &params, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: util.cpp:25
CTxMemPool * mempool
Definition: context.h:38
Cursor for iterating over CoinsView state.
Definition: coins.h:155