feat(fullnode): add "Repair Wallet" (-zapwallettxes=2) to Settings

When a note's stored record is corrupt or its tx isn't in the canonical chain,
z_sendmany fails to build a valid sapling spend proof even after a full -rescan,
because a plain rescan replays witnesses but keeps the existing tx/note records.
The zcashd repair for this is -zapwallettxes=2, which deletes all wallet tx/note
records and rebuilds them from the chain (keys/addresses preserved).

Adds a RepairWallet lifecycle operation that mirrors the existing -rescan plumbing
(one-shot zapOnNextStart flag on the embedded daemon; -zapwallettxes=2 implies and
supersedes -rescan), an App::repairWallet() that reuses the rescan status UI (so the
status bar + warmup-end completion detection apply), and a confirmed "Repair Wallet"
button + dialog in Settings → node maintenance (embedded daemon only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 07:42:10 -05:00
parent 6ff80354df
commit 37c8287a12
8 changed files with 129 additions and 2 deletions

View File

@@ -183,6 +183,14 @@ public:
void setRescanOnNextStart(bool v) { rescan_on_next_start_ = v; }
bool rescanOnNextStart() const { return rescan_on_next_start_.load(); }
/**
* @brief Request a wallet repair (-zapwallettxes=2) on the next daemon start. This deletes all
* wallet transaction/note records and rebuilds them from the chain (keys are kept); the
* daemon implicitly rescans afterwards. One-shot, like the rescan flag.
*/
void setZapOnNextStart(bool v) { zap_on_next_start_ = v; }
bool zapOnNextStart() const { return zap_on_next_start_.load(); }
/** Get number of consecutive daemon crashes (resets on successful start or manual reset) */
int getCrashCount() const { return crash_count_.load(); }
/** Reset crash counter (call on successful connection or manual restart) */
@@ -222,6 +230,7 @@ private:
int max_connections_ = 0; // 0 = daemon default
std::atomic<int> crash_count_{0}; // consecutive crash counter
std::atomic<bool> rescan_on_next_start_{false}; // -rescan flag for next start
std::atomic<bool> zap_on_next_start_{false}; // -zapwallettxes=2 flag for next start
};
} // namespace daemon