Account creation, derivation and default keypair type #3
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #1. Depends on #2 and on quantus/common#1, #2 and #4.
Default type
Two places pick
sr25519today:packages/extension/src/background.ts:103—keyring.loadAll({ store: new AccountsStore(), type: 'sr25519' })packages/extension-ui/src/util/defaultType.ts—export const DEFAULT_TYPE: KeypairType = 'sr25519'Both become
dilithium65. ML-DSA-87 must remain importable — it is what accounts created before the scheme was recorded use — but never offered as a choice for a new account.Derivation UI
packages/extension-ui/src/Popup/Derive/*is built around substrate suri junctions, andSelectParent.tsxalready gates onparent?.type === 'sr25519'with the message "Soft derivation is only allowed for sr25519 accounts". None of that vocabulary survives: Quantus derivation is a hardened BIP44 path where the account index sits at the third level,m/44'/189189'/<account>'/0'/1'.The honest UI is probably an account index, not a free-text path — a user typing
//aliceshould get an error, not a different account. Whatever the input, it has to produce exactly what quantus/common#4 accepts; settle the suri syntax there first and follow it here.packages/extension-base/src/utils/canDerive.tswhitelists['ed25519', 'sr25519', 'ecdsa', 'ethereum']and will silently returnfalsefor the new types, hiding the derive action entirely. That is a reasonable temporary state — better than a broken derive — but decide deliberately rather than by omission.Seed handling
Extension.tshasgetSuri()and anETH_DERIVE_DEFAULTconstant that appends a derivation path for ethereum accounts. Quantus needs the same treatment with its own default path, andseedValidateneeds to accept what the Quantus path produces. Its existing checks — 12/15/18/21/24 words,mnemonicValidate— are plain BIP39 and stay correct.Acceptance
quantus-cliderives for that mnemonic at index 0quantus-clifor the same nTwo constraints for this issue, both settled in
commonand both changing what the UI should do.The mnemonic is the only portable backup
quantus-cliwrites an entirely different wallet format — Argon2id + AES-256-GCM around a JSON payload, where polkadot-js uses scrypt + NaCl secretbox around PKCS8. Details in quantus/common#3.Neither tool can read the other's file. Import is fine, because a CLI wallet's mnemonic moves it and that path is verified against real CLI wallets. Export is the problem: a backup this extension writes is readable only by polkadot-js-format tooling, so a user whose only backup is our JSON, with the extension unavailable, cannot recover through
quantus-clior the mobile wallet.So the backup flow must present the mnemonic at least as prominently as the JSON file, and should say plainly that the JSON is extension-specific while the mnemonic works everywhere. That is a UI decision, not a format one — implementing CLI-format export was considered and rejected, since the format is mid-flight (
encryption_version: 2with emptykyber_*fields) and the mnemonic already covers it.One exception worth handling: dev-genesis wallets have no mnemonic (
derivation_path: "m/", raw seed). They move as a hex seed.seedValidatealready accepts a 256-bit hex seed, so the import side works; anything offering "back up your mnemonic" needs to not claim one exists for those accounts.Derivation: offer an index at creation, not a derive action
quantus/common#4 landed the suri syntax:
//<n>//m/44'/189189'/…Send
//<n>.//Alicethrows,/0throws, and an unhardened level in an explicit path throws — deliberately, since reinterpreting any of them would produce an address no other Quantus tool derives.More importantly for the UI:
pair.derive()refuses, and cannot do otherwise. ML-DSA keys are not derivable from one another — the Quantus tree derives each account from the mnemonic independently — so "derive a child from this account" is not an unimplemented feature, it is an impossible one. The error namescreateFromUriand the mnemonic.That settles the
canDerive.tsquestion this issue left open: it is not a temporary omission to revisit. The derive-from-parent flow inPopup/Derive/*has no ML-DSA meaning at all, and what replaces it is an account index chosen at creation or import time, against the mnemonic the user already has. Worth doing as part of the create/import screens rather than as a separate action that only ever fails.Checked against
main. Most of this is superseded by the wallet model in #14. Two concrete items remain.Met:
dilithium65(background.ts,util/defaultType.ts).quantus-cli: the index-0 accounts of a mnemonic, both schemes (Extension.spec.tswallets block, and common'sdilithiumDerive.spec.ts).TEST_ADDRESS_HD_0andTEST_WORMHOLE_ADDRESS, both also pinned by the mobile SDK, were checked in the running extension.canDeriveis false for ML-DSA, and wallets add account indices instead.Remaining:
quantus-cli. Today the path is only correct by construction (//<n>→m/44'/189189'/n'/0'/scheme'), and the tests show only that index 1 differs from index 0. Add a CLI-derived address for an index ≥ 1 as a vector.Export.tsxandExportAll.tsxare upstream's. They should put the recovery phrase ahead of the JSON file, and say the JSON restores only into this extension.