Adversarial verification of the audit fixes found real gaps in them:
- HIGH throw-safety: the switch worker and the encryption-restart worker set
daemon_restarting_=true but reset it only on their normal/early-return paths —
a throw from stop/startEmbeddedDaemon left the flag stuck true, wedging
reconnect and every future switch/rescan/encryption. Both now reset it on all
paths (try/catch); a throw during a switch is treated as a failed switch and
triggers the revert.
- HIGH residual chat leak: resetChatSession() cleared the flags but an already-
posted z_exportmnemonic worker job still held wallet A's secret, and its
completion callback (guarded only by isLocked(), false for an unencrypted
wallet) would provision A's identity under B. Add a chat_session_generation_
epoch bumped on every wallet change; the fetch captures it and its callback
discards the (previous-wallet) secret if the epoch no longer matches.
- LOW vault-scope collision: the per-wallet vault tag was a lossy char-substitution
(two distinct files could map to one vault). Append an 8-hex FNV-1a of the raw
filename so distinct wallets never share a vault. +unit test.
- LOW seed-adopt: removeVault() on adopt so the legacy wallet's PIN passphrase
isn't left associated with the new seed wallet (same file name).
- LOW: clear lock_unlock_in_progress_ on switch too.
Deferred (documented): the 1.5s start grace can't catch a wallet that fails LATE
in daemon init (the existing crash-wedge detection still applies); beginShutdown's
join of the switch task can briefly freeze the UI during quit (necessary to avoid
orphaning the daemon).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From the wallet-switching audit (HIGH-severity cross-wallet leaks):
- Chat identity leak: the full-node switch (switchToWallet) and seed-migration
adopt reset state_ but NOT the HushChat identity, so wallet A's decrypted
conversations surfaced under wallet B and outgoing chat was signed with A's
keypair. Factor the existing teardown into App::resetChatSession() and call it
on both wallet-change paths (the lite path already reset it via
rebuildLiteWallet, which now uses the helper too).
- Global PIN vault: the PIN quick-unlock vault was a single vault.dat, so after
a switch wallet A's stored passphrase was offered/applied to encrypted wallet
B. SecureVault is now scoped per wallet (vault-<walletfile>.dat); the default
wallet keeps the legacy vault.dat for back-compat. vault_ is constructed for
the active wallet and re-scoped on switch, so B has its own (empty) vault.
- Lock-screen state: switching now clears the carried-over failed-attempt
counter + lockout timer and secure-zeroes the passphrase/PIN entry buffers so
the previous wallet's unlock state can't apply to the new one.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
removeVault() overwrote vault.dat with zeros then unlinked it, but never flushed
to stable storage, so the zeros could stay in the OS cache and never reach disk.
flush + fsync before unlink on POSIX (still best-effort on CoW/SSD, but now does
what it claims).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Write vault.dat atomically and 0600 (it holds the PIN-encrypted passphrase, so
a world-readable copy enables an offline brute-force of the short PIN), and
chmod the tx-history SQLite + its WAL/SHM sidecars to 0600 on open.
- The tx-history snapshot and key-salt rows are keyed on a hash of the full
address set, which changes whenever a new address is generated — orphaning the
prior hash's full-history blob and salt forever. pruneOtherWallets() now drops
rows for every non-live wallet hash on each save, bounding the database.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Full-node GUI wallet for DragonX cryptocurrency.
Built with Dear ImGui, SDL3, and OpenGL3/DX11.
Features:
- Send/receive shielded and transparent transactions
- Autoshield with merged transaction display
- Built-in CPU mining (xmrig)
- Peer management and network monitoring
- Wallet encryption with PIN lock
- QR code generation for receive addresses
- Transaction history with pagination
- Console for direct RPC commands
- Cross-platform (Linux, Windows)