feat(node): warn when the daemon auto-recovers (salvages) wallet.dat
dragonxd auto-recovers a wallet.dat that fails BDB verification on startup — no flag needed (CWallet::Verify → CDBEnv::Verify(walletFile, CWalletDB::Recover)): it moves the original to wallet.<timestamp>.bak, salvages readable keys into a fresh wallet.dat, and keeps running. The salvage can be incomplete (or the whole thing a FALSE POSITIVE from stale/cross-platform BDB env state — __db.* / the database/ dir carried between machines), so the node silently comes up on a possibly-empty wallet. To the user that reads as fund loss, with no warning. Detect it and warn loudly instead: - daemon/daemon_startup_diagnosis.h: pure walletAutoRecovered() (the salvage / "Original wallet.dat saved as wallet.<ts>.bak" markers) + newestWalletSalvageBak() (picks the wallet.<unixtime>.bak the recovery just made). - onConnected() scans the node's captured output once per session; on a match it shows a warning dialog + notification: the ORIGINAL is safe in wallet.<ts>.bak, the shown balance may be incomplete, and here are the exact steps to restore it (rename the .bak back + delete the stale database/ + __db.* env). One-click "Open data folder" jumps straight there. Full-node only; lite-safe. Deliberately does NOT auto-swap the wallet files (untested per-platform file manipulation on a real wallet is not worth the risk) — it informs + guides. Adds walletAutoRecovered / newestWalletSalvageBak coverage to testBlockDbOutputDiagnosis. Suite green (1/1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -572,6 +572,20 @@ void App::onConnected()
|
||||
daemon_last_seen_crashes_ = 0; // (onConnected resets the daemon's crash count too)
|
||||
connection_status_ = TR("connected");
|
||||
|
||||
// Detect a silent wallet AUTO-RECOVERY: dragonxd moves wallet.dat to wallet.<ts>.bak and loads a
|
||||
// salvaged copy whenever BDB verify fails (no flag, often a false positive from stale/cross-platform
|
||||
// env state). The node comes up fine — so we only see it here, on connect — but the loaded wallet can
|
||||
// be empty/incomplete, which reads as fund loss. Surface it loudly, once per session, so the user can
|
||||
// restore the untouched original from the .bak. (Full-node only; lite has no embedded dragonxd.)
|
||||
if (!wallet_auto_recovered_warned_ && isUsingEmbeddedDaemon() && daemon_controller_ && daemon_controller_->daemon() &&
|
||||
daemon::walletAutoRecovered(daemon_controller_->daemon()->getOutput())) {
|
||||
wallet_auto_recovered_ = true;
|
||||
wallet_auto_recovered_warned_ = true;
|
||||
show_wallet_recovered_dialog_ = true;
|
||||
ui::Notifications::instance().error(TR("wallet_recovered_notify"), 30.0f);
|
||||
VERBOSE_LOGF("[connect] Daemon auto-recovered wallet.dat (salvage) — warning the user\n");
|
||||
}
|
||||
|
||||
// Stamp the active wallet as opened in the index (last-opened + size + synced-here). Balance +
|
||||
// address count fill in on the first address refresh (addresses aren't loaded yet here).
|
||||
updateWalletIndexForActiveWallet(/*markOpened=*/true);
|
||||
|
||||
Reference in New Issue
Block a user