/
githubmirror
/
bitcoin
Обзор
Документация
Войти
/
githubmirror
/
bitcoin
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/bitcoin-util.cpp
257 строк
8 KB
Anthony Towns
bitcoin-util: replace netmagic command with getchainparams command
17 июл 2026, 15:01
17 июл 2026, 15:01
7298281
Код
Авторство
О чём код?
// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bitcoin-build-config.h> // IWYU pragma: keep #include <arith_uint256.h> #include <chain.h> #include <chainparams.h> #include <chainparamsbase.h> #include <clientversion.h> #include <common/args.h> #include <common/license_info.h> #include <common/system.h> #include <compat/compat.h> #include <core_io.h> #include <streams.h> #include <univalue.h> #include <util/exception.h> #include <util/strencodings.h> #include <util/translation.h> #include <atomic> #include <cstdio> #include <functional> #include <memory> #include <thread> static const int CONTINUE_EXECUTION=-1; const TranslateFn G_TRANSLATION_FUN{nullptr}; static void SetupBitcoinUtilArgs(ArgsManager &argsman) { SetupHelpOptions(argsman); argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddCommand("grind", "Perform proof of work on hex header string"); argsman.AddCommand("getchainparams", "Get hardcoded parameters for the selected chain"); SetupChainParamsBaseOptions(argsman); } // This function returns either one of EXIT_ codes when it's expected to stop the process or // CONTINUE_EXECUTION when it's expected to continue further. static int AppInitUtil(ArgsManager& args, int argc, char* argv[]) { SetupBitcoinUtilArgs(args); std::string error; if (!args.ParseParameters(argc, argv, error)) { tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error); return EXIT_FAILURE; } if (HelpRequested(args) || args.GetBoolArg("-version", false)) { // First part of help message is specific to this utility std::string strUsage = CLIENT_NAME " bitcoin-util utility version " + FormatFullVersion() + "\n"; if (args.GetBoolArg("-version", false)) { strUsage += FormatParagraph(LicenseInfo()); } else { strUsage += "\n" "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" "\n" "Usage: bitcoin-util [options] [command]\n" "or: bitcoin-util [options] grind <hex-block-header>\n"; strUsage += "\n" + args.GetHelpMessage(); } tfm::format(std::cout, "%s", strUsage); if (argc < 2) { tfm::format(std::cerr, "Error: too few parameters\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } // Check for chain settings (Params() calls are only valid after this clause) try { SelectParams(args.GetChainType()); } catch (const std::exception& e) { tfm::format(std::cerr, "Error: %s\n", e.what()); return EXIT_FAILURE; } return CONTINUE_EXECUTION; } static void grind_task(uint32_t nBits, CBlockHeader header, uint32_t offset, uint32_t step, std::atomic<bool>& found, uint32_t& proposed_nonce) { arith_uint256 target; bool neg, over; target.SetCompact(nBits, &neg, &over); if (target == 0 || neg || over) return; header.nNonce = offset; uint32_t finish = std::numeric_limits<uint32_t>::max() - step; finish = finish - (finish % step) + offset; while (!found && header.nNonce < finish) { const uint32_t next = (finish - header.nNonce < 5000*step) ? finish : header.nNonce + 5000*step; do { if (UintToArith256(header.GetHash()) <= target) { if (!found.exchange(true)) { proposed_nonce = header.nNonce; } return; } header.nNonce += step; } while(header.nNonce != next); } } static int Grind(const std::vector<std::string>& args, std::string& strPrint) { if (args.size() != 1) { strPrint = "Must specify block header to grind"; return EXIT_FAILURE; } CBlockHeader header; if (!DecodeHexBlockHeader(header, args[0])) { strPrint = "Could not decode block header"; return EXIT_FAILURE; } uint32_t nBits = header.nBits; std::atomic<bool> found{false}; uint32_t proposed_nonce{}; std::vector<std::thread> threads; int n_tasks = std::max(1u, std::thread::hardware_concurrency()); threads.reserve(n_tasks); for (int i = 0; i < n_tasks; ++i) { threads.emplace_back(grind_task, nBits, header, i, n_tasks, std::ref(found), std::ref(proposed_nonce)); } for (auto& t : threads) { t.join(); } if (found) { header.nNonce = proposed_nonce; } else { strPrint = "Could not satisfy difficulty target"; return EXIT_FAILURE; } DataStream ss{}; ss << header; strPrint = HexStr(ss); return EXIT_SUCCESS; } static int GetChainParams(const std::vector<std::string>& args, std::string& strPrint) { if (!args.empty()) { strPrint = "getchainparams does not take arguments"; return EXIT_FAILURE; } const auto& params = Params(); const auto& consensus = params.GetConsensus(); UniValue result{UniValue::VOBJ}; result.pushKV("chain", params.GetChainTypeString()); result.pushKV("test_chain", params.IsTestChain()); result.pushKV("genesis", HexStr(consensus.hashGenesisBlock)); result.pushKV("subsidy_halving_interval", consensus.nSubsidyHalvingInterval); if (consensus.signet_blocks) { UniValue signet{UniValue::VOBJ}; signet.pushKV("challenge", HexStr(consensus.signet_challenge)); result.pushKV("signet", signet); } { UniValue pow{UniValue::VOBJ}; pow.pushKV("limit", consensus.powLimit.ToString()); if (!consensus.fPowNoRetargeting) { pow.pushKV("target_spacing", TicksSeconds(consensus.PowTargetSpacing())); pow.pushKV("difficulty_retarget_interval", consensus.DifficultyAdjustmentInterval()); std::string mindiff_blocks = (consensus.fPowAllowMinDifficultyBlocks ? (consensus.enforce_BIP94 ? "bip94" : "yes") : "no"); pow.pushKV("mindiff_blocks", mindiff_blocks); } result.pushKV("pow", pow); } { UniValue net{UniValue::VOBJ}; net.pushKV("default_port", params.GetDefaultPort()); net.pushKV("magic", HexStr(params.MessageStart())); UniValue dns{UniValue::VARR}; for (const auto& seed : params.DNSSeeds()) { dns.push_back(seed); } net.pushKV("dns_seeds", dns); result.pushKV("net", net); } { UniValue addr{UniValue::VOBJ}; addr.pushKV("bech32_hrp", params.Bech32HRP()); result.pushKV("addresses", addr); } strPrint = result.write(/*prettyIndent=*/2); return EXIT_SUCCESS; } MAIN_FUNCTION { ArgsManager& args = gArgs; SetupEnvironment(); try { int ret = AppInitUtil(args, argc, argv); if (ret != CONTINUE_EXECUTION) { return ret; } } catch (const std::exception& e) { PrintExceptionContinue(&e, "AppInitUtil()"); return EXIT_FAILURE; } catch (...) { PrintExceptionContinue(nullptr, "AppInitUtil()"); return EXIT_FAILURE; } const auto cmd = args.GetCommand(); if (!cmd) { tfm::format(std::cerr, "Error: must specify a command\n"); return EXIT_FAILURE; } int ret = EXIT_FAILURE; std::string strPrint; try { if (cmd->command == "grind") { ret = Grind(cmd->args, strPrint); } else if (cmd->command == "getchainparams") { ret = GetChainParams(cmd->args, strPrint); } else { assert(false); // unknown command should be caught earlier } } catch (const std::exception& e) { strPrint = std::string("error: ") + e.what(); } catch (...) { strPrint = "unknown error"; } if (strPrint != "") { tfm::format(ret == 0 ? std::cout : std::cerr, "%s\n", strPrint); } return ret; }