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.
1// Copyright (c) 2009-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <bitcoin-build-config.h> // IWYU pragma: keep7#include <arith_uint256.h>8#include <chain.h>9#include <chainparams.h>10#include <chainparamsbase.h>11#include <clientversion.h>12#include <common/args.h>13#include <common/license_info.h>14#include <common/system.h>15#include <compat/compat.h>16#include <core_io.h>17#include <crypto/sha256.h>18#include <streams.h>19#include <univalue.h>20#include <util/exception.h>21#include <util/strencodings.h>22#include <util/translation.h>24#include <atomic>25#include <cstdio>26#include <functional>27#include <memory>28#include <thread>30static const int CONTINUE_EXECUTION=-1;32const TranslateFn G_TRANSLATION_FUN{nullptr};34static void SetupBitcoinUtilArgs(ArgsManager &argsman)35{36SetupHelpOptions(argsman);38argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);40argsman.AddCommand("grind", "Perform proof of work on hex header string");41argsman.AddCommand("getchainparams", "Get hardcoded parameters for the selected chain");43SetupChainParamsBaseOptions(argsman);44}46// This function returns either one of EXIT_ codes when it's expected to stop the process or47// CONTINUE_EXECUTION when it's expected to continue further.48static int AppInitUtil(ArgsManager& args, int argc, char* argv[])49{50SetupBitcoinUtilArgs(args);51std::string error;52if (!args.ParseParameters(argc, argv, error)) {53tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);54return EXIT_FAILURE;55}57if (HelpRequested(args) || args.GetBoolArg("-version", false)) {58// First part of help message is specific to this utility59std::string strUsage = CLIENT_NAME " bitcoin-util utility version " + FormatFullVersion() + "\n";61if (args.GetBoolArg("-version", false)) {62strUsage += FormatParagraph(LicenseInfo());63} else {64strUsage += "\n"65"The bitcoin-util tool provides bitcoin related functionality that does not rely on the ability to access a running node. Available [commands] are listed below.\n"66"\n"67"Usage: bitcoin-util [options] [command]\n"68"or: bitcoin-util [options] grind <hex-block-header>\n";69strUsage += "\n" + args.GetHelpMessage();70}72tfm::format(std::cout, "%s", strUsage);74if (argc < 2) {75tfm::format(std::cerr, "Error: too few parameters\n");76return EXIT_FAILURE;77}78return EXIT_SUCCESS;79}81// Check for chain settings (Params() calls are only valid after this clause)82try {83SelectParams(args.GetChainType());84} catch (const std::exception& e) {85tfm::format(std::cerr, "Error: %s\n", e.what());86return EXIT_FAILURE;87}89return CONTINUE_EXECUTION;90}92static void grind_task(uint32_t nBits, CBlockHeader header, uint32_t offset, uint32_t step, std::atomic<bool>& found, uint32_t& proposed_nonce)93{94arith_uint256 target;95bool neg, over;96target.SetCompact(nBits, &neg, &over);97if (target == 0 || neg || over) return;98header.nNonce = offset;100uint32_t finish = std::numeric_limits<uint32_t>::max() - step;101finish = finish - (finish % step) + offset;103while (!found && header.nNonce < finish) {104const uint32_t next = (finish - header.nNonce < 5000*step) ? finish : header.nNonce + 5000*step;105do {106if (UintToArith256(header.GetHash()) <= target) {107if (!found.exchange(true)) {108proposed_nonce = header.nNonce;109}110return;111}112header.nNonce += step;113} while(header.nNonce != next);114}115}117static int Grind(const std::vector<std::string>& args, std::string& strPrint)118{119if (args.size() != 1) {120strPrint = "Must specify block header to grind";121return EXIT_FAILURE;122}124CBlockHeader header;125if (!DecodeHexBlockHeader(header, args[0])) {126strPrint = "Could not decode block header";127return EXIT_FAILURE;128}130uint32_t nBits = header.nBits;131std::atomic<bool> found{false};132uint32_t proposed_nonce{};134std::vector<std::thread> threads;135int n_tasks = std::max(1u, std::thread::hardware_concurrency());136threads.reserve(n_tasks);137for (int i = 0; i < n_tasks; ++i) {138threads.emplace_back(grind_task, nBits, header, i, n_tasks, std::ref(found), std::ref(proposed_nonce));139}140for (auto& t : threads) {141t.join();142}143if (found) {144header.nNonce = proposed_nonce;145} else {146strPrint = "Could not satisfy difficulty target";147return EXIT_FAILURE;148}150DataStream ss{};151ss << header;152strPrint = HexStr(ss);153return EXIT_SUCCESS;154}156static int GetChainParams(const std::vector<std::string>& args, std::string& strPrint)157{158if (!args.empty()) {159strPrint = "getchainparams does not take arguments";160return EXIT_FAILURE;161}163const auto& params = Params();164const auto& consensus = params.GetConsensus();166UniValue result{UniValue::VOBJ};167result.pushKV("chain", params.GetChainTypeString());168result.pushKV("test_chain", params.IsTestChain());169result.pushKV("genesis", consensus.hashGenesisBlock.GetHex());170result.pushKV("subsidy_halving_interval", consensus.nSubsidyHalvingInterval);172if (consensus.signet_blocks) {173UniValue signet{UniValue::VOBJ};174signet.pushKV("challenge", HexStr(consensus.signet_challenge));175result.pushKV("signet", signet);176}178{179UniValue pow{UniValue::VOBJ};180pow.pushKV("limit", consensus.powLimit.ToString());181if (!consensus.fPowNoRetargeting) {182pow.pushKV("target_spacing", TicksSeconds(consensus.PowTargetSpacing()));183pow.pushKV("difficulty_retarget_interval", consensus.DifficultyAdjustmentInterval());184std::string mindiff_blocks = (consensus.fPowAllowMinDifficultyBlocks ?185(consensus.enforce_BIP94 ? "bip94" : "yes") : "no");186pow.pushKV("mindiff_blocks", mindiff_blocks);187}188result.pushKV("pow", pow);189}191{192UniValue net{UniValue::VOBJ};193net.pushKV("default_port", params.GetDefaultPort());194net.pushKV("magic", HexStr(params.MessageStart()));195UniValue dns{UniValue::VARR};196for (const auto& seed : params.DNSSeeds()) {197dns.push_back(seed);198}199net.pushKV("dns_seeds", dns);200result.pushKV("net", net);201}203{204UniValue addr{UniValue::VOBJ};205addr.pushKV("bech32_hrp", params.Bech32HRP());206result.pushKV("addresses", addr);207}209strPrint = result.write(/*prettyIndent=*/2);210return EXIT_SUCCESS;211}213MAIN_FUNCTION214{215ArgsManager& args = gArgs;216SetupEnvironment();217SHA256AutoDetect();219try {220int ret = AppInitUtil(args, argc, argv);221if (ret != CONTINUE_EXECUTION) {222return ret;223}224} catch (const std::exception& e) {225PrintExceptionContinue(&e, "AppInitUtil()");226return EXIT_FAILURE;227} catch (...) {228PrintExceptionContinue(nullptr, "AppInitUtil()");229return EXIT_FAILURE;230}232const auto cmd = args.GetCommand();233if (!cmd) {234tfm::format(std::cerr, "Error: must specify a command\n");235return EXIT_FAILURE;236}238int ret = EXIT_FAILURE;239std::string strPrint;240try {241if (cmd->command == "grind") {242ret = Grind(cmd->args, strPrint);243} else if (cmd->command == "getchainparams") {244ret = GetChainParams(cmd->args, strPrint);245} else {246assert(false); // unknown command should be caught earlier247}248} catch (const std::exception& e) {249strPrint = std::string("error: ") + e.what();250} catch (...) {
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.