fix: Windows identity, async address creation, mining UI, and chart artifacts

Windows identity:
- Add VERSIONINFO resource (.rc) with ObsidianDragon file description
- Embed application manifest for DPI awareness and shell identity
- Patch libwinpthread/libpthread to remove competing VERSIONINFO
- Set AppUserModelID and HWND property store to override Task Manager cache
- Link patched pthread libs to eliminate "POSIX WinThreads" description

Address creation (+New button):
- Move z_getnewaddress/getnewaddress off UI thread to async worker
- Inject new address into state immediately for instant UI selection
- Trigger background refresh for balance updates

Mining tab:
- Add pool mining dropdown with saved URLs/workers and bookmarks
- Add solo mining log panel from daemon output with chart/log toggle
- Fix toggle button cursor (render after InputTextMultiline)
- Auto-restart miner on pool config change
- Migrate default pool URL to include stratum port

Transactions:
- Sort pending (0-conf) transactions to top of history
- Fall back to timereceived when timestamp is missing

Shutdown:
- Replace blocking sleep_for calls with 100ms polling loops
- Check shutting_down_ flag throughout daemon restart/bootstrap flows
- Reduce daemon stop timeout from 30s to 10s

Other:
- Fix market chart fill artifact (single concave polygon vs per-segment quads)
- Add bootstrap checksum verification state display
- Rename daemon client identifier to ObsidianDragon
This commit is contained in:
dan_s
2026-03-05 22:43:27 -06:00
parent 4b16a2a2c4
commit 653a90de62
20 changed files with 842 additions and 116 deletions

View File

@@ -75,8 +75,11 @@ void App::encryptWalletWithPassphrase(const std::string& passphrase) {
// Give daemon a moment to shut down, then restart
// (do this off the main thread to avoid stalling the UI)
std::thread([this]() {
std::this_thread::sleep_for(std::chrono::seconds(2));
for (int i = 0; i < 20 && !shutting_down_; ++i)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (shutting_down_) return;
stopEmbeddedDaemon();
if (shutting_down_) return;
startEmbeddedDaemon();
// tryConnect will be called by the update loop
}).detach();
@@ -187,8 +190,11 @@ void App::processDeferredEncryption() {
// Restart daemon (it shuts itself down after encryptwallet)
if (isUsingEmbeddedDaemon()) {
std::thread([this]() {
std::this_thread::sleep_for(std::chrono::seconds(2));
for (int i = 0; i < 20 && !shutting_down_; ++i)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (shutting_down_) return;
stopEmbeddedDaemon();
if (shutting_down_) return;
startEmbeddedDaemon();
// tryConnect will be called by the update loop
}).detach();
@@ -1095,7 +1101,8 @@ void App::renderDecryptWalletDialog() {
}
// Wait for daemon to fully stop
std::this_thread::sleep_for(std::chrono::seconds(3));
for (int i = 0; i < 30 && !shutting_down_; ++i)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return [this, exportPath]() {
decrypt_step_ = 3;
@@ -1127,18 +1134,23 @@ void App::renderDecryptWalletDialog() {
decrypt_status_ = "Restarting daemon...";
auto restartAndImport = [this, exportPath]() {
std::this_thread::sleep_for(std::chrono::seconds(2));
for (int i = 0; i < 20 && !shutting_down_; ++i)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (shutting_down_) return;
if (isUsingEmbeddedDaemon()) {
stopEmbeddedDaemon();
std::this_thread::sleep_for(std::chrono::seconds(1));
if (shutting_down_) return;
for (int i = 0; i < 10 && !shutting_down_; ++i)
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (shutting_down_) return;
startEmbeddedDaemon();
}
// Wait for daemon to become available
int maxWait = 60;
bool daemonUp = false;
for (int i = 0; i < maxWait; i++) {
for (int i = 0; i < maxWait && !shutting_down_; i++) {
std::this_thread::sleep_for(std::chrono::seconds(1));
try {
rpc_->call("getinfo");