fix(autoshield): defer to the daemon's own coinbase auto-shield on v1.3.0+

v1.3.0 daemons auto-shield coinbase by default (when the HD seed is recoverable — which
every ObsidianDragon-created wallet is, via -usemnemonic=1). The wallet also ran its own
client-side auto-shield every refresh tick, so both raced for the same coinbase UTXOs and
split funds across different z-addresses (the wallet picks the first z_listaddresses entry;
the daemon uses a seed-hardened derivation).

Probe z_autoshieldstatus once per connection (while synced, so the daemon is past warmup)
and skip the wallet's client-side shield when the daemon reports it active. Fail-closed: a
pre-1.3.0 daemon has no such RPC, so the probe returns active=false and the wallet keeps
shielding — no regression on the currently-bundled v1.0.3. Re-probes on reconnect (handles
a live daemon upgrade/swap).

Follow-up (not done): drive the Settings "Auto-shield" toggle + disabled_reason from
z_autoshieldstatus (O1) — needs runtime verification of the RPC fields on a live v1.3.0 node.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-31 22:33:12 -05:00
co-authored by Claude Opus 4.8
parent 0942691eb3
commit ba1d760bb3
2 changed files with 36 additions and 3 deletions
+7
View File
@@ -1241,6 +1241,13 @@ private:
// Auto-shield guard (prevents concurrent auto-shield operations)
std::atomic<bool> auto_shield_pending_{false};
// v1.3.0+ daemons auto-shield coinbase themselves; probe z_autoshieldstatus once per connection and
// defer the wallet's own client-side auto-shield when the daemon is doing it (otherwise both race for
// the same coinbase UTXOs and split funds across different z-addresses). Fail-closed: a pre-1.3.0
// daemon lacks the RPC → active stays false → the wallet keeps shielding client-side (no regression).
bool daemon_autoshield_probed_ = false;
bool daemon_autoshield_active_ = false;
std::atomic<bool> daemon_autoshield_probe_inflight_{false};
// P4: Incremental transaction cache
int last_tx_block_height_ = -1; // block height at last full tx fetch