Skip to content

feat: switch default auth scheme to ECDSA for new accounts#229

Open
WiktorStarczewski wants to merge 2 commits intomainfrom
wiktor/default-ecdsa
Open

feat: switch default auth scheme to ECDSA for new accounts#229
WiktorStarczewski wants to merge 2 commits intomainfrom
wiktor/default-ecdsa

Conversation

@WiktorStarczewski
Copy link
Copy Markdown
Collaborator

Summary

Switches the wallet's default auth scheme to ECDSA for new accounts. Existing accounts keep working as Falcon — their auth component is sealed at on-chain creation and can never rotate, so the signing path keys off whichever secret is in the keystore for each account regardless of any current "default".

Won't this break existing wallets?

No, but only because each restore path is updated to do the right thing. Detail in the commit; tl;dr:

Scenario Outcome
In-place upgrade (open wallet, don't wipe) No change. Existing Falcon accounts keep signing with Falcon. New accounts created post-upgrade are ECDSA.
Mnemonic-only restore (user wipes + types 12 words) Vault.spawn PROBES both schemes (falcon first, ecdsa second) to find the user's actual on-chain account. Falls through to fresh ECDSA create only if neither probe matches (= "fresh" mnemonic with no history).
Encrypted-file restore Each WalletAccount carries its scheme; restore re-derives the matching secret. Pre-migration files lack the field → treated as Falcon, matching the historical on-chain account.
Private-key import Scheme detected from the deserialized AuthSecretKey via the SDK's per-scheme accessor (throws on type mismatch). Stamped into the new WalletAccount.

The WalletAccount schema gets a new optional authScheme: 'falcon' | 'ecdsa' field. Missing-on-read → 'falcon' (matches the historical default 1:1). Encrypted-file format change is additive — no version bump needed.

Files

File What
src/lib/shared/types.ts New AuthScheme type + optional authScheme field on WalletAccount; legacy-on-read default documented inline.
src/lib/miden/back/vault.ts NEW_ACCOUNT_AUTH_SCHEME = 'ecdsa', LEGACY_AUTH_SCHEME = 'falcon'; helpers getAccountAuthScheme / authSecretKeyFromSeed / detectAuthScheme; all four creation paths thread the scheme correctly; Vault.spawn probe loop.
src/lib/miden/sdk/miden-client-interface.ts createMidenWallet and importPublicMidenWalletFromSeed now accept an optional auth and forward only when explicitly provided.
src/lib/miden/back/vault.test.ts Mock now exposes AuthSecretKey.ecdsaWithRNG; +5 tests covering each new branch.

Test plan

  • yarn jest — 1804/1804 pass
  • yarn test:coverage — gates clear (lines 95.67%, branches 95.01%, functions 95.46%, statements 95.67%)
  • In-place upgrade: existing Falcon wallet opens, signs, sends a tx
  • Mnemonic restore from a Falcon-era wallet: probe lands on falcon, account ID matches expected
  • Mnemonic restore from a fresh mnemonic: both probes miss, ECDSA account is created
  • Encrypted-file restore from a Falcon-era backup: legacy entries treated as Falcon
  • New encrypted-file export contains authScheme per account; round-trips through restore
  • Private-key import of a Falcon hex → authScheme='falcon'; ECDSA hex → authScheme='ecdsa'

…Falcon for existing

NEW account creation now defaults to ECDSA. EXISTING accounts (created
under the historical Falcon default) keep working as Falcon — their
auth component is sealed at on-chain creation and can never rotate, so
the signing path uses whatever secret is stored in the keystore for
each account regardless of any current 'default'.

To keep restore paths correct in both directions, WalletAccount gains
an optional 'authScheme' field. Legacy records (written before this
change) have it absent on read; consumers treat missing as Falcon, the
historical default. New records stamp the scheme at creation.

Behavior matrix:

  Scenario                          Outcome
  --------                          -------
  In-place upgrade                  No change. Existing Falcon accounts
                                    keep signing with Falcon. New account
                                    creations switch to ECDSA.

  Mnemonic-only restore             Vault.spawn now PROBES both schemes
  (no per-account metadata)         against the chain (falcon first,
                                    ecdsa second) to find the user's
                                    real account at hdIndex=0. If neither
                                    probe finds an on-chain account the
                                    user's mnemonic is fresh — fall
                                    through to a brand-new ECDSA create.

  Encrypted-file restore            Each WalletAccount in the file
  (per-account metadata present)    carries its scheme; restore uses it.
                                    Old files lacking the field default
                                    to Falcon, matching the historical
                                    on-chain account.

  Private-key import                Scheme detected from the
                                    deserialized AuthSecretKey via the
                                    SDK's per-scheme accessor (throws
                                    on type mismatch), stamped into the
                                    new WalletAccount.

Files touched:
- src/lib/shared/types.ts: AuthScheme type + optional WalletAccount
  field; legacy-on-read default documented inline.
- src/lib/miden/back/vault.ts: NEW_ACCOUNT_AUTH_SCHEME + LEGACY_AUTH_SCHEME
  constants; getAccountAuthScheme / authSecretKeyFromSeed /
  detectAuthScheme helpers. spawn / spawnFromMidenClient / createHDAccount
  / importAccountFromPrivateKey all stamp + thread the scheme correctly.
- src/lib/miden/sdk/miden-client-interface.ts: createMidenWallet and
  importPublicMidenWalletFromSeed accept optional auth, forward to SDK
  only when explicitly provided so unmigrated callers still get the SDK
  default.
- src/lib/miden/back/vault.test.ts: updated mock for the now-multi-probe
  spawn restore path; added 5 new tests covering each branch (probe
  finds account under second scheme, probe finds under first scheme,
  ECDSA secret stamped on import, ECDSA-derivation re-keying on
  encrypted-file restore, falcon-fallback on legacy WalletAccount with
  no authScheme).

1804/1804 tests pass; jest coverage gate clears at 95.67%/95.01%/95.46%/95.67%.

Encrypted-file format change is additive: old files restore as Falcon
(historical default), new files carry the per-account scheme. No
version bump.
@WiktorStarczewski WiktorStarczewski marked this pull request as ready for review May 5, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant