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:
@@ -31,6 +31,7 @@ public:
|
||||
enum class LifecycleOperation {
|
||||
ManualRestart,
|
||||
Rescan,
|
||||
RepairWallet, // restart with -zapwallettxes=2 (wipe & rebuild wallet tx records)
|
||||
DeleteBlockchainData,
|
||||
BootstrapStop
|
||||
};
|
||||
@@ -46,6 +47,7 @@ public:
|
||||
bool setRescanOnNextStart = false;
|
||||
bool disconnectRpc = false;
|
||||
int restartDelayMs = 0;
|
||||
bool setZapOnNextStart = false;
|
||||
};
|
||||
|
||||
class LifecycleTaskContext {
|
||||
@@ -102,6 +104,8 @@ public:
|
||||
void resetCrashCount();
|
||||
void setRescanOnNextStart(bool enabled);
|
||||
bool rescanOnNextStart() const;
|
||||
void setZapOnNextStart(bool enabled);
|
||||
bool zapOnNextStart() const;
|
||||
|
||||
static ShutdownDecision evaluateShutdownPolicy(bool hasDaemon,
|
||||
bool externalDaemonDetected,
|
||||
@@ -141,6 +145,13 @@ public:
|
||||
}
|
||||
return {operation, true, daemonRunning, "rescan-blockchain", "Starting rescan...", "",
|
||||
false, true, false, 3000};
|
||||
case LifecycleOperation::RepairWallet:
|
||||
if (!usingEmbeddedDaemon || !hasDaemon) {
|
||||
return {operation, false, daemonRunning, "", "",
|
||||
"Wallet repair requires embedded daemon. Restart your daemon with -zapwallettxes=2 manually."};
|
||||
}
|
||||
return {operation, true, daemonRunning, "repair-wallet", "Repairing wallet...", "",
|
||||
false, false, false, 3000, true};
|
||||
case LifecycleOperation::DeleteBlockchainData:
|
||||
if (!usingEmbeddedDaemon || !hasDaemon) {
|
||||
return {operation, false, daemonRunning, "", "",
|
||||
@@ -190,6 +201,7 @@ public:
|
||||
}
|
||||
break;
|
||||
case LifecycleOperation::Rescan:
|
||||
case LifecycleOperation::RepairWallet:
|
||||
case LifecycleOperation::DeleteBlockchainData:
|
||||
runtime.stopDaemonWithPolicy();
|
||||
result.stopped = true;
|
||||
@@ -206,6 +218,7 @@ public:
|
||||
}
|
||||
|
||||
if (decision.operation == LifecycleOperation::Rescan ||
|
||||
decision.operation == LifecycleOperation::RepairWallet ||
|
||||
decision.operation == LifecycleOperation::DeleteBlockchainData) {
|
||||
runtime.resetOutputOffset();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user