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