- 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
119 lines
4.2 KiB
C++
119 lines
4.2 KiB
C++
// DragonX Wallet - ImGui Edition
|
|
// Copyright 2024-2026 The Hush Developers
|
|
// Released under the GPLv3
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <mutex>
|
|
#include <atomic>
|
|
#include <thread>
|
|
|
|
namespace dragonx {
|
|
namespace util {
|
|
|
|
/**
|
|
* @brief Bootstrap downloader + extractor for DRAGONX blockchain data.
|
|
*
|
|
* Downloads a blockchain snapshot zip from bootstrap.dragonx.is, verifies
|
|
* SHA-256 / MD5 checksums, extracts it into the DRAGONX data directory
|
|
* (skipping wallet.dat), and cleans old chain data before extraction.
|
|
* All work runs on a background thread; progress is queried thread-safely
|
|
* from the UI thread.
|
|
*/
|
|
class Bootstrap {
|
|
public:
|
|
enum class State {
|
|
Idle,
|
|
Downloading,
|
|
Verifying,
|
|
Extracting,
|
|
Completed,
|
|
Failed
|
|
};
|
|
|
|
struct Progress {
|
|
State state = State::Idle;
|
|
double downloaded_bytes = 0;
|
|
double total_bytes = 0; // 0 if server doesn't send Content-Length
|
|
float percent = 0.0f; // 0..100
|
|
std::string status_text; // human-readable status
|
|
std::string error; // non-empty on failure
|
|
};
|
|
|
|
Bootstrap() = default;
|
|
~Bootstrap();
|
|
|
|
// Non-copyable
|
|
Bootstrap(const Bootstrap&) = delete;
|
|
Bootstrap& operator=(const Bootstrap&) = delete;
|
|
|
|
/// 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.
|
|
/// @param dataDir Path to DRAGONX data dir (e.g. ~/.hush/DRAGONX/)
|
|
/// @param url Bootstrap zip URL
|
|
void start(const std::string& dataDir,
|
|
const std::string& url = "https://bootstrap.dragonx.is/DRAGONX.zip");
|
|
|
|
/// Cancel an in-progress download/extract.
|
|
void cancel();
|
|
|
|
/// Thread-safe read of current progress.
|
|
Progress getProgress() const;
|
|
|
|
/// Whether the operation is finished (success or failure).
|
|
bool isDone() const;
|
|
|
|
/// Format a byte count as human-readable string (e.g. "1.24 GB")
|
|
static std::string formatSize(double bytes);
|
|
|
|
private:
|
|
mutable std::mutex mutex_;
|
|
Progress progress_;
|
|
std::atomic<bool> cancel_requested_{false};
|
|
std::thread worker_;
|
|
std::atomic<bool> worker_running_{false};
|
|
|
|
bool download(const std::string& url, const std::string& destZip);
|
|
bool extract(const std::string& zipPath, const std::string& dataDir);
|
|
void cleanChainData(const std::string& dataDir);
|
|
void setProgress(State state, const std::string& text, double downloaded = 0, double total = 0);
|
|
|
|
/// Download a small text file (checksum) into a string. Returns empty on failure.
|
|
std::string downloadSmallFile(const std::string& url);
|
|
|
|
/// Compute SHA-256 of a file, return lowercase hex digest.
|
|
/// Updates progress with "Verifying SHA-256..." status during computation.
|
|
std::string computeSHA256(const std::string& filePath);
|
|
|
|
/// Compute MD5 of a file, return lowercase hex digest.
|
|
/// Updates progress with "Verifying MD5..." status during computation.
|
|
std::string computeMD5(const std::string& filePath);
|
|
|
|
/// Parse the first hex token from a checksum file (handles "<hash> <filename>" format).
|
|
static std::string parseChecksumFile(const std::string& content);
|
|
|
|
/// Verify downloaded zip against remote checksums. Returns true if valid.
|
|
bool verifyChecksums(const std::string& zipPath, const std::string& baseUrl);
|
|
|
|
/// Perform a HEAD request to get remote file size.
|
|
/// Returns -1 on failure.
|
|
long long getRemoteFileSize(const std::string& url);
|
|
|
|
/// Byte offset of the partial file when resuming a download.
|
|
/// Added to dlnow in progress reports so the bar reflects true total.
|
|
double resume_offset_{0};
|
|
|
|
// libcurl progress callback (static → calls into instance via clientp)
|
|
static int progressCallback(void* clientp, long long dltotal, long long dlnow,
|
|
long long ultotal, long long ulnow);
|
|
};
|
|
|
|
} // namespace util
|
|
} // namespace dragonx
|