Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1251[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1252{1253NodeContext& node = EnsureAnyNodeContext(request.context);1254ChainstateManager& chainman = EnsureChainman(node);1255LOCK(cs_main);1257UniValue ret(UniValue::VOBJ);1259auto hash{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};1260COutPoint out{hash, request.params[1].getInt<uint32_t>()};1261bool fMempool = true;1262if (!request.params[2].isNull())1263fMempool = request.params[2].get_bool();1265Chainstate& active_chainstate = chainman.ActiveChainstate();1266CCoinsViewCache* coins_view = &active_chainstate.CoinsTip();1268std::optional<Coin> coin;1269if (fMempool) {1270const CTxMemPool& mempool = EnsureMemPool(node);1271LOCK(mempool.cs);1272CCoinsViewMemPool view(coins_view, mempool);1273if (!mempool.isSpent(out)) coin = view.GetCoin(out);1274} else {1275coin = coins_view->GetCoin(out);1276}1277if (!coin) return UniValue::VNULL;1279const CBlockIndex* pindex = active_chainstate.m_blockman.LookupBlockIndex(coins_view->GetBestBlock());1280ret.pushKV("bestblock", pindex->GetBlockHash().GetHex());1281if (coin->nHeight == MEMPOOL_HEIGHT) {1282ret.pushKV("confirmations", 0);1283} else {1284ret.pushKV("confirmations", pindex->nHeight - coin->nHeight + 1);1285}1286ret.pushKV("value", ValueFromAmount(coin->out.nValue));1287UniValue o(UniValue::VOBJ);1288ScriptToUniv(coin->out.scriptPubKey, /*out=*/o, /*include_hex=*/true, /*include_address=*/true);1289ret.pushKV("scriptPubKey", std::move(o));1290ret.pushKV("coinbase", coin->IsCoinBase());1292return ret;1293},1294};1295}1297static RPCMethod verifychain()1298{1299return RPCMethod{1300"verifychain",1301"Verifies blockchain database.\n",1302{1303{"checklevel", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%d, range=0-4", DEFAULT_CHECKLEVEL)},1304strprintf("How thorough the block verification is:\n%s", MakeUnorderedList(CHECKLEVEL_DOC))},1305{"nblocks", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%d, 0=all", DEFAULT_CHECKBLOCKS)}, "The number of blocks to check."},1306},1307RPCResult{1308RPCResult::Type::BOOL, "", "Verification finished successfully. If false, check debug log for reason."},1309RPCExamples{1310HelpExampleCli("verifychain", "")1311+ HelpExampleRpc("verifychain", "")1312},1313[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1314{1315const int check_level{request.params[0].isNull() ? DEFAULT_CHECKLEVEL : request.params[0].getInt<int>()};1316const int check_depth{request.params[1].isNull() ? DEFAULT_CHECKBLOCKS : request.params[1].getInt<int>()};1318ChainstateManager& chainman = EnsureAnyChainman(request.context);1319LOCK(cs_main);1321Chainstate& active_chainstate = chainman.ActiveChainstate();1322return CVerifyDB(chainman.GetNotifications()).VerifyDB(1323active_chainstate, chainman.GetParams().GetConsensus(), active_chainstate.CoinsTip(), check_level, check_depth) == VerifyDBResult::SUCCESS;1324},1325};1326}1328static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::BuriedDeployment dep)1329{1330// For buried deployments.1332if (!DeploymentEnabled(chainman, dep)) return;1334UniValue rv(UniValue::VOBJ);1335rv.pushKV("type", "buried");1336// getdeploymentinfo reports the softfork as active from when the chain height is1337// one below the activation height1338rv.pushKV("active", DeploymentActiveAfter(blockindex, chainman, dep));1339rv.pushKV("height", chainman.GetConsensus().DeploymentHeight(dep));1340softforks.pushKV(DeploymentName(dep), std::move(rv));1341}1343static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id)1344{1345// For BIP9 deployments.1346if (!DeploymentEnabled(chainman, id)) return;1347if (blockindex == nullptr) return;1349UniValue bip9(UniValue::VOBJ);1350BIP9Info info{chainman.m_versionbitscache.Info(*blockindex, chainman.GetConsensus(), id)};1351const auto& depparams{chainman.GetConsensus().vDeployments[id]};1353// BIP9 parameters1354if (info.stats.has_value()) {1355bip9.pushKV("bit", depparams.bit);1356}1357bip9.pushKV("start_time", depparams.nStartTime);1358bip9.pushKV("timeout", depparams.nTimeout);1359bip9.pushKV("min_activation_height", depparams.min_activation_height);1361// BIP9 status1362bip9.pushKV("status", info.current_state);1363bip9.pushKV("since", info.since);1364bip9.pushKV("status_next", info.next_state);1366// BIP9 signalling status, if applicable1367if (info.stats.has_value()) {1368UniValue statsUV(UniValue::VOBJ);1369statsUV.pushKV("period", info.stats->period);1370statsUV.pushKV("elapsed", info.stats->elapsed);1371statsUV.pushKV("count", info.stats->count);1372if (info.stats->threshold > 0 || info.stats->possible) {1373statsUV.pushKV("threshold", info.stats->threshold);1374statsUV.pushKV("possible", info.stats->possible);1375}1376bip9.pushKV("statistics", std::move(statsUV));1378std::string sig;1379sig.reserve(info.signalling_blocks.size());1380for (const bool s : info.signalling_blocks) {1381sig.push_back(s ? '#' : '-');1382}1383bip9.pushKV("signalling", sig);1384}1386UniValue rv(UniValue::VOBJ);1387rv.pushKV("type", "bip9");1388bool is_active = false;1389if (info.active_since.has_value()) {1390rv.pushKV("height", *info.active_since);1391is_active = (*info.active_since <= blockindex->nHeight + 1);1392}1393rv.pushKV("active", is_active);1394rv.pushKV("bip9", bip9);1395softforks.pushKV(DeploymentName(id), std::move(rv));1396}1398// used by rest.cpp:rest_chaininfo, so cannot be static1399RPCMethod getblockchaininfo()1400{1401return RPCMethod{"getblockchaininfo",1402"Returns an object containing various state info regarding blockchain processing.\n",1403{},1404RPCResult{1405RPCResult::Type::OBJ, "", "",1406{1407{RPCResult::Type::STR, "chain", "current network name (" LIST_CHAIN_NAMES ")"},1408{RPCResult::Type::NUM, "blocks", "the height of the most-work fully-validated chain. The genesis block has height 0"},1409{RPCResult::Type::NUM, "headers", "the current number of headers we have validated"},1410{RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block"},1411{RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},1412{RPCResult::Type::STR_HEX, "target", "the difficulty target"},1413{RPCResult::Type::NUM, "difficulty", "the current difficulty"},1414{RPCResult::Type::NUM_TIME, "time", "the block time expressed in " + UNIX_EPOCH_TIME},1415{RPCResult::Type::NUM_TIME, "mediantime", "the median block time expressed in " + UNIX_EPOCH_TIME},1416{RPCResult::Type::NUM, "verificationprogress", "estimate of verification progress [0..1]"},1417{RPCResult::Type::BOOL, "initialblockdownload", "(debug information) estimate of whether this node is in Initial Block Download mode"},1418{RPCResult::Type::OBJ, "backgroundvalidation", /*optional=*/true, "state info regarding background validation process",1419{1420{RPCResult::Type::NUM, "snapshotheight", "the height of the snapshot block. Background validation verifies the chain from genesis up to this height"},1421{RPCResult::Type::NUM, "blocks", "the height of the most-work background fully-validated chain. The genesis block has height 0"},1422{RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block validated in the background"},1423{RPCResult::Type::NUM_TIME, "mediantime", "the median block time expressed in " + UNIX_EPOCH_TIME},1424{RPCResult::Type::NUM, "verificationprogress", "estimate of background verification progress [0..1]"},1425{RPCResult::Type::STR_HEX, "chainwork", "total amount of work in background validated chain, in hexadecimal"},1426}},1427{RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"},1428{RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"},1429{RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"},1430{RPCResult::Type::NUM, "pruneheight", /*optional=*/true, "the first block unpruned, all previous blocks were pruned (only present if pruning is enabled)"},1431{RPCResult::Type::BOOL, "automatic_pruning", /*optional=*/true, "whether automatic pruning is enabled (only present if pruning is enabled)"},1432{RPCResult::Type::NUM, "prune_target_size", /*optional=*/true, "the target size used by pruning (only present if automatic pruning is enabled)"},1433{RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "the block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)"},1434(IsDeprecatedRPCEnabled("warnings") ?1435RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} :1436RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)",1437{1438{RPCResult::Type::STR, "", "warning"},1439}1440}1441),1442}},1443RPCExamples{1444HelpExampleCli("getblockchaininfo", "")1445+ HelpExampleRpc("getblockchaininfo", "")1446},1447[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1448{1449ChainstateManager& chainman = EnsureAnyChainman(request.context);1450LOCK(cs_main);1451Chainstate& active_chainstate = chainman.ActiveChainstate();1453const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())};1454const int height{tip.nHeight};1455UniValue obj(UniValue::VOBJ);1456obj.pushKV("chain", chainman.GetParams().GetChainTypeString());1457obj.pushKV("blocks", height);1458obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);1459obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());1460obj.pushKV("bits", strprintf("%08x", tip.nBits));1461obj.pushKV("target", GetTarget(tip, chainman.GetConsensus().powLimit).GetHex());1462obj.pushKV("difficulty", GetDifficulty(tip));1463obj.pushKV("time", tip.GetBlockTime());1464obj.pushKV("mediantime", tip.GetMedianTimePast());1465obj.pushKV("verificationprogress", chainman.GuessVerificationProgress(&tip));1466obj.pushKV("initialblockdownload", chainman.IsInitialBlockDownload());1467auto historical_blocks{chainman.GetHistoricalBlockRange()};1468if (historical_blocks) {1469UniValue background_validation(UniValue::VOBJ);1470const CBlockIndex& btip{*CHECK_NONFATAL(historical_blocks->first)};1471const CBlockIndex& btarget{*CHECK_NONFATAL(historical_blocks->second)};1472background_validation.pushKV("snapshotheight", btarget.nHeight);1473background_validation.pushKV("blocks", btip.nHeight);1474background_validation.pushKV("bestblockhash", btip.GetBlockHash().GetHex());1475background_validation.pushKV("mediantime", btip.GetMedianTimePast());1476background_validation.pushKV("chainwork", btip.nChainWork.GetHex());1477background_validation.pushKV("verificationprogress", chainman.GetBackgroundVerificationProgress(btip));1478obj.pushKV("backgroundvalidation", std::move(background_validation));1479}1480obj.pushKV("chainwork", tip.nChainWork.GetHex());1481obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());1482obj.pushKV("pruned", chainman.m_blockman.IsPruneMode());1483if (chainman.m_blockman.IsPruneMode()) {1484const auto prune_height{GetPruneHeight(chainman.m_blockman, active_chainstate.m_chain)};1485obj.pushKV("pruneheight", prune_height ? prune_height.value() + 1 : 0);1487const bool automatic_pruning{chainman.m_blockman.GetPruneTarget() != BlockManager::PRUNE_TARGET_MANUAL};1488obj.pushKV("automatic_pruning", automatic_pruning);1489if (automatic_pruning) {1490obj.pushKV("prune_target_size", chainman.m_blockman.GetPruneTarget());1491}1492}1493if (chainman.GetParams().GetChainType() == ChainType::SIGNET) {1494const std::vector<uint8_t>& signet_challenge =1495chainman.GetParams().GetConsensus().signet_challenge;1496obj.pushKV("signet_challenge", HexStr(signet_challenge));1497}1499NodeContext& node = EnsureAnyNodeContext(request.context);1500obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings")));