Every signed write strands an SDK client and an IndexedDB connection
- 主要語言
- TypeScript
- 星號
- 5
- 分支
- 28
- 平均合併
- 9 小時 50 分鐘
- 30 天內合併 PR
- 123
描述
Every signed write (send, claim, swap) rebuilds the with-options `MidenClient` and never releases the one it replaces, so a long-lived session leaks one SDK client and one IndexedDB connection per write. Same leak class as #868, which #869 fixes for the consumability read and the guardian PSWAP build; this is the signing path.
- **Symptom:** WASM client objects and `IDBDatabase` connections in the realm grow by one per signed write, without bound over a session.
- **Repro:** on mobile, or the extension service worker with the offscreen client off, run N sends or claims and count `IDBDatabase` objects in that realm (for example with the CDP leak-probe used for #868). The count grows by N.
- **Expected:** at most one signing client per realm per client replacement (trap recovery, endpoint change).
- **Impact:** slower than #868's per-lap leak (one per write, not one per 30 s), but unbounded; auto-claim makes it write-rate driven on idle wallets too.
Mechanism and sites
- `getInstanceWithOptions` (`src/lib/miden/sdk/miden-client.ts`) disposes and rebuilds on every call to re-apply options. Disposal runs `detachOrFree` -> `freeGuarded` -> `MidenClientInterface.free()` -> `MidenClient.terminate()`.
- `@miden-sdk/miden-sdk` 0.16.0: `WebClient.terminate()` only terminates a Web Worker. A `useWorker: false` client (mobile) or a client in a Worker-less realm (the MV3 service worker) releases nothing. Each build's `openDatabase` opens a new Dexie connection and replaces the registry entry without closing the previous one.
- Per-write callers: `src/lib/miden/back/miden-client-proxy.ts` (consumeNoteId, sendTransaction and siblings), `src/lib/miden/back/vault.ts`, `src/lib/miden/transaction/index.ts`.
Fix sketch
Keep one with-options client per realm per client generation, the bound #869 gives the consumability reader. The per-write options are not only a sign callback: `buildSignCallbackOptions` wraps the caller's signer, and `MidenClientCreateOptions` also carries `seed`, `insertKeyCallback` and `getKeyCallback`, fixed at client creation. So this needs a stable trampoline sign callback that forwards to a per-write signer installed under the WASM lock, plus a decision for the creation-time seed and key callbacks (likely a separate path for account creation and import). It spans the vault, the proxy, the transaction pipeline and the offscreen write path. The seed/key-callback split is the part that needs a design decision.
貢獻指南
研究方向
The leak is in `src/lib/miden/sdk/miden-client.ts` `getInstanceWithOptions`, which rebuilds the client on every signed write. Examine `MidenClientInterface.free()` and `WebClient.terminate()` in `@miden-sdk/miden-sdk` 0.16.0 to see why connections aren't released. The fix involves creating a stable client per realm, similar to the approach in #869, and spans vault, proxy, and transaction pipeline files. Start by reproducing the leak as described and tracing the client lifecycle.
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- typescript, wasm
- 領域
- backend, databases
- Issue 類型
- 缺陷
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 活躍
- 描述清晰度
- 描述清楚
- 新手友好度
- 45/100