From 75b946f315a0ec778506ff33f0119c5c7ad99bc7 Mon Sep 17 00:00:00 2001 From: everoddandeven Date: Wed, 11 Feb 2026 00:23:54 +0100 Subject: [PATCH] Add regtest option * Add `regtest` option to `monero_wallet_config` * Allow mismatched daemon hard fork version for regtest `monero_wallet_full` * Setup block reorg tolerance for regtest `monero_wallet_full` * add `regtest` parameter for `monero_wallet_full::open_wallet*` --- src/wallet/monero_wallet_full.cpp | 27 +++++++++++++++++++++++++-- src/wallet/monero_wallet_full.h | 6 ++++-- src/wallet/monero_wallet_model.cpp | 3 +++ src/wallet/monero_wallet_model.h | 1 + 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/wallet/monero_wallet_full.cpp b/src/wallet/monero_wallet_full.cpp index feeb055a..bc15e11f 100644 --- a/src/wallet/monero_wallet_full.cpp +++ b/src/wallet/monero_wallet_full.cpp @@ -1059,23 +1059,33 @@ namespace monero { return key_file_exists; } - monero_wallet_full* monero_wallet_full::open_wallet(const std::string& path, const std::string& password, const monero_network_type network_type) { + monero_wallet_full* monero_wallet_full::open_wallet(const std::string& path, const std::string& password, const monero_network_type network_type, bool regtest) { MTRACE("open_wallet(" << path << ", ***, " << network_type << ")"); monero_wallet_full* wallet = new monero_wallet_full(); wallet->m_w2 = std::unique_ptr(new tools::wallet2(static_cast(network_type), 1, true)); wallet->m_w2->load(path, password); wallet->m_w2->init(""); + if (regtest) { + if (network_type != monero_network_type::MAINNET) throw std::runtime_error("Network type must be mainnet when using regtest option"); + wallet->m_w2->allow_mismatched_daemon_version(true); + wallet->m_w2->max_reorg_depth(100000); + } wallet->init_common(); return wallet; } - monero_wallet_full* monero_wallet_full::open_wallet_data(const std::string& password, const monero_network_type network_type, const std::string& keys_data, const std::string& cache_data, const monero_rpc_connection& daemon_connection, std::unique_ptr http_client_factory) { + monero_wallet_full* monero_wallet_full::open_wallet_data(const std::string& password, const monero_network_type network_type, const std::string& keys_data, const std::string& cache_data, const monero_rpc_connection& daemon_connection, std::unique_ptr http_client_factory, bool regtest) { MTRACE("open_wallet_data(...)"); monero_wallet_full* wallet = new monero_wallet_full(); if (http_client_factory == nullptr) wallet->m_w2 = std::unique_ptr(new tools::wallet2(static_cast(network_type), 1, true)); else wallet->m_w2 = std::unique_ptr(new tools::wallet2(static_cast(network_type), 1, true, std::move(http_client_factory))); wallet->m_w2->load("", password, keys_data, cache_data); wallet->m_w2->init(""); + if (regtest) { + if (network_type != monero_network_type::MAINNET) throw std::runtime_error("Network type must be mainnet when using regtest option"); + wallet->m_w2->allow_mismatched_daemon_version(true); + wallet->m_w2->max_reorg_depth(100000); + } wallet->set_daemon_connection(daemon_connection); wallet->init_common(); return wallet; @@ -1100,6 +1110,7 @@ namespace monero { if (config_normalized.m_language.get().empty()) config_normalized.m_language = std::string("English"); if (!monero_utils::is_valid_language(config_normalized.m_language.get())) throw std::runtime_error("Unknown language: " + config_normalized.m_language.get()); if (config.m_network_type == boost::none) throw std::runtime_error("Must provide wallet network type"); + if (config.m_regtest != boost::none && *config.m_regtest == true && *config.m_network_type != monero_network_type::MAINNET) throw std::runtime_error("Network type must be mainnet when using regtest option"); // create wallet if (!config_normalized.m_seed.get().empty()) { @@ -1137,6 +1148,10 @@ namespace monero { if (http_client_factory == nullptr) wallet->m_w2 = std::unique_ptr(new tools::wallet2(static_cast(config.m_network_type.get()), 1, true)); else wallet->m_w2 = std::unique_ptr(new tools::wallet2(static_cast(config.m_network_type.get()), 1, true, std::move(http_client_factory))); wallet->m_w2->init(""); + if (config.m_regtest != boost::none && config.m_regtest.get() == true) { + wallet->m_w2->allow_mismatched_daemon_version(true); + wallet->m_w2->max_reorg_depth(100000); + } wallet->set_daemon_connection(config.m_server); wallet->m_w2->set_seed_language(language); if (config.m_account_lookahead != boost::none) wallet->m_w2->set_subaddress_lookahead(config.m_account_lookahead.get(), config.m_subaddress_lookahead.get()); @@ -1232,6 +1247,10 @@ namespace monero { else if (has_spend_key) wallet->m_w2->generate(config.m_path.get(), config.m_password.get(), spend_key_sk, true, false); else wallet->m_w2->generate(config.m_path.get(), config.m_password.get(), address_info.address, view_key_sk); wallet->m_w2->init(""); + if (config.m_regtest != boost::none && config.m_regtest.get() == true) { + wallet->m_w2->allow_mismatched_daemon_version(true); + wallet->m_w2->max_reorg_depth(100000); + } wallet->set_daemon_connection(config.m_server); wallet->m_w2->set_refresh_from_block_height(config.m_restore_height.get()); wallet->m_w2->set_seed_language(config.m_language.get()); @@ -1251,6 +1270,10 @@ namespace monero { if (http_client_factory == nullptr) wallet->m_w2 = std::unique_ptr(new tools::wallet2(static_cast(config.m_network_type.get()), 1, true)); else wallet->m_w2 = std::unique_ptr(new tools::wallet2(static_cast(config.m_network_type.get()), 1, true, std::move(http_client_factory))); wallet->m_w2->init(""); + if (config.m_regtest != boost::none && config.m_regtest.get() == true) { + wallet->m_w2->allow_mismatched_daemon_version(true); + wallet->m_w2->max_reorg_depth(100000); + } wallet->set_daemon_connection(config.m_server); wallet->m_w2->set_seed_language(config.m_language.get()); crypto::secret_key secret_key; diff --git a/src/wallet/monero_wallet_full.h b/src/wallet/monero_wallet_full.h index aa2b376c..2ac7d8e8 100644 --- a/src/wallet/monero_wallet_full.h +++ b/src/wallet/monero_wallet_full.h @@ -92,9 +92,10 @@ namespace monero { * @param path is the path to the wallet file to open * @param password is the password of the wallet file to open * @param network_type is the wallet's network type + * @param regtest enable regtest * @return a pointer to the wallet instance */ - static monero_wallet_full* open_wallet(const std::string& path, const std::string& password, const monero_network_type network_type); + static monero_wallet_full* open_wallet(const std::string& path, const std::string& password, const monero_network_type network_type, bool regtest = false); /** * Open an in-memory wallet from existing data buffers. @@ -105,9 +106,10 @@ namespace monero { * @param cache_data contains the contents of the wallet cache file (no extension) * @param daemon_connection is connection information to a daemon (default = an unconnected wallet) * @param http_client_factory allows use of custom http clients + * @param regtest enable regtest * @return a pointer to the wallet instance */ - static monero_wallet_full* open_wallet_data(const std::string& password, const monero_network_type, const std::string& keys_data, const std::string& cache_data, const monero_rpc_connection& daemon_connection = monero_rpc_connection(), std::unique_ptr http_client_factory = nullptr); + static monero_wallet_full* open_wallet_data(const std::string& password, const monero_network_type, const std::string& keys_data, const std::string& cache_data, const monero_rpc_connection& daemon_connection = monero_rpc_connection(), std::unique_ptr http_client_factory = nullptr, bool regtest = false); /** * Create a new wallet with the given configuration. diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 6aadd378..2ffa4d85 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -108,6 +108,7 @@ namespace monero { m_account_lookahead = config.m_account_lookahead; m_subaddress_lookahead = config.m_subaddress_lookahead; m_is_multisig = config.m_is_multisig; + m_regtest = config.m_regtest; } monero_wallet_config monero_wallet_config::copy() const { @@ -145,6 +146,7 @@ namespace monero { // set bool values if (m_save_current != boost::none) monero_utils::add_json_member("saveCurrent", m_save_current.get(), allocator, root); if (m_is_multisig != boost::none) monero_utils::add_json_member("isMultisig", m_is_multisig.get(), allocator, root); + if (m_regtest != boost::none) monero_utils::add_json_member("regtest", m_regtest.get(), allocator, root); // return root return root; @@ -182,6 +184,7 @@ namespace monero { else if (key == std::string("accountLookahead")) config->m_account_lookahead = it->second.get_value(); else if (key == std::string("subaddressLookahead")) config->m_subaddress_lookahead = it->second.get_value(); else if (key == std::string("isMultisig")) config->m_is_multisig = it->second.get_value(); + else if (key == std::string("regtest")) config->m_regtest = it->second.get_value(); } return config; diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index c15aa0c2..5ee66e6e 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -80,6 +80,7 @@ namespace monero { boost::optional m_account_lookahead; boost::optional m_subaddress_lookahead; boost::optional m_is_multisig; + boost::optional m_regtest; monero_wallet_config() {} monero_wallet_config(const monero_wallet_config& config);