1
0
forked from GRIN/grim
Files
goblin/locales
2ro 4337580806 goblin: full wallet backup (seed + all identities) with restore
The .backup file now seals the money seed AND every held identity in one
encrypted, versioned envelope, and the caption's promise ("Contains your
wallet and all identities.") is finally true.

Format (nostr/identity.rs): a JSON envelope tagged goblin_backup:2. The
seed phrase is sealed with seal_secret_text() and each identity with the
existing per-identity to_encrypted_backup() (so every element is itself a
valid v1 identity envelope). Both layers reuse the in-tree NIP-49 ncryptsec
+ NIP-44 primitives under one password: no new crypto, no new dependency.
The plaintext seed is assembled and sealed in memory (the zeroizing
recovery string drops at scope end) and never written to disk. Old v1
single-identity backups keep restoring unchanged; is_full_backup() is
checked before the v1 path so the two never collide.

Build (wallet.rs): create_full_backup() gathers the seed via the existing
recovery API (which proves the wallet password) plus every unlocked held
identity. restore_full_backup_identities() reinstates them into a freshly
created wallet, re-encrypting each under the new wallet password, making the
backup's active identity active, and reusing the held-index/service-rebuild
plumbing. The identity-only import paths now reject a full backup with a
clear pointer to wallet creation.

Restore (onboarding.rs): the restore-from-seed step gains a .backup picker;
unlocking it decrypts the seed into the standard 24-word creation grid and
stashes the identities, which a worker reinstates once the wallet opens.

Copy: backup caption, title, blurb, and saved-sub updated across all nine
locales; two new restore strings added in all nine.

Tests: full_backup_roundtrips_seed_identities_and_active,
old_single_identity_backup_is_not_a_full_backup,
seal_secret_text_roundtrips_and_is_opaque; i18n drift + news tests green.
2026-07-07 19:21:05 -04:00
..