From 7298281ba8dfb58e07121c74e64f07861ec21f5c Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 15 Jul 2026 08:07:43 +1000 Subject: [PATCH] bitcoin-util: replace netmagic command with getchainparams command Co-Authored-By: ekzyis --- doc/release-notes-35610.md | 4 +- src/CMakeLists.txt | 1 + src/bitcoin-util.cpp | 59 +++++++++++++++++-- .../data/util/bitcoin-util-test.json | 42 ++++++------- .../data/util/getchainparams-mainnet.json | 28 +++++++++ .../data/util/getchainparams-regtest.json | 19 ++++++ .../util/getchainparams-signet-custom.json | 24 ++++++++ .../data/util/getchainparams-signet.json | 26 ++++++++ .../data/util/getchainparams-testnet.json | 26 ++++++++ .../data/util/getchainparams-testnet4.json | 23 ++++++++ .../functional/data/util/netmagic-mainnet.hex | 1 - .../functional/data/util/netmagic-regtest.hex | 1 - .../data/util/netmagic-signet-custom.hex | 1 - test/functional/data/util/netmagic-signet.hex | 1 - .../functional/data/util/netmagic-testnet.hex | 1 - .../data/util/netmagic-testnet4.hex | 1 - 16 files changed, 223 insertions(+), 35 deletions(-) create mode 100644 test/functional/data/util/getchainparams-mainnet.json create mode 100644 test/functional/data/util/getchainparams-regtest.json create mode 100644 test/functional/data/util/getchainparams-signet-custom.json create mode 100644 test/functional/data/util/getchainparams-signet.json create mode 100644 test/functional/data/util/getchainparams-testnet.json create mode 100644 test/functional/data/util/getchainparams-testnet4.json delete mode 100644 test/functional/data/util/netmagic-mainnet.hex delete mode 100644 test/functional/data/util/netmagic-regtest.hex delete mode 100644 test/functional/data/util/netmagic-signet-custom.hex delete mode 100644 test/functional/data/util/netmagic-signet.hex delete mode 100644 test/functional/data/util/netmagic-testnet.hex delete mode 100644 test/functional/data/util/netmagic-testnet4.hex diff --git a/doc/release-notes-35610.md b/doc/release-notes-35610.md index 8e0dd2087a8..1f80677e8ce 100644 --- a/doc/release-notes-35610.md +++ b/doc/release-notes-35610.md @@ -1,6 +1,6 @@ Tools and Utilities ------------------- -- A new `bitcoin-util netmagic` command returns the network magic of the - selected chain. +- A new `bitcoin-util getchainparams` command returns hardcoded details + about the selected chain. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 47266dcf5cd..2b6840bbc39 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -388,6 +388,7 @@ if(BUILD_UTIL) core_interface bitcoin_common bitcoin_util + univalue ) install_binary_component(bitcoin-util HAS_MANPAGE) endif() diff --git a/src/bitcoin-util.cpp b/src/bitcoin-util.cpp index f17c7a0dd17..7e774685537 100644 --- a/src/bitcoin-util.cpp +++ b/src/bitcoin-util.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,7 @@ static void SetupBitcoinUtilArgs(ArgsManager &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("netmagic", "Get the network magic bytes of the selected chain"); + argsman.AddCommand("getchainparams", "Get hardcoded parameters for the selected chain"); SetupChainParamsBaseOptions(argsman); } @@ -151,14 +152,60 @@ static int Grind(const std::vector& args, std::string& strPrint) return EXIT_SUCCESS; } -static int NetMagic(const std::vector& args, std::string& strPrint) +static int GetChainParams(const std::vector& args, std::string& strPrint) { if (!args.empty()) { - strPrint = "netmagic does not take arguments"; + strPrint = "getchainparams does not take arguments"; return EXIT_FAILURE; } - strPrint = HexStr(Params().MessageStart()); + 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; } @@ -191,8 +238,8 @@ MAIN_FUNCTION try { if (cmd->command == "grind") { ret = Grind(cmd->args, strPrint); - } else if (cmd->command == "netmagic") { - ret = NetMagic(cmd->args, strPrint); + } else if (cmd->command == "getchainparams") { + ret = GetChainParams(cmd->args, strPrint); } else { assert(false); // unknown command should be caught earlier } diff --git a/test/functional/data/util/bitcoin-util-test.json b/test/functional/data/util/bitcoin-util-test.json index 9c37a4e531a..2aaffff4b5c 100644 --- a/test/functional/data/util/bitcoin-util-test.json +++ b/test/functional/data/util/bitcoin-util-test.json @@ -31,52 +31,52 @@ }, { "exec": "./bitcoin-util", - "args": ["netmagic"], + "args": ["getchainparams"], "return_code": 0, - "output_cmp": "netmagic-mainnet.hex", - "description": "netmagic returns mainnet magic bytes" + "output_cmp": "getchainparams-mainnet.json", + "description": "getchainparams returns mainnet info" }, { "exec": "./bitcoin-util", - "args": ["-regtest", "netmagic"], + "args": ["-regtest", "getchainparams"], "return_code": 0, - "output_cmp": "netmagic-regtest.hex", - "description": "netmagic returns regtest magic bytes" + "output_cmp": "getchainparams-regtest.json", + "description": "getchainparams returns regtest info" }, { "exec": "./bitcoin-util", - "args": ["-testnet", "netmagic"], + "args": ["-testnet", "getchainparams"], "return_code": 0, - "output_cmp": "netmagic-testnet.hex", - "description": "netmagic returns testnet magic bytes" + "output_cmp": "getchainparams-testnet.json", + "description": "getchainparams returns testnet info" }, { "exec": "./bitcoin-util", - "args": ["-testnet4", "netmagic"], + "args": ["-testnet4", "getchainparams"], "return_code": 0, - "output_cmp": "netmagic-testnet4.hex", - "description": "netmagic returns testnet4 magic bytes" + "output_cmp": "getchainparams-testnet4.json", + "description": "getchainparams returns testnet4 info" }, { "exec": "./bitcoin-util", - "args": ["-signet", "netmagic"], + "args": ["-signet", "getchainparams"], "return_code": 0, - "output_cmp": "netmagic-signet.hex", - "description": "netmagic returns signet magic bytes" + "output_cmp": "getchainparams-signet.json", + "description": "getchainparams returns signet info" }, { "exec": "./bitcoin-util", - "args": ["-signet", "-signetchallenge=512102f7561d208dd9ae99bf497273e16f389bdbd6c4742ddb8e6b216e64fa2928ad8f51ae", "netmagic"], + "args": ["-signet", "-signetchallenge=512102f7561d208dd9ae99bf497273e16f389bdbd6c4742ddb8e6b216e64fa2928ad8f51ae", "getchainparams"], "return_code": 0, - "output_cmp": "netmagic-signet-custom.hex", - "description": "netmagic returns custom signet magic bytes" + "output_cmp": "getchainparams-signet-custom.json", + "description": "getchainparams returns custom signet info" }, { "exec": "./bitcoin-util", - "args": ["netmagic", "extra_arg"], + "args": ["getchainparams", "extra_arg"], "return_code": 1, - "error_txt": "netmagic does not take arguments", - "description": "netmagic rejects extra arguments" + "error_txt": "getchainparams does not take arguments", + "description": "getchainparams rejects extra arguments" }, { "exec": "./bitcoin-tx", "args": ["-create", "nversion=1"], diff --git a/test/functional/data/util/getchainparams-mainnet.json b/test/functional/data/util/getchainparams-mainnet.json new file mode 100644 index 00000000000..c0e0402cbbf --- /dev/null +++ b/test/functional/data/util/getchainparams-mainnet.json @@ -0,0 +1,28 @@ +{ + "chain": "main", + "test_chain": false, + "genesis": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + "subsidy_halving_interval": 210000, + "pow": { + "limit": "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "target_spacing": 600, + "difficulty_retarget_interval": 2016, + "mindiff_blocks": "no" + }, + "net": { + "default_port": 8333, + "magic": "f9beb4d9", + "dns_seeds": [ + "dnsseed.bluematt.me.", + "seed.bitcoin.jonasschnelli.ch.", + "seed.btc.petertodd.net.", + "seed.bitcoin.sprovoost.nl.", + "dnsseed.emzy.de.", + "seed.bitcoin.wiz.biz.", + "seed.mainnet.achownodes.xyz." + ] + }, + "addresses": { + "bech32_hrp": "bc" + } +} diff --git a/test/functional/data/util/getchainparams-regtest.json b/test/functional/data/util/getchainparams-regtest.json new file mode 100644 index 00000000000..7a3191b7b33 --- /dev/null +++ b/test/functional/data/util/getchainparams-regtest.json @@ -0,0 +1,19 @@ +{ + "chain": "regtest", + "test_chain": true, + "genesis": "06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f", + "subsidy_halving_interval": 150, + "pow": { + "limit": "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + }, + "net": { + "default_port": 18444, + "magic": "fabfb5da", + "dns_seeds": [ + "dummySeed.invalid." + ] + }, + "addresses": { + "bech32_hrp": "bcrt" + } +} diff --git a/test/functional/data/util/getchainparams-signet-custom.json b/test/functional/data/util/getchainparams-signet-custom.json new file mode 100644 index 00000000000..4f5d5287038 --- /dev/null +++ b/test/functional/data/util/getchainparams-signet-custom.json @@ -0,0 +1,24 @@ +{ + "chain": "signet", + "test_chain": true, + "genesis": "f61eee3b63a380a477a063af32b2bbc97c9ff9f01f2c4225e973988108000000", + "subsidy_halving_interval": 210000, + "signet": { + "challenge": "512102f7561d208dd9ae99bf497273e16f389bdbd6c4742ddb8e6b216e64fa2928ad8f51ae" + }, + "pow": { + "limit": "00000377ae000000000000000000000000000000000000000000000000000000", + "target_spacing": 600, + "difficulty_retarget_interval": 2016, + "mindiff_blocks": "no" + }, + "net": { + "default_port": 38333, + "magic": "a5df2dcb", + "dns_seeds": [ + ] + }, + "addresses": { + "bech32_hrp": "tb" + } +} diff --git a/test/functional/data/util/getchainparams-signet.json b/test/functional/data/util/getchainparams-signet.json new file mode 100644 index 00000000000..91905976bc5 --- /dev/null +++ b/test/functional/data/util/getchainparams-signet.json @@ -0,0 +1,26 @@ +{ + "chain": "signet", + "test_chain": true, + "genesis": "f61eee3b63a380a477a063af32b2bbc97c9ff9f01f2c4225e973988108000000", + "subsidy_halving_interval": 210000, + "signet": { + "challenge": "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae" + }, + "pow": { + "limit": "00000377ae000000000000000000000000000000000000000000000000000000", + "target_spacing": 600, + "difficulty_retarget_interval": 2016, + "mindiff_blocks": "no" + }, + "net": { + "default_port": 38333, + "magic": "0a03cf40", + "dns_seeds": [ + "seed.signet.bitcoin.sprovoost.nl.", + "seed.signet.achownodes.xyz." + ] + }, + "addresses": { + "bech32_hrp": "tb" + } +} diff --git a/test/functional/data/util/getchainparams-testnet.json b/test/functional/data/util/getchainparams-testnet.json new file mode 100644 index 00000000000..b0b8a4ea07e --- /dev/null +++ b/test/functional/data/util/getchainparams-testnet.json @@ -0,0 +1,26 @@ +{ + "chain": "test", + "test_chain": true, + "genesis": "43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000", + "subsidy_halving_interval": 210000, + "pow": { + "limit": "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "target_spacing": 600, + "difficulty_retarget_interval": 2016, + "mindiff_blocks": "yes" + }, + "net": { + "default_port": 18333, + "magic": "0b110907", + "dns_seeds": [ + "testnet-seed.bitcoin.jonasschnelli.ch.", + "seed.tbtc.petertodd.net.", + "seed.testnet.bitcoin.sprovoost.nl.", + "testnet-seed.bluematt.me.", + "seed.testnet.achownodes.xyz." + ] + }, + "addresses": { + "bech32_hrp": "tb" + } +} diff --git a/test/functional/data/util/getchainparams-testnet4.json b/test/functional/data/util/getchainparams-testnet4.json new file mode 100644 index 00000000000..a59dd1064a8 --- /dev/null +++ b/test/functional/data/util/getchainparams-testnet4.json @@ -0,0 +1,23 @@ +{ + "chain": "testnet4", + "test_chain": true, + "genesis": "43f08bdab050e35b567c864b91f47f50ae725ae2de53bcfbbaf284da00000000", + "subsidy_halving_interval": 210000, + "pow": { + "limit": "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "target_spacing": 600, + "difficulty_retarget_interval": 2016, + "mindiff_blocks": "bip94" + }, + "net": { + "default_port": 48333, + "magic": "1c163f28", + "dns_seeds": [ + "seed.testnet4.bitcoin.sprovoost.nl.", + "seed.testnet4.wiz.biz." + ] + }, + "addresses": { + "bech32_hrp": "tb" + } +} diff --git a/test/functional/data/util/netmagic-mainnet.hex b/test/functional/data/util/netmagic-mainnet.hex deleted file mode 100644 index 94b2c3359e6..00000000000 --- a/test/functional/data/util/netmagic-mainnet.hex +++ /dev/null @@ -1 +0,0 @@ -f9beb4d9 diff --git a/test/functional/data/util/netmagic-regtest.hex b/test/functional/data/util/netmagic-regtest.hex deleted file mode 100644 index e2a9cb27319..00000000000 --- a/test/functional/data/util/netmagic-regtest.hex +++ /dev/null @@ -1 +0,0 @@ -fabfb5da diff --git a/test/functional/data/util/netmagic-signet-custom.hex b/test/functional/data/util/netmagic-signet-custom.hex deleted file mode 100644 index b24f8cb493d..00000000000 --- a/test/functional/data/util/netmagic-signet-custom.hex +++ /dev/null @@ -1 +0,0 @@ -a5df2dcb diff --git a/test/functional/data/util/netmagic-signet.hex b/test/functional/data/util/netmagic-signet.hex deleted file mode 100644 index 69a8b58868e..00000000000 --- a/test/functional/data/util/netmagic-signet.hex +++ /dev/null @@ -1 +0,0 @@ -0a03cf40 diff --git a/test/functional/data/util/netmagic-testnet.hex b/test/functional/data/util/netmagic-testnet.hex deleted file mode 100644 index 90b026d4d41..00000000000 --- a/test/functional/data/util/netmagic-testnet.hex +++ /dev/null @@ -1 +0,0 @@ -0b110907 diff --git a/test/functional/data/util/netmagic-testnet4.hex b/test/functional/data/util/netmagic-testnet4.hex deleted file mode 100644 index 8967d142b3c..00000000000 --- a/test/functional/data/util/netmagic-testnet4.hex +++ /dev/null @@ -1 +0,0 @@ -1c163f28