daemon version check, idle mining control, bootstrap mirror, import key paste, and cleanup

- Add startup binary version checking for dragonxd/xmrig
- Display daemon version in UI
- Add idle mining thread count adjustment
- Add bootstrap mirror option (bootstrap2.dragonx.is) in setup wizard
- Add paste button to import private key dialog with address validation
- Add z-address generation UI feedback (loading indicator)
- Add option to delete blockchain data while preserving wallet.dat
- Add font scale slider hotkey tooltip (Ctrl+Plus/Ctrl+Minus)
- Fix Windows RPC auth: trim \r from config values, add .cookie fallback
- Fix connection status message during block index loading
- Improve application shutdown to prevent lingering background process
This commit is contained in:
dan_s
2026-03-17 14:57:12 -05:00
parent f0c87e4092
commit 4a841fd032
27 changed files with 897 additions and 2050 deletions

View File

@@ -3,6 +3,7 @@
// Released under the GPLv3
#include "bootstrap.h"
#include "../daemon/embedded_daemon.h"
#include <curl/curl.h>
#include <miniz.h>
@@ -135,11 +136,33 @@ void Bootstrap::start(const std::string& dataDir, const std::string& url) {
worker_running_ = false;
return;
}
// Step 3: Clean old chain data
// Step 3: Ensure daemon is fully stopped before touching chain data
{
setProgress(State::Extracting, "Waiting for daemon to stop...");
int waited = 0;
while (daemon::EmbeddedDaemon::isRpcPortInUse() && waited < 60 && !cancel_requested_) {
std::this_thread::sleep_for(std::chrono::seconds(1));
waited++;
if (waited % 5 == 0)
DEBUG_LOGF("[Bootstrap] Still waiting for daemon to stop... (%ds)\n", waited);
}
if (cancel_requested_) {
setProgress(State::Failed, "Cancelled while waiting for daemon");
worker_running_ = false;
return;
}
if (daemon::EmbeddedDaemon::isRpcPortInUse()) {
setProgress(State::Failed, "Daemon is still running — stop it before using bootstrap");
worker_running_ = false;
return;
}
}
// Step 4: Clean old chain data
setProgress(State::Extracting, "Removing old chain data...");
cleanChainData(dataDir);
// Step 4: Extract (skipping wallet.dat)
// Step 5: Extract (skipping wallet.dat)
if (!extract(zipPath, dataDir)) {
if (cancel_requested_)
setProgress(State::Failed, "Extraction cancelled");

View File

@@ -51,6 +51,7 @@ public:
/// Base URL for bootstrap downloads (zip + checksum files).
static constexpr const char* kBaseUrl = "https://bootstrap.dragonx.is";
static constexpr const char* kMirrorUrl = "https://bootstrap2.dragonx.is";
static constexpr const char* kZipName = "DRAGONX.zip";
/// Start the bootstrap process on a background thread.

View File

@@ -297,7 +297,7 @@ void I18n::loadBuiltinEnglish()
strings_["tt_noise"] = "Grain texture intensity (0%% = off, 100%% = maximum)";
strings_["tt_ui_opacity"] = "Card and sidebar opacity (100%% = fully opaque, lower = more see-through)";
strings_["tt_window_opacity"] = "Background opacity (lower = desktop visible through window)";
strings_["tt_font_scale"] = "Scale all text and UI (1.0x = default, up to 1.5x).";
strings_["tt_font_scale"] = "Scale all text and UI (1.0x = default, up to 1.5x). Hotkey: Alt + Scroll Wheel";
strings_["tt_custom_theme"] = "Custom theme active";
strings_["tt_address_book"] = "Manage saved addresses for quick sending";
strings_["tt_validate"] = "Check if a DragonX address is valid";
@@ -321,6 +321,12 @@ void I18n::loadBuiltinEnglish()
strings_["tt_rpc_pass"] = "RPC authentication password";
strings_["tt_test_conn"] = "Verify the RPC connection to the daemon";
strings_["tt_rescan"] = "Rescan the blockchain for missing transactions";
strings_["tt_delete_blockchain"] = "Delete all blockchain data and start a fresh sync. Your wallet.dat and config are preserved.";
strings_["delete_blockchain"] = "Delete Blockchain";
strings_["delete_blockchain_confirm"] = "Delete & Resync";
strings_["confirm_delete_blockchain_title"] = "Delete Blockchain Data";
strings_["confirm_delete_blockchain_msg"] = "This will stop the daemon, delete all blockchain data (blocks, chainstate, peers), and start a fresh sync from scratch. This can take several hours to complete.";
strings_["confirm_delete_blockchain_safe"] = "Your wallet.dat, config, and transaction history are safe and will not be deleted.";
strings_["tt_encrypt"] = "Encrypt wallet.dat with a passphrase";
strings_["tt_change_pass"] = "Change the wallet encryption passphrase";
strings_["tt_lock"] = "Lock the wallet immediately";
@@ -718,6 +724,7 @@ void I18n::loadBuiltinEnglish()
strings_["console_daemon_error"] = "Daemon error!";
strings_["console_daemon_started"] = "Daemon started";
strings_["console_daemon_stopped"] = "Daemon stopped";
strings_["daemon_version"] = "Daemon";
strings_["console_disconnected"] = "Disconnected from daemon";
strings_["console_errors"] = "Errors";
strings_["console_filter_hint"] = "Filter output...";
@@ -836,6 +843,10 @@ void I18n::loadBuiltinEnglish()
strings_["mining_filter_tip_solo"] = "Show solo earnings only";
strings_["mining_idle_off_tooltip"] = "Enable idle mining";
strings_["mining_idle_on_tooltip"] = "Disable idle mining";
strings_["mining_idle_scale_on_tooltip"] = "Thread scaling: ON\nClick to switch to start/stop mode";
strings_["mining_idle_scale_off_tooltip"] = "Start/stop mode: ON\nClick to switch to thread scaling mode";
strings_["mining_idle_threads_active_tooltip"] = "Threads when user is active";
strings_["mining_idle_threads_idle_tooltip"] = "Threads when system is idle";
strings_["mining_local_hashrate"] = "Local Hashrate";
strings_["mining_mine"] = "Mine";
strings_["mining_mining_addr"] = "Mining Addr";
@@ -847,6 +858,7 @@ void I18n::loadBuiltinEnglish()
strings_["mining_open_in_explorer"] = "Open in explorer";
strings_["mining_payout_address"] = "Payout Address";
strings_["mining_payout_tooltip"] = "Address to receive mining rewards";
strings_["mining_generate_z_address_hint"] = "Generate a Z address in the Receive tab to use as your payout address";
strings_["mining_pool"] = "Pool";
strings_["mining_pool_hashrate"] = "Pool Hashrate";
strings_["mining_pool_url"] = "Pool URL";
@@ -927,6 +939,7 @@ void I18n::loadBuiltinEnglish()
// --- Receive Tab ---
strings_["click_copy_address"] = "Click to copy address";
strings_["click_copy_uri"] = "Click to copy URI";
strings_["generating"] = "Generating";
strings_["failed_create_shielded"] = "Failed to create shielded address";
strings_["failed_create_transparent"] = "Failed to create transparent address";
strings_["new_shielded_created"] = "New shielded address created";