feat(wallet): detect a corrupt target wallet on switch + offer -salvagewallet repair
When a switch fails, the failure modal now distinguishes a CORRUPT target wallet
from other failures and offers a one-click repair:
- The switch worker watermarks the node's captured console output before the
start and, if the node dies in init, scans this start's output for a corruption
signature ("Failed to rename … .bak" / "salvage failed" / "wallet.dat corrupt" /
"Error loading wallet") → sets switch_wallet_corrupt_.
- The Failed modal then shows an accurate "this wallet appears corrupt" message
(instead of the generic "Couldn't open that wallet") plus a "Try to repair
(salvage)" button that retries the switch with the target node started under
-salvagewallet (recovers readable keypairs; implies -rescan).
- EmbeddedDaemon::setSalvageOnNextStart (one-shot, precedence salvage > zap >
rescan) + controller forwarder; switchToWallet gains a salvage arg.
Salvage operates only on the corrupt target (never the good wallet, no fund
movement). Adversarially verified: output isolation, one-shot lifecycle, state
handling, re-entrancy, no success-path regression.
i18n (EN + 8 languages) + 2 new CJK glyphs baked into the subset font.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3919,6 +3919,15 @@ void App::renderSwitchStopDaemonDialog()
|
||||
// rather than repeating the title.
|
||||
ui::material::DialogWarningHeader(wallet_switch_error_.c_str());
|
||||
ImGui::Dummy(ImVec2(0, ui::Layout::spacingMd()));
|
||||
// If the node reported the target wallet as corrupt, offer a one-click -salvagewallet repair
|
||||
// (retries the switch to that wallet with recovery enabled).
|
||||
if (switch_wallet_corrupt_.load()) {
|
||||
if (ui::material::TactileButton(TR("switch_corrupt_repair"), ImVec2(240.0f * dp, 0))) {
|
||||
const std::string target = wallet_switch_target_file_;
|
||||
switchToWallet(target, /*stopDaemonConfirmed=*/true, /*salvage=*/true); // reopens the progress modal
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
if (ui::material::TactileButton(TR("close"), ImVec2(110.0f * dp, 0))) {
|
||||
wallet_switch_dialog_open_.store(false);
|
||||
wallet_switch_phase_.store(static_cast<int>(WalletSwitchPhase::None));
|
||||
|
||||
Reference in New Issue
Block a user