fix: FAQ CJK glyphs, outgoing-tx history, lite encryption, migrate & sync safety

Bug-report fixes plus adversarial-audit follow-ups. Bumps full 2.0.1->2.0.2 and
lite 1.1.0->1.1.1.

i18n / fonts:
- Rebuild the NotoSansCJK subset with the glyphs the FAQ back-fill introduced
  (什/么/门/做); Chinese FAQ titles rendered as "??" on zh (and ja/ko).

Transaction history (enumeration gaps):
- Surface outgoing shielded z->z sends via z_listsentbyaddress (listtransactions
  and z_listreceivedbyaddress never report them).
- Surface z->t deshields by parsing z_listsentbyaddress transparentSends (which
  z_viewtransaction does not expose); dedupe t->t against listtransactions.
- Key send-row dedup on address so equal-value multi-output sends aren't dropped.

Lite wallet (key safety):
- The async create/restore/open path the UI uses now applies the passphrase:
  encrypt a new/restored wallet, unlock an existing one. It previously discarded
  the passphrase, storing the seed/keys in PLAINTEXT (create/restore) or leaving
  an encrypted wallet locked (open).

Migrate-to-seed (fund safety):
- Persist a sweep-submitted marker at broadcast so a resumed migration can't treat
  a ~0 balance (an unconfirmed in-flight sweep) as an empty wallet and adopt (swap
  wallet.dat) before the sweep confirms; best-effort locate routes to the confirm gate.

Sync / threading:
- Gate isSynced() on a peer-derived tip (tip_known) so a peerless node isn't reported
  synced (Send against a stale balance); add a "no peers" status banner.
- Guard daemon_status_ with a mutex (monitor-thread write vs UI-thread read).

Tests: extends tests/test_phase4.cpp across all of the above; suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwycPDQSfEKtrTS2uC4JeT
This commit is contained in:
2026-09-04 04:02:27 -05:00
parent f30fdc5ed1
commit fae8b20fb7
16 changed files with 646 additions and 34 deletions

View File

@@ -425,6 +425,9 @@ void I18n::loadBuiltinEnglish()
// Sweep step: balance still loading / no funds to move
strings_["mig_checking_balance"] = "Checking your balance";
strings_["mig_no_funds"] = "Your wallet has no funds to migrate. You can adopt the new seed wallet directly — it replaces your current (empty) wallet with the seed-backed one. Your old wallet is still moved aside to a timestamped backup, just in case.";
strings_["mig_sweep_inflight"] = "A sweep was already started and hasn't confirmed yet. Your balance reads zero because the funds are in the pending sweep transaction — they are not lost. Wait for it to confirm before finishing; the wallet will not be swapped until the sweep is mined.";
strings_["mig_checking_sweep"] = "Looking for the sweep transaction";
strings_["mig_check_sweep"] = "Check the sweep";
strings_["mig_adopt_now"] = "Adopt seed wallet";
strings_["mig_nofunds_confirm"] = "I understand this replaces my current wallet with the new seed wallet";
// Adopting step note (shown under the spinner while the node restarts + rescans)
@@ -1459,6 +1462,7 @@ void I18n::loadBuiltinEnglish()
strings_["sb_wallet_needs_recovery"] = "Wallet repair available";
// Persistent node-status banner (App::renderNodeStatusBanner).
strings_["node_banner_offline_title"] = "Not connected to the DragonX node";
strings_["node_banner_no_peers_title"] = "Connected, but no network peers — the node can't sync";
strings_["node_banner_crashed_title"] = "The node stopped unexpectedly";
strings_["node_banner_lite_open_failed"] = "Couldn't open your wallet";
strings_["node_banner_reconnect"] = "Reconnect";