bitcoin-util: replace netmagic command with getchainparams command
What changed, and why it matters
This commit renames and expands a command-line helper in Bitcoin Core. The old 'bitcoin-util netmagic' command, which only printed the network's magic bytes, is replaced by 'bitcoin-util getchainparams', which prints a JSON document containing chain parameters such as genesis block, ports, DNS seeds, and address prefixes. There is no security fix or vulnerability here; it is a routine feature change.
No security action required. Reviewers may want to confirm that the newly exposed parameters are all already public/hardcoded and that linking univalue does not introduce unexpected dependencies.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies src/bitcoin-util.cpp to replace the NetMagic() handler with GetChainParams(). The new handler builds a UniValue JSON object from the active CChainParams and consensus parameters, including chain type, genesis hash, subsidy halving interval, signet challenge, PoW limit/spacing/retarget interval, default port, message magic, DNS seeds, and bech32 HRP. It also updates CMakeLists.txt to link bitcoin-util against univalue, revises release notes, and swaps the old single-value hex test fixtures for JSON fixtures.
Changed components
src/bitcoin-util.cppsrc/CMakeLists.txttest/functional/data/util/bitcoin-util-test.jsonInspect captured patch +223 / −35
diff --git a/doc/release-notes-35610.md b/doc/release-notes-35610.md
index 8e0dd208..1f80677e 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 47266dcf..2b6840bb 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 f17c7a0d..7e774685 100644
--- a/src/bitcoin-util.cpp
+++ b/src/bitcoin-util.cpp
@@ -15,6 +15,7 @@
#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>
@@ -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<std::string>& args, std::string& strPrint)
return EXIT_SUCCESS;
}
-static int NetMagic(const std::vector<std::string>& args, std::string& strPrint)
+static int GetChainParams(const std::vector<std::string>& 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 9c37a4e5..2aaffff4 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 00000000..c0e0402c
--- /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 00000000..7a3191b7
--- /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 00000000..4f5d5287
--- /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 00000000..91905976
--- /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 00000000..b0b8a4ea
--- /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 00000000..a59dd106
--- /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 94b2c335..00000000
--- 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 e2a9cb27..00000000
--- 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 b24f8cb4..00000000
--- 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 69a8b588..00000000
--- 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 90b026d4..00000000
--- 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 8967d142..00000000
--- a/test/functional/data/util/netmagic-testnet4.hex
+++ /dev/null
@@ -1 +0,0 @@
-1c163f28
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.