feat(recovery): import keys from a legacy wallet backup file (z_importwallet)

Phase 3: for a wallet.dat the current daemon can't open, recover its keys from the OLD wallet's export file.
Settings → "Import From Backup File…" opens a dialog that takes the path to a z_exportwallet / dumpwallet
dump (or SilentDragon's "Export all private keys") and calls z_importwallet — the daemon reads every key
and does ONE rescan, far faster and simpler than importing keys one at a time. On success it nudges the user
to shield any mined coinbase from the Shield screen.

- New App::importWalletFile(path, cb): runs z_importwallet on the long-call lane (no client timeout — the
  rescan can take a long time), then refreshAddresses + markWalletMutated. Full-node only.
- Only the PATH touches GUI memory, never the keys themselves (the daemon reads the file) — less secret
  exposure than a pasted-key field.
- New renderImportWalletFileDialog (typed path + Paste/Clear, progress, result) + a Settings card.

Reuses the existing long-call + z_importwallet infra; the careful single-key import dialog is untouched.
No send/sweep/encrypt call changed. Build + ctest green; the import/rescan itself is a daemon RPC, not
pure-testable, and wasn't exercised end-to-end here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-19 22:43:49 -05:00
co-authored by Claude Opus 4.8
parent 293b633a24
commit a3b4f534d5
5 changed files with 149 additions and 1 deletions
+10
View File
@@ -630,6 +630,15 @@ void I18n::loadBuiltinEnglish()
strings_["settings_merge_to_address"] = "Merge to Address…";
strings_["settings_clear_ztx"] = "Clear Z-Tx History";
strings_["settings_import_key"] = "Import Private Key…";
strings_["settings_import_wallet_file"] = "Import From Backup File…";
strings_["import_wallet_file_title"] = "Import keys from a backup file";
strings_["import_wallet_file_note"] = "Imports every private key from an old wallet's export file (its z_exportwallet / dumpwallet output, or SilentDragon's \"Export all private keys\") and rescans once — the fastest way to recover a legacy wallet.dat this client can't open.";
strings_["import_wallet_file_path_label"] = "Path to the key dump file:";
strings_["import_wallet_file_import_btn"] = "Import and rescan";
strings_["import_wallet_file_importing"] = "Importing keys and rescanning — this can take a while";
strings_["import_wallet_file_ok"] = "Keys imported. Once the rescan finishes, shield any mined (coinbase) transparent funds from the Shield screen to make them spendable.";
strings_["import_wallet_file_need_path"] = "Enter the path to the key dump file.";
strings_["import_wallet_file_not_found"] = "Couldn't open that file — check the path is correct and the file is readable.";
strings_["settings_import_viewkey"] = "Import Viewing Key…";
strings_["settings_export_key"] = "Export Key…";
strings_["settings_export_all"] = "Export All…";
@@ -1099,6 +1108,7 @@ void I18n::loadBuiltinEnglish()
// Settings: additional tooltips (keys/data row)
strings_["tt_import_key"] = "Import a private key (zkey or tkey) into this wallet";
strings_["tt_import_wallet_file"] = "Import all keys from an old wallet's exported dump file (one rescan)";
strings_["tt_import_viewkey"] = "Import a shielded viewing key to watch an address (read-only)";
strings_["tt_export_key"] = "Export the private key for the selected address";
strings_["tt_export_all"] = "Export all private keys to a file";