blockchain_utilities: fix --data-dir option
What changed, and why it matters
This commit fixes command-line handling in Monero's blockchain utility programs. It makes sure the --data-dir option works correctly with the newer --regtest network mode, and centralizes the logic that decides which network type (mainnet, testnet, stagenet, or regtest) is being used. It is a code-quality and correctness fix rather than a security patch for an exploitable vulnerability.
Treat as a routine bug fix. No urgent security action is required, but operators using --regtest with blockchain utilities should upgrade to avoid data-dir/network mismatches.
Security signals we found
Fixes inconsistent command-line option handling across blockchain utilities
Adds missing --regtest support to multiple utilities
Centralizes network-type validation to prevent mutually-exclusive network flags
No evidence of memory corruption, authentication bypass, or cryptographic weakness
Evidence from the diff
The patch adds arg_regtest_on to several blockchain_utility command-line option descriptions and replaces inline ternary network-type resolution with a new shared helper core::get_network_type_from_args(). That helper enforces mutual exclusion of –testnet, –stagenet, and –regtest and returns FAKECHAIN for regtest. Previously some utilities did not expose –regtest and computed network type manually, which could lead to incorrect data directory / database network handling when regtest was intended. The daemon’s duplicate validation logic is also replaced with a call to the same helper.
Changed components
src/blockchain_utilities/blockchain_ancestry.cppsrc/blockchain_utilities/blockchain_depth.cppsrc/blockchain_utilities/blockchain_export.cppsrc/blockchain_utilities/blockchain_import.cppsrc/blockchain_utilities/blockchain_prune.cppsrc/blockchain_utilities/blockchain_prune_known_spent_data.cppsrc/blockchain_utilities/blockchain_stats.cppsrc/blockchain_utilities/blockchain_usage.cppsrc/cryptonote_core/cryptonote_core.cppsrc/cryptonote_core/cryptonote_core.hsrc/daemon/main.cppInspect captured patch +37 / −40
diff --git a/src/blockchain_utilities/blockchain_ancestry.cpp b/src/blockchain_utilities/blockchain_ancestry.cpp
index bdf5a12..721aec7 100644
--- a/src/blockchain_utilities/blockchain_ancestry.cpp
+++ b/src/blockchain_utilities/blockchain_ancestry.cpp
@@ -355,6 +355,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_regtest_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_txid);
command_line::add_arg(desc_cmd_sett, arg_output);
@@ -397,9 +398,7 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
- bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
+ const network_type net_type = core::get_network_type_from_args(vm);
std::string opt_txid_string = command_line::get_arg(vm, arg_txid);
std::string opt_output_string = command_line::get_arg(vm, arg_output);
uint64_t opt_height = command_line::get_arg(vm, arg_height);
diff --git a/src/blockchain_utilities/blockchain_depth.cpp b/src/blockchain_utilities/blockchain_depth.cpp
index c59052b..0d954e1 100644
--- a/src/blockchain_utilities/blockchain_depth.cpp
+++ b/src/blockchain_utilities/blockchain_depth.cpp
@@ -63,6 +63,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_regtest_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_txid);
command_line::add_arg(desc_cmd_sett, arg_height);
@@ -99,9 +100,7 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
- bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
+ const network_type net_type = core::get_network_type_from_args(vm);
std::string opt_txid_string = command_line::get_arg(vm, arg_txid);
uint64_t opt_height = command_line::get_arg(vm, arg_height);
bool opt_include_coinbase = command_line::get_arg(vm, arg_include_coinbase);
diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp
index 7702ba8..ae27348 100644
--- a/src/blockchain_utilities/blockchain_export.cpp
+++ b/src/blockchain_utilities/blockchain_export.cpp
@@ -68,6 +68,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, arg_output_file);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_regtest_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_block_start);
command_line::add_arg(desc_cmd_sett, arg_block_stop);
@@ -105,13 +106,6 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
- bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- if (opt_testnet && opt_stagenet)
- {
- std::cerr << "Can't specify more than one of --testnet and --stagenet" << std::endl;
- return 1;
- }
bool opt_blocks_dat = command_line::get_arg(vm, arg_blocks_dat);
std::string m_config_folder;
@@ -154,7 +148,8 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Error opening database: " << e.what());
return 1;
}
- r = core_storage->blockchain.init(db, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET);
+ const network_type net_type = core::get_network_type_from_args(vm);
+ r = core_storage->blockchain.init(db, net_type);
if (core_storage->blockchain.get_blockchain_pruning_seed() && !opt_blocks_dat)
{
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index 82ff2de..7563af6 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -667,13 +667,6 @@ int main(int argc, char* argv[])
}
}
- opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- if (opt_testnet && opt_stagenet)
- {
- std::cerr << "Error: Can't specify more than one of --testnet and --stagenet" << ENDL;
- return 1;
- }
m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
mlog_configure(mlog_get_default_log_path("monero-blockchain-import.log"), true);
diff --git a/src/blockchain_utilities/blockchain_prune.cpp b/src/blockchain_utilities/blockchain_prune.cpp
index bc5b6b6..9210ce0 100644
--- a/src/blockchain_utilities/blockchain_prune.cpp
+++ b/src/blockchain_utilities/blockchain_prune.cpp
@@ -547,6 +547,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_regtest_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_db_sync_mode);
command_line::add_arg(desc_cmd_sett, arg_copy_pruned_database);
@@ -581,9 +582,7 @@ int main(int argc, char* argv[])
MINFO("Starting...");
- bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
+ const network_type net_type = core::get_network_type_from_args(vm);
bool opt_copy_pruned_database = command_line::get_arg(vm, arg_copy_pruned_database);
std::string data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
while (boost::ends_with(data_dir, "/") || boost::ends_with(data_dir, "\\"))
diff --git a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp
index 6e7dd29..b4001de 100644
--- a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp
+++ b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp
@@ -112,6 +112,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_regtest_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_verbose);
command_line::add_arg(desc_cmd_sett, arg_dry_run);
@@ -148,9 +149,7 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
- bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
+ const network_type net_type = core::get_network_type_from_args(vm);
bool opt_verbose = command_line::get_arg(vm, arg_verbose);
bool opt_dry_run = command_line::get_arg(vm, arg_dry_run);
diff --git a/src/blockchain_utilities/blockchain_stats.cpp b/src/blockchain_utilities/blockchain_stats.cpp
index 7c8fb22..87703b8 100644
--- a/src/blockchain_utilities/blockchain_stats.cpp
+++ b/src/blockchain_utilities/blockchain_stats.cpp
@@ -145,6 +145,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_regtest_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_block_start);
command_line::add_arg(desc_cmd_sett, arg_block_stop);
@@ -187,9 +188,7 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
- bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
+ const network_type net_type = core::get_network_type_from_args(vm);
block_start = command_line::get_arg(vm, arg_block_start);
block_stop = command_line::get_arg(vm, arg_block_stop);
do_inputs = command_line::get_arg(vm, arg_inputs);
diff --git a/src/blockchain_utilities/blockchain_usage.cpp b/src/blockchain_utilities/blockchain_usage.cpp
index 9865478..b287a0e 100644
--- a/src/blockchain_utilities/blockchain_usage.cpp
+++ b/src/blockchain_utilities/blockchain_usage.cpp
@@ -93,6 +93,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_regtest_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_rct_only);
command_line::add_arg(desc_cmd_sett, arg_input);
@@ -130,9 +131,7 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
- bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
+ const network_type net_type = core::get_network_type_from_args(vm);
bool opt_rct_only = command_line::get_arg(vm, arg_rct_only);
// If we wanted to use the memory pool, we would set up a fake_core.
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 2964875..511e29b 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -354,13 +354,21 @@ namespace cryptonote
BlockchainDB::init_options(desc);
}
//-----------------------------------------------------------------------------------------------
+ network_type core::get_network_type_from_args(const boost::program_options::variables_map& vm)
+ {
+ const bool testnet = command_line::get_arg(vm, arg_testnet_on);
+ const bool stagenet = command_line::get_arg(vm, arg_stagenet_on);
+ const bool regtest = command_line::get_arg(vm, arg_regtest_on);
+ if (testnet + stagenet + regtest > 1)
+ throw std::runtime_error("More than one network type argument was specified");
+ return testnet ? TESTNET : stagenet ? STAGENET : regtest ? FAKECHAIN : MAINNET;
+ }
+ //-----------------------------------------------------------------------------------------------
bool core::handle_command_line(const boost::program_options::variables_map& vm)
{
if (m_nettype != FAKECHAIN)
{
- const bool testnet = command_line::get_arg(vm, arg_testnet_on);
- const bool stagenet = command_line::get_arg(vm, arg_stagenet_on);
- m_nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
+ m_nettype = get_network_type_from_args(vm);
}
m_config_folder = command_line::get_arg(vm, arg_data_dir);
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index d57c6cc..3e4b862 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -276,6 +276,15 @@ namespace cryptonote
*/
static void init_options(boost::program_options::options_description& desc);
+ /**
+ * @brief resolves the network type based on command line arguments
+ * @param vm variables map
+ * @return network type corresponding to arg_{testnet,stagenet,regtest}_on, defaulting to MAINNET
+ * @throw std::runtime_error if more than 1 of arg_{testnet,stagenet,regtest}_on is present
+ * @throw boost::bad_any_cast if arg_{testnet,stagenet,regtest}_on weren't added to vm
+ */
+ static network_type get_network_type_from_args(const boost::program_options::variables_map& vm);
+
/**
* @brief initializes the core as needed
*
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index b455b4f..8ad5de0 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -240,10 +240,8 @@ int main(int argc, char const * argv[])
return 1;
}
- const bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
- const bool regtest = command_line::get_arg(vm, cryptonote::arg_regtest_on);
- if (testnet + stagenet + regtest > 1)
+ try { cryptonote::core::get_network_type_from_args(vm); }
+ catch (const std::runtime_error&)
{
std::cerr << "Can't specify more than one of --testnet and --stagenet and --regtest" << ENDL;
return 1;
Why this scored 18/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.