feat: fully in-browser RS256 proving via multi-threaded WASM#20
Open
feat: fully in-browser RS256 proving via multi-threaded WASM#20
Conversation
5 tasks
0f3fa18 to
06a0693
Compare
Separate Rust crate using the 0xVikasRushi/Spartan2 fork (openac-sdk branch) which compiles to wasm32-unknown-unknown. Supports RS256 circuit with witness-only proving path for browser use. Key: Rs256Circuit with 19 public inputs, synthesize_witness_only fallback when R1CS is unavailable in WASM, CLI for native key generation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add wasm-bindgen-rayon + rayon deps for Web Worker thread pool - Export init_thread_pool for JS-side thread pool initialization - Add load_rs256_pk() to deserialize 744MB PK into WASM memory once - Add prove_rs256() and verify_rs256() for single-circuit RS256 flow - Configure .cargo/config.toml with atomics, shared-memory, 4GB max memory - Update wasm-bridge.ts with initWithModule(), loadKeys(), precomputeFromWitness() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Vite + TypeScript browser demo with 4-step pipeline: 1. Load certificate input (test data) 2. Generate witness (circom WASM in browser) 3. Prove RS256 circuit (multi-threaded Spartan2 WASM) 4. Verify proof (Spartan2 WASM) Uses SharedArrayBuffer + Web Workers for parallel proving. COOP/COEP headers configured for cross-origin isolation. scripts/copy-assets.sh handles WASM artifact setup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add circom circuit sources and compilation config for jwt (ES256) and show circuits, used by the witness calculator in browser. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This PR focuses on RS256 in-browser proving. Remove all ES256/ECDSA circuit definitions, show/prepare circuit implementations, and related WASM bindings that are not needed for the RS256 workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…go features Switch ecdsa-spartan2 to the WASM-compatible Spartan2 fork (0xVikasRushi/Spartan2 branch openac-sdk) and gate native-only dependencies behind a "native" cargo feature. This eliminates the duplicate ecdsa-spartan2-jwt crate while supporting both native and WASM builds from a single crate. - Add "native" feature (default) gating witnesscalc, x509, rsa, memmap2, etc. - Add synthesize_witness_only() and with_witness() for WASM proving path - Add CircuitSize enum and witness-only R1CS fallback - Update mobile and WASM consumers to use the consolidated crate - Delete ecdsa-spartan2-jwt/ entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verifies the full WASM + web pipeline compiles: circom circuit compilation, Rust WASM bindings build (nightly + wasm-bindgen), and Vite/TypeScript web app build. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
wasm-bindgen-rayon requires imported shared memory. Without --import-memory, the WASM binary exports memory instead, causing wasm-bindgen to panic: assertion failed: mem.import.is_some() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When using --import-memory with -Z build-std, wasm-bindgen needs __wasm_init_tls and related TLS/stack symbols to be explicitly exported for thread pool initialization. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The generated openac_wasm.js imports workerHelpers.js from a relative ./snippets/ path. The CI step was only copying individual files from pkg/, missing the snippets/ directory entirely, causing Vite to fail. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ocal copy The web build and local dev setup now fetch ecdsa-spartan2-keys.zip from the latest GitHub release when local keys are unavailable. Also fixes the key filename mismatch (default_rs256_* → rs256_*) in pipeline.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The wasm-bindgen-rayon workerHelpers.js uses import('../../..') to resolve
back to the package root. Without a package.json in src/wasm/, Vite cannot
resolve the bare directory import, causing the build to fail.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
wasm-bindgen (unlike wasm-pack) does not generate package.json, so the
CI artifact lacks it. Generate a minimal one inline with the module entry
point needed for workerHelpers.js import('../../..') resolution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lity The workerHelpers.js uses dynamic import() which requires code-splitting, incompatible with Vite's default IIFE worker format. Setting worker format to 'es' allows the dynamic import to resolve correctly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…of downloading from GitHub release Proving keys depend on the circuit structure and should be generated per session rather than fetched from a shared release artifact. The WASM module already exports setup_rs256() which generates keys in-browser. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5655ebd to
aa036f4
Compare
Collaborator
Author
|
The refreshed implementation with separate WASM modules in We need to refactor/optimize the circuit further. e.g., |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
PR #18 implemented a hybrid approach: witness generation in browser, proving on a Node.js server (~7s). This PR explores the alternative: everything runs in the browser via multi-threaded WebAssembly.
What this PR does
ecdsa-spartan2/— Consolidated Rust crate with cargo feature gatingnativefeature (default): CLI key generation, witnesscalc-adapter, mobile supportopenac-sdk/wasm/— Multi-threaded WASM bindingswasm-bindgen-rayonintegration: rayon thread pool backed by Web Workers + SharedArrayBuffersetup_rs256(): generates proving and verifying keys at runtime in the browserload_rs256_pk(): loads serialized proving key into WASM memory for reuse across prove callsprove_rs256()/verify_rs256(): single-circuit RS256 proving and verification+atomics,+bulk-memory,+mutable-globals, 4GB max WASM memoryweb/— Vite + TypeScript browser demoscripts/copy-assets.shfor WASM artifact setup (keys optional — generated at runtime)package.jsoninsrc/wasm/for workerHelpers.jsimport('../../..')resolutionCI
web-build.yaml— End-to-end build verification pipeline with 3 jobs:rs256.wasm+witness_calculator.js)wasm-bindgen(runs in parallel with step 1)pnpm build(tsc + vite build)snippets/directory from wasm-bindgen output (containsworkerHelpers.jsneeded by wasm-bindgen-rayon for Web Worker threading)package.jsoninsrc/wasm/for worker module resolutionTriggers on changes to
web/,openac-sdk/wasm/,ecdsa-spartan2/, orcircom/circuits/.Key technical decisions
nativevs no-default) inecdsa-spartan2setup_rs256()load_rs256_pk()split fromprove_rs256()opt-level = 3over"s"build-std"es"in Vite configimport()which requires code-splitting, incompatible with default IIFE formatScreenshot
Status
Work in progress. The multi-threaded WASM initialization and proving pipeline is built and compiles, but end-to-end browser proving has not been confirmed yet — the 744MB proving key pushes WASM memory limits. Next step: test in browser after the 4GB max-memory rebuild.
How to run
Related
🤖 Generated with Claude Code