Skip to content

fix(mint/auth): make a fresh 0.21.0 auth mint work end-to-end#1004

Open
robwoodgate wants to merge 31 commits into
cashubtc:mainfrom
robwoodgate:fix/auth-keyset-migrations
Open

fix(mint/auth): make a fresh 0.21.0 auth mint work end-to-end#1004
robwoodgate wants to merge 31 commits into
cashubtc:mainfrom
robwoodgate:fix/auth-keyset-migrations

Conversation

@robwoodgate
Copy link
Copy Markdown
Contributor

@robwoodgate robwoodgate commented May 13, 2026

Stacked on #999

This PR is a fix for BLS implementation PR #999.

Summary

Five coupled fixes that surface together when a fresh Nutshell 0.21.0 auth mint runs against any OIDC provider (e.g. Keycloak 25+) and a v3 (BLS) keyset is generated on first start. Verified end-to-end against a local Keycloak + this branch + cashu-ts.

Each fix is small; bundled because they share one architectural root — AuthLedger inherits the mint CRUD (LedgerCrudSqlite) and the global mint_input_fee_ppk setting, while the auth migrations chain / response models / user-id contract / auth-side CRUD never kept up.

The five fixes

  1. Force input_fee_ppk=0 on auth keyset generation. Auth proofs are NUT-22 amount-1 bearer tokens — never swapped or melted. AuthLedger.verify_blind_auth already explicitly skips fee calculation. But Ledger.activate_keyset reads settings.mint_input_fee_ppk unconditionally, so any mint with a non-zero global fee bakes that value into the auth keyset id — semantically wrong, and breaks wallet-side id re-derivation. Matches CDK's behaviour (crates/cdk/src/mint/builder.rs forces fee=0 for the Auth unit). Implementation: LedgerKeysets gets a per-instance keyset_input_fee_ppk: Optional[int] = None defaulting to settings.mint_input_fee_ppk; AuthLedger overrides to 0. No behaviour change for non-auth ledgers.

  2. m003: add final_expiry column to auth keysets table. LedgerCrudSqlite.store_keyset INSERTs final_expiry (added on the mint side in m031 for keysets v2). Auth migrations stopped at m002, so v3 keyset generation crashes with no column named final_expiry. Mirrors mint m031.

  3. m004: align auth promises table with the mint-side schema. The mint side evolved promises to add mint_quote / swap_id (m023) and melt_quote / signed_at + drop the c_ NOT NULL constraint (m032-ish). LedgerCrudSqlite.store_promise INSERTs the full column set, so auth-side blind minting (first exercised by v3 BAT issuance at 0.21+) trips first no column named mint_quote then NOT NULL constraint failed: promises.c_. SQLite path rebuilds the table; Postgres path uses the ALTER chain.

  4. Tolerate missing sub claim in clear-auth tokens. _get_user hard-coded decoded_token[\"sub\"], raising KeyError when the IdP omits sub from access tokens. Keycloak 25+ does this by default for public clients (the oidc-subject-mapper declared in the test cashu-realm.json gets silently dropped on import). CDK's verify_cat doesn't read sub at all and works against the same realm. Fall back to preferred_username then azp so single-user-per-realm rate-limit tracking still works without changing happy-path semantics for IdPs that ship sub. Cross-IdP, not Keycloak-specific.

  5. AuthLedgerCrudSqlite.get_keyset: use MintKeyset.from_row instead of MintKeyset(**row). The mint-side equivalent (cashu/mint/crud.py:962) uses from_row correctly; the auth-side spreads the row dict directly into the constructor, which passes amounts through as the raw stringified-JSON SQLite stores (e.g. \"[1]\"). Iteration over self.amounts would then walk characters instead of list elements, producing junk key material. Dead code under the current wiring — cashu/mint/startup.py:94 constructs AuthLedger with crud=LedgerCrudSqlite() (whose get_keyset is the correct from_row version), and self.auth_crud = AuthLedgerCrudSqlite() is only used for user CRUD (get_user / create_user / update_user), never for get_keyset. Fixed anyway as a 1-line free fix that removes a landmine for the eventual switch-to-AuthLedgerCrudSqlite cleanup noted below.

Out of scope (worth a follow-up)

The underlying smell is AuthLedger using LedgerCrudSqlite instead of the (existing-but-unused) AuthLedgerCrudSqlite, whose leaner store_keyset / store_promise already match the auth m001 schema and would obviate (1)–(3). Switching CRUDs requires adding several missing methods to AuthLedgerCrud (store_blinded_message, update_keyset, bump_keyset_*, balance logs) — too wide for this PR.

Test plan

  • Fresh container, no prior auth DB: migrations chain through m001 → m004 cleanly, v3 auth keyset persists, /v1/auth/blind/keysets exposes the keyset.
  • Wallet OIDC password grant against Keycloak 25 succeeds (was previously rejected with ClearAuthFailedError due to missing sub).
  • Wallet mints 3 BATs, BLS pairing verifies them, consumes them across mint / swap / receive flows.
  • No effect on non-auth ledgers: keyset_input_fee_ppk defaults to None → falls through to settings.mint_input_fee_ppk.
  • CI on this PR.
  • Postgres-backed auth DB (m004 has separate ALTER path; not tested locally).

Refs #999.

a1denvalu3 and others added 30 commits May 5, 2026 11:12
… verification

- Fixed keyset v3 derivation logic and ID generation
- Replaced additive blinding logic with BLS multiplicative blinding
- Handled backwards compatibility for DLEQ skipping and verifying
- Implemented batch BLS pairing verification for unblinded signatures
- Removed redundant dummy DLEQ generation in BLS operations
- Fixed failing unit tests and resolved type-checking union issues
fix v3 Proof.Y hash-to-curve and BlindedSignature dleq=None
@github-project-automation github-project-automation Bot moved this to Backlog in nutshell May 13, 2026
@robwoodgate robwoodgate force-pushed the fix/auth-keyset-migrations branch from c6a730a to 442caa4 Compare May 13, 2026 21:10
@robwoodgate robwoodgate changed the title fix(mint/auth): add final_expiry migration so v3 BLS keysets persist fix(mint/auth): make a fresh 0.21.0 auth mint work end-to-end May 13, 2026
@robwoodgate robwoodgate force-pushed the fix/auth-keyset-migrations branch 2 times, most recently from 9c8d3cb to b388db9 Compare May 13, 2026 21:21
@robwoodgate robwoodgate force-pushed the fix/auth-keyset-migrations branch from b388db9 to 1b2f28a Compare May 13, 2026 21:26
@a1denvalu3 a1denvalu3 changed the base branch from feature/bls12-381-v3-keyset to main May 14, 2026 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants