Files
ObsidianDragon/src/util/bootstrap.h
DanS 40dd6d45b2 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
2026-03-17 14:57:12 -05:00

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