Create, import and store a wallet (Android engine) #73

Merged
paulhitt merged 1 commits from feat/wallet-store into main 2026-09-04 20:49:40 +00:00
paulhitt commented 2026-09-04 18:35:02 +00:00 (Migrated from gitlab.com)

Wallet makes one, adopts one from a phrase somebody typed, and reads the
phrase back; the vault seals the record at rest.

The property guarded hardest is a NEGATIVE one: a wallet must not be
derivable from the account. The entropy is fresh randomness — never the
passphrase, the handle, or the Flamenet identity. Deriving it from the
passphrase would be convenient, would need no backup at all, and would tie
every payment somebody ever received to their handle on a public ledger for
ever. The chain does not forget, so there is no undoing it later. A test
asserts that eight wallets made in a row share nothing, which is what would
catch that shortcut being taken.

The record stores the ENTROPY, never the seed. The seed is a one-way
function of the phrase, so a record holding it would open the wallet and be
unable to produce the words: somebody who lost their phrase but still had their
account could spend, and could never write it down again or move to another
wallet. Self-custody in name only.

Erasing the device destroys the record, and the phrase is then the only copy
that exists. Checked rather than assumed while writing this: plain sign-out
keeps the vault and updatePassword uses the plain door, so a password change
does NOT cost somebody their wallet; signOut(erasingDevice = true) and
deleteAccount destroy it. That is what a recovery phrase is for, and it has to
be said at the moment the phrase is shown rather than discovered afterwards.

An imported phrase is validated BEFORE it is stored. One that fails its
checksum is refused at import rather than saved and discovered later, when the
wallet it names turns out to be empty and nobody can say why.

The receive counter is carried across a rewrite rather than reset. Resuming
at zero would hand out addresses somebody has already been paid at, undoing the
one linkability a wallet can prevent.

SecureRandom() with no seeding call. Seeding it from a timestamp or a
device id would make the wallet reconstructible from things that are not
secret — the same failure as deriving it from the passphrase, wearing a
different hat.

9 tests. App builds, every JVM suite green.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

`Wallet` makes one, adopts one from a phrase somebody typed, and reads the phrase back; the vault seals the record at rest. The property guarded hardest is a NEGATIVE one: a wallet must not be derivable from the account. The entropy is fresh randomness — never the passphrase, the handle, or the Flamenet identity. Deriving it from the passphrase would be convenient, would need no backup at all, and would tie every payment somebody ever received to their handle on a public ledger for ever. The chain does not forget, so there is no undoing it later. A test asserts that eight wallets made in a row share nothing, which is what would catch that shortcut being taken. The record stores the ENTROPY, never the seed. The seed is a one-way function of the phrase, so a record holding it would open the wallet and be unable to produce the words: somebody who lost their phrase but still had their account could spend, and could never write it down again or move to another wallet. Self-custody in name only. Erasing the device destroys the record, and the phrase is then the only copy that exists. Checked rather than assumed while writing this: plain sign-out keeps the vault and `updatePassword` uses the plain door, so a password change does NOT cost somebody their wallet; `signOut(erasingDevice = true)` and `deleteAccount` destroy it. That is what a recovery phrase is for, and it has to be said at the moment the phrase is shown rather than discovered afterwards. An imported phrase is validated BEFORE it is stored. One that fails its checksum is refused at import rather than saved and discovered later, when the wallet it names turns out to be empty and nobody can say why. The receive counter is carried across a rewrite rather than reset. Resuming at zero would hand out addresses somebody has already been paid at, undoing the one linkability a wallet can prevent. `SecureRandom()` with no seeding call. Seeding it from a timestamp or a device id would make the wallet reconstructible from things that are not secret — the same failure as deriving it from the passphrase, wearing a different hat. 9 tests. App builds, every JVM suite green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
paulhitt commented 2026-09-04 18:35:03 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt
paulhitt commented 2026-09-04 20:49:38 +00:00 (Migrated from gitlab.com)

deleted the feat/wallet-keys-and-address branch. This merge request now targets the main branch

deleted the `feat/wallet-keys-and-address` branch. This merge request now targets the `main` branch
paulhitt commented 2026-09-04 20:49:40 +00:00 (Migrated from gitlab.com)

mentioned in commit 958689b3eb

mentioned in commit 958689b3eb38a03962e599bff831bccbf25f5b6d
paulhitt (Migrated from gitlab.com) merged commit 958689b3eb into main 2026-09-04 20:49:40 +00:00
paulhitt commented 2026-09-09 19:01:31 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
Sign in to join this conversation.