@voter-protocol/noir-prover 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/circuits/district_membership_14.json +1 -0
  2. package/circuits/district_membership_18.json +1 -0
  3. package/circuits/district_membership_20.json +1 -0
  4. package/circuits/district_membership_22.json +1 -0
  5. package/circuits/district_membership_24.json +1 -0
  6. package/circuits/two_tree_membership_18.json +1 -0
  7. package/circuits/two_tree_membership_20.json +1 -0
  8. package/circuits/two_tree_membership_22.json +1 -0
  9. package/circuits/two_tree_membership_24.json +1 -0
  10. package/dist/district_membership_18-Breq2tlt.js +128 -0
  11. package/dist/district_membership_18-DSj7IJGE.cjs +139 -0
  12. package/dist/district_membership_20-Bu0PWpWT.js +128 -0
  13. package/dist/district_membership_20-DKRyEvX4.cjs +139 -0
  14. package/dist/district_membership_22-DlrHPQtq.js +128 -0
  15. package/dist/district_membership_22-pal861Dz.cjs +139 -0
  16. package/dist/district_membership_24-BAJ-CEhq.cjs +139 -0
  17. package/dist/district_membership_24-CM66_Yd9.js +128 -0
  18. package/dist/index.cjs +1052 -123
  19. package/dist/index.js +1041 -124
  20. package/dist/noir-prover/src/cross-origin-isolation.d.ts +1 -0
  21. package/dist/noir-prover/src/cross-origin-isolation.d.ts.map +1 -0
  22. package/dist/noir-prover/src/fixtures.d.ts +82 -0
  23. package/dist/noir-prover/src/fixtures.d.ts.map +1 -0
  24. package/dist/noir-prover/src/hash.worker.d.ts +2 -0
  25. package/dist/noir-prover/src/hash.worker.d.ts.map +1 -0
  26. package/dist/noir-prover/src/index.d.ts +10 -2
  27. package/dist/noir-prover/src/index.d.ts.map +1 -0
  28. package/dist/noir-prover/src/profiler.d.ts +74 -0
  29. package/dist/noir-prover/src/profiler.d.ts.map +1 -0
  30. package/dist/noir-prover/src/prover-e2e.test.d.ts +1 -0
  31. package/dist/noir-prover/src/prover-e2e.test.d.ts.map +1 -0
  32. package/dist/noir-prover/src/prover-orchestrator.d.ts +104 -0
  33. package/dist/noir-prover/src/prover-orchestrator.d.ts.map +1 -0
  34. package/dist/noir-prover/src/prover.d.ts +43 -1
  35. package/dist/noir-prover/src/prover.d.ts.map +1 -0
  36. package/dist/noir-prover/src/prover.test.d.ts +1 -0
  37. package/dist/noir-prover/src/prover.test.d.ts.map +1 -0
  38. package/dist/noir-prover/src/two-tree-prover.d.ts +106 -0
  39. package/dist/noir-prover/src/two-tree-prover.d.ts.map +1 -0
  40. package/dist/noir-prover/src/two-tree-prover.test.d.ts +18 -0
  41. package/dist/noir-prover/src/two-tree-prover.test.d.ts.map +1 -0
  42. package/dist/noir-prover/src/types.d.ts +289 -20
  43. package/dist/noir-prover/src/types.d.ts.map +1 -0
  44. package/dist/noir-prover/src/worker-protocol.d.ts +75 -0
  45. package/dist/noir-prover/src/worker-protocol.d.ts.map +1 -0
  46. package/dist/two_tree_membership_18-Dfr1mYE-.cjs +195 -0
  47. package/dist/two_tree_membership_18-DufFLCM8.js +184 -0
  48. package/dist/two_tree_membership_20-DhrOeOFx.js +184 -0
  49. package/dist/two_tree_membership_20-jDMJJKIC.cjs +195 -0
  50. package/dist/two_tree_membership_22-CjwYhC_e.cjs +195 -0
  51. package/dist/two_tree_membership_22-iMLJVJEK.js +184 -0
  52. package/dist/two_tree_membership_24-Br8I-xLQ.cjs +195 -0
  53. package/dist/two_tree_membership_24-Df3SNDL0.js +184 -0
  54. package/package.json +12 -8
@@ -27,3 +27,4 @@ export declare function checkCrossOriginIsolation(): {
27
27
  * Call this before initializing NoirProver.
28
28
  */
29
29
  export declare function requireCrossOriginIsolation(): void;
30
+ //# sourceMappingURL=cross-origin-isolation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-origin-isolation.d.ts","sourceRoot":"","sources":["../../../src/cross-origin-isolation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,wBAAgB,yBAAyB,IAAI;IACzC,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B,EAAE,OAAO,CAAC;IACpC,OAAO,EAAE;QACL,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;CACnB,CA2BA;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAyBlD"}
@@ -0,0 +1,82 @@
1
+ import { CircuitInputs, CircuitDepth, AuthorityLevel } from './types.js';
2
+ /**
3
+ * Reset fixtures singleton to release WASM memory
4
+ * Call this between profiler runs to prevent memory accumulation
5
+ */
6
+ export declare function resetFixtures(): void;
7
+ /**
8
+ * Compute nullifier as the circuit does internally
9
+ *
10
+ * From the new secure circuit:
11
+ * ```noir
12
+ * let nullifier = poseidon2_hash2(user_secret, action_domain);
13
+ * ```
14
+ *
15
+ * Note: This is for reference/testing only - the actual nullifier is
16
+ * computed INSIDE the circuit and returned as a public output.
17
+ *
18
+ * BA-003 FIX: Uses poseidon2Hash2() with domain separation tag to match circuit
19
+ */
20
+ export declare function computeNullifier(userSecret: string, actionDomain: string): Promise<string>;
21
+ /**
22
+ * Fixture configuration options for the new secure circuit
23
+ */
24
+ export interface FixtureOptions {
25
+ /** User's secret for nullifier derivation and leaf computation */
26
+ userSecret?: string;
27
+ /** District identifier */
28
+ districtId?: string;
29
+ /** Authority level (1-5) */
30
+ authorityLevel?: AuthorityLevel;
31
+ /** Registration salt for leaf computation */
32
+ registrationSalt?: string;
33
+ /** Action domain (replaces epochId + campaignId) */
34
+ actionDomain?: string;
35
+ /** Leaf position in tree (0 to 2^depth - 1) */
36
+ leafIndex?: number;
37
+ /** Custom merkle path siblings */
38
+ merklePath?: string[];
39
+ /**
40
+ * Circuit depth (18, 20, 22, or 24)
41
+ * Determines merkle path length and max leaf index
42
+ * Defaults to DEFAULT_CIRCUIT_DEPTH (20)
43
+ */
44
+ depth?: CircuitDepth;
45
+ }
46
+ /**
47
+ * Generate valid circuit inputs for the new secure circuit
48
+ *
49
+ * Creates inputs that WILL satisfy circuit constraints:
50
+ * - Leaf is computed from userSecret, districtId, authorityLevel, registrationSalt
51
+ * - Merkle root is computed from the leaf + path
52
+ * - Nullifier will be computed inside the circuit from userSecret + actionDomain
53
+ *
54
+ * @param options - Optional overrides for fixture values (including depth)
55
+ * @returns CircuitInputs that will pass circuit assertions
56
+ */
57
+ export declare function generateValidInputs(options?: FixtureOptions): Promise<CircuitInputs>;
58
+ /**
59
+ * Generate realistic fixtures using shadow-atlas style district data
60
+ *
61
+ * Creates a more realistic scenario:
62
+ * - District identifier based on real naming convention
63
+ * - Non-trivial merkle path (not all zeros)
64
+ * - Realistic authority level
65
+ *
66
+ * @param depth - Circuit depth (defaults to DEFAULT_CIRCUIT_DEPTH)
67
+ */
68
+ export declare function generateRealisticInputs(depth?: CircuitDepth): Promise<CircuitInputs>;
69
+ /**
70
+ * Precomputed minimal valid fixture for DEFAULT_CIRCUIT_DEPTH
71
+ * @deprecated Use getPrecomputedFixture(depth) instead for explicit depth control
72
+ */
73
+ export declare const PRECOMPUTED_FIXTURE: CircuitInputs;
74
+ /**
75
+ * Get precomputed fixture for a specific depth
76
+ * Lazily computes and caches fixtures per depth
77
+ *
78
+ * @param depth - Circuit depth (defaults to DEFAULT_CIRCUIT_DEPTH)
79
+ * @returns Precomputed CircuitInputs that satisfy circuit constraints
80
+ */
81
+ export declare function getPrecomputedFixture(depth?: CircuitDepth): Promise<CircuitInputs>;
82
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../src/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA4B9E;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAQpC;AAsHD;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAE7B,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAEtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAgDxB;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,GAAE,YAAoC,GAC1C,OAAO,CAAC,aAAa,CAAC,CAqCxB;AAqBD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,aAKjC,CAAC;AAKF;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,GAAE,YAAoC,GAC1C,OAAO,CAAC,aAAa,CAAC,CAuCxB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hash.worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.worker.d.ts","sourceRoot":"","sources":["../../../src/hash.worker.ts"],"names":[],"mappings":""}
@@ -2,7 +2,15 @@
2
2
  * @voter-protocol/noir-prover
3
3
  *
4
4
  * Browser-native ZK prover using Barretenberg/Noir backend.
5
+ *
6
+ * Public API exports for production use.
7
+ * Dev-only code (profiler, test fixtures, orchestrator) is kept internal.
5
8
  */
6
- export { NoirProver } from './prover';
7
- export type { ProverConfig, ProofResult, CircuitInputs } from './types';
9
+ export { NoirProver, getProver, getProverForDepth, resetProverSingleton, resetProverForDepth, } from './prover';
10
+ export { TwoTreeNoirProver, getTwoTreeProverForDepth, resetTwoTreeProverSingleton, resetTwoTreeProverForDepth, } from './two-tree-prover';
11
+ export type { ProverConfig, ProofResult, CircuitInputs, CircuitDepth, AuthorityLevel } from './types';
12
+ export { DEFAULT_CIRCUIT_DEPTH, validateAuthorityLevel } from './types';
13
+ export type { TwoTreeProverConfig, TwoTreeProofInput, TwoTreeProofResult, } from './types';
14
+ export { DISTRICT_SLOT_COUNT, TWO_TREE_PUBLIC_INPUT_COUNT } from './types';
8
15
  export { checkCrossOriginIsolation, requireCrossOriginIsolation } from './cross-origin-isolation';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,EACH,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,GACtB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACH,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,GAC7B,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAGxE,YAAY,EACR,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GACrB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAG3E,OAAO,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Memory and Performance Profiler for NoirProver
3
+ *
4
+ * Run this on real mobile devices to get actual memory/timing data.
5
+ *
6
+ * ARCHITECTURE (matches communique pattern):
7
+ * - Hash worker: Generates valid circuit inputs using Poseidon2 (TERMINABLE for memory)
8
+ * - Main thread: Runs NoirProver for proof generation (UltraHonkBackend internal workers)
9
+ *
10
+ * MEMORY MANAGEMENT:
11
+ * The hash worker can be TERMINATED between runs to reclaim its WASM memory.
12
+ * Main thread WASM memory cannot be reclaimed without a page refresh.
13
+ *
14
+ * USAGE:
15
+ * 1. Build and serve this in a web page
16
+ * 2. Open on real iPhone (Safari) or Android (Chrome)
17
+ * 3. Open browser DevTools (Safari Web Inspector / Chrome Remote Debug)
18
+ * 4. Call window.runProverProfile() from console
19
+ * 5. Watch memory timeline + console output
20
+ *
21
+ * Expected times for ~4K constraint circuit:
22
+ * - Desktop (8 threads): 5-15 seconds
23
+ * - Mobile (1-4 threads): 20-60 seconds
24
+ */
25
+ export declare function setQuietMode(quiet: boolean): void;
26
+ export interface ProfileResult {
27
+ device: string;
28
+ userAgent: string;
29
+ timestamp: string;
30
+ memoryBefore?: number;
31
+ memoryAfterInit?: number;
32
+ memoryAfterInputs?: number;
33
+ memoryAfterProof?: number;
34
+ memoryAfterCleanup?: number;
35
+ memoryPeak?: number;
36
+ initTimeMs: number;
37
+ inputGenTimeMs: number;
38
+ proofTimeMs: number;
39
+ cleanupTimeMs: number;
40
+ totalTimeMs: number;
41
+ threads: number;
42
+ sharedArrayBuffer: boolean;
43
+ crossOriginIsolated: boolean;
44
+ workerSupported: boolean;
45
+ proofSizeBytes?: number;
46
+ error?: string;
47
+ orchestratorReused: boolean;
48
+ }
49
+ /**
50
+ * Run full profiling suite using ProverOrchestrator
51
+ *
52
+ * This matches the communique architecture:
53
+ * - Input generation in terminable worker
54
+ * - Proof generation on main thread
55
+ *
56
+ * SINGLETON MODE: Reuses orchestrator across runs to avoid recreating UltraHonkBackend.
57
+ * Worker is still terminated between runs for memory isolation.
58
+ */
59
+ export declare function runProfile(): Promise<ProfileResult>;
60
+ /**
61
+ * Reset the profiler by destroying the shared orchestrator.
62
+ * Use this for testing or to force a fresh start.
63
+ */
64
+ export declare function resetProfiler(): Promise<void>;
65
+ /**
66
+ * Run multiple profiler iterations with shared orchestrator
67
+ *
68
+ * This demonstrates proper memory management:
69
+ * - Worker termination reclaims input generation WASM memory between runs
70
+ * - Orchestrator (including UltraHonkBackend) is reused across all runs
71
+ * - First run initializes, subsequent runs reuse
72
+ */
73
+ export declare function runProfileMultiple(iterations?: number): Promise<ProfileResult[]>;
74
+ //# sourceMappingURL=profiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../../src/profiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAiBH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGjD;AAcD,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAGlB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IAGpB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;IAGzB,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,kBAAkB,EAAE,OAAO,CAAC;CAC/B;AA6BD;;;;;;;;;GASG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAoLzD;AAED;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAcnD;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,GAAE,MAAU,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAuBzF"}
@@ -1 +1,2 @@
1
1
  export {};
2
+ //# sourceMappingURL=prover-e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prover-e2e.test.d.ts","sourceRoot":"","sources":["../../../src/prover-e2e.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ import { CircuitInputs, ProofResult } from './types';
2
+ import { GenerateInputsOptions } from './worker-protocol';
3
+ export interface OrchestratorConfig {
4
+ /** Auto-terminate worker after each proof to reclaim memory */
5
+ autoTerminate?: boolean;
6
+ /** Progress callback for proof generation */
7
+ onProgress?: (stage: string, percent: number) => void;
8
+ }
9
+ export declare class ProverOrchestrator {
10
+ private worker;
11
+ private workerReady;
12
+ private workerInitPromise;
13
+ private prover;
14
+ private proverInitPromise;
15
+ private config;
16
+ constructor(config?: OrchestratorConfig);
17
+ /**
18
+ * Initialize both main thread prover and hash worker
19
+ */
20
+ init(): Promise<void>;
21
+ /**
22
+ * Initialize only the main thread prover (for proof generation)
23
+ *
24
+ * SINGLETON PATTERN: Uses getProver() to retrieve the shared prover instance.
25
+ * The prover is initialized once at module level and reused across all orchestrators.
26
+ * This prevents memory leaks from creating multiple UltraHonkBackend instances.
27
+ */
28
+ initProver(): Promise<void>;
29
+ /**
30
+ * Initialize only the hash worker (for input generation)
31
+ */
32
+ initWorker(): Promise<void>;
33
+ /**
34
+ * Generate valid circuit inputs using Poseidon2 hashing (runs in worker)
35
+ *
36
+ * The new secure circuit computes internally:
37
+ * - leaf = hash(userSecret, districtId, authorityLevel, registrationSalt)
38
+ * - nullifier = hash(userSecret, actionDomain)
39
+ *
40
+ * This function computes:
41
+ * - merkleRoot = compute_merkle_root(computed_leaf, path, index)
42
+ */
43
+ generateInputs(options?: GenerateInputsOptions): Promise<CircuitInputs>;
44
+ /**
45
+ * Compute Merkle root from leaf + path (runs in worker)
46
+ */
47
+ computeMerkleRoot(leaf: string, merklePath: string[], leafIndex: number): Promise<string>;
48
+ /**
49
+ * Generate a ZK proof (runs on main thread)
50
+ *
51
+ * UltraHonkBackend internally creates its own Web Workers for parallelism.
52
+ * Running this inside another worker causes nested worker deadlocks.
53
+ */
54
+ prove(inputs: CircuitInputs): Promise<ProofResult>;
55
+ /**
56
+ * Full proof flow: generate inputs + prove
57
+ */
58
+ proveWithInputGeneration(options?: GenerateInputsOptions): Promise<{
59
+ inputs: CircuitInputs;
60
+ proof: ProofResult;
61
+ }>;
62
+ /**
63
+ * Terminate the hash worker to reclaim its WASM memory
64
+ *
65
+ * This is the ONLY way to reclaim WebAssembly linear memory.
66
+ * After termination, call initWorker() to create a fresh worker.
67
+ */
68
+ terminateWorker(): void;
69
+ /**
70
+ * Destroy the main thread prover
71
+ *
72
+ * NO-OP: The prover is now a singleton managed at module level.
73
+ * It should NOT be destroyed between runs to prevent memory leaks
74
+ * from recreating UltraHonkBackend instances.
75
+ *
76
+ * This method is kept for backward compatibility but does nothing.
77
+ * The singleton prover will be automatically cleaned up when the
78
+ * page/module is unloaded.
79
+ *
80
+ * @deprecated Use singleton prover pattern - no manual cleanup needed
81
+ */
82
+ destroyProver(): Promise<void>;
83
+ /**
84
+ * Full cleanup: terminate worker only
85
+ *
86
+ * SINGLETON PATTERN: Only terminates the worker to reclaim its WASM memory.
87
+ * The prover is a singleton and should not be destroyed between runs.
88
+ */
89
+ destroy(): Promise<void>;
90
+ isWorkerReady(): boolean;
91
+ isProverReady(): boolean;
92
+ /**
93
+ * Check if the orchestrator is fully initialized (both prover and worker ready)
94
+ */
95
+ isInitialized(): boolean;
96
+ getThreadCount(): number;
97
+ }
98
+ /**
99
+ * Create a prover orchestrator configured for memory-constrained environments
100
+ *
101
+ * Auto-terminates worker after each proof to prevent WASM memory accumulation.
102
+ */
103
+ export declare function createMemorySafeOrchestrator(): ProverOrchestrator;
104
+ //# sourceMappingURL=prover-orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prover-orchestrator.d.ts","sourceRoot":"","sources":["../../../src/prover-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAM5E,MAAM,WAAW,kBAAkB;IAC/B,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;AAED,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA8B;IAEvD,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,iBAAiB,CAA8B;IAEvD,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,GAAE,kBAAuB;IAW3C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B;;;;;;OAMG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAcjC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDjC;;;;;;;;;OASG;IACG,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,aAAa,CAAC;IA2BjF;;OAEG;IACG,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA+B/F;;;;;OAKG;IACG,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAiBxD;;OAEG;IACG,wBAAwB,CAC1B,OAAO,GAAE,qBAA0B,GACpC,OAAO,CAAC;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,WAAW,CAAA;KAAE,CAAC;IAczD;;;;;OAKG;IACH,eAAe,IAAI,IAAI;IAYvB;;;;;;;;;;;;OAYG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,aAAa,IAAI,OAAO;IAIxB,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB,cAAc,IAAI,MAAM;CAG3B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,kBAAkB,CAEjE"}
@@ -1,20 +1,35 @@
1
- import { ProverConfig, CircuitInputs, ProofResult } from './types';
1
+ import { ProverConfig, CircuitInputs, ProofResult, CircuitDepth } from './types';
2
2
  export declare class NoirProver {
3
3
  private backend;
4
4
  private noir;
5
5
  private config;
6
+ private threads;
7
+ private readonly depth;
6
8
  constructor(config?: ProverConfig);
7
9
  /**
8
10
  * Initialize the prover (must be called before generating proofs)
11
+ * Lazily loads the circuit for the configured depth
9
12
  */
10
13
  init(): Promise<void>;
14
+ /**
15
+ * Get the circuit depth for this prover instance
16
+ */
17
+ getDepth(): CircuitDepth;
11
18
  /**
12
19
  * Pre-warm the prover by initializing backend
13
20
  * Call this on app load to hide latency from user
14
21
  */
15
22
  warmup(): Promise<void>;
23
+ /** Maximum allowed Merkle depth (prevents DoS via oversized arrays) */
24
+ private static readonly MAX_MERKLE_DEPTH;
16
25
  /**
17
26
  * Generate a ZK proof for district membership
27
+ *
28
+ * The new secure circuit computes leaf and nullifier internally:
29
+ * - leaf = hash(userSecret, districtId, authorityLevel, registrationSalt)
30
+ * - nullifier = hash(userSecret, actionDomain)
31
+ *
32
+ * This prevents attackers from submitting arbitrary leaves or nullifiers.
18
33
  */
19
34
  prove(inputs: CircuitInputs): Promise<ProofResult>;
20
35
  /**
@@ -26,3 +41,30 @@ export declare class NoirProver {
26
41
  */
27
42
  destroy(): Promise<void>;
28
43
  }
44
+ /**
45
+ * Get or create a NoirProver instance for the specified depth
46
+ * Safe for concurrent calls - deduplicates initialization per depth
47
+ *
48
+ * @param depth - Circuit depth (18, 20, 22, or 24). Defaults to 20.
49
+ * @param config - Optional prover configuration (threads, etc.)
50
+ */
51
+ export declare function getProverForDepth(depth?: CircuitDepth, config?: Omit<ProverConfig, 'depth'>): Promise<NoirProver>;
52
+ /**
53
+ * Get or create the default NoirProver instance (depth=20)
54
+ * Backward-compatible API - equivalent to getProverForDepth(20)
55
+ *
56
+ * @param config - Optional prover configuration
57
+ * @deprecated Use getProverForDepth() for explicit depth control
58
+ */
59
+ export declare function getProver(config?: ProverConfig): Promise<NoirProver>;
60
+ /**
61
+ * Reset all singleton instances (for testing or page unload)
62
+ */
63
+ export declare function resetProverSingleton(): Promise<void>;
64
+ /**
65
+ * Reset a specific depth's singleton instance
66
+ *
67
+ * @param depth - Circuit depth to reset
68
+ */
69
+ export declare function resetProverForDepth(depth: CircuitDepth): Promise<void>;
70
+ //# sourceMappingURL=prover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prover.d.ts","sourceRoot":"","sources":["../../../src/prover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAkB,MAAM,SAAS,CAAC;AAgDtG,qBAAa,UAAU;IACnB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,MAAM,GAAE,YAAiB;IAWrC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B;;OAEG;IACH,QAAQ,IAAI,YAAY;IAIxB;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAK7B,uEAAuE;IACvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAM;IAE9C;;;;;;;;OAQG;IACG,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAsFxD;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzE;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAOjC;AASD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACnC,KAAK,GAAE,YAAoC,EAC3C,MAAM,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GACrC,OAAO,CAAC,UAAU,CAAC,CA+CrB;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAG1E;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAS1D;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5E"}
@@ -12,3 +12,4 @@
12
12
  * Full proof tests require the same noir_js version.
13
13
  */
14
14
  export {};
15
+ //# sourceMappingURL=prover.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prover.test.d.ts","sourceRoot":"","sources":["../../../src/prover.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,106 @@
1
+ import { TwoTreeProverConfig, TwoTreeProofInput, TwoTreeProofResult, CircuitDepth } from './types';
2
+ export declare class TwoTreeNoirProver {
3
+ private backend;
4
+ private noir;
5
+ private readonly threads;
6
+ private readonly depth;
7
+ constructor(config?: TwoTreeProverConfig);
8
+ /**
9
+ * Initialize the prover (must be called before generating proofs).
10
+ * Lazily loads the circuit for the configured depth.
11
+ */
12
+ init(): Promise<void>;
13
+ /**
14
+ * Get the circuit depth for this prover instance.
15
+ */
16
+ getDepth(): CircuitDepth;
17
+ /**
18
+ * Pre-warm the prover by initializing backend.
19
+ * Call this on app load to hide latency from user.
20
+ */
21
+ warmup(): Promise<void>;
22
+ /** Maximum allowed Merkle depth (prevents DoS via oversized arrays) */
23
+ private static readonly MAX_MERKLE_DEPTH;
24
+ /**
25
+ * Validate all inputs before circuit execution.
26
+ * Throws descriptive errors for any invalid input.
27
+ */
28
+ validateInputs(inputs: TwoTreeProofInput): void;
29
+ /**
30
+ * Format TypeScript inputs into the Noir circuit's expected parameter names
31
+ * and types (snake_case, hex strings, integer arrays).
32
+ *
33
+ * This is exposed as a method for testing purposes.
34
+ */
35
+ formatInputs(inputs: TwoTreeProofInput): Record<string, unknown>;
36
+ /**
37
+ * Generate a ZK proof for two-tree membership.
38
+ *
39
+ * The circuit internally verifies:
40
+ * 1. User leaf in Tree 1: hash4(user_secret, cell_id, registration_salt, authority_level)
41
+ * 2. District commitment: poseidon2_sponge_24(districts)
42
+ * 3. Cell map leaf in Tree 2: hash2(cell_id, district_commitment)
43
+ * 4. Nullifier: hash2(identity_commitment, action_domain) (NUL-001)
44
+ * 5. Authority level in [1, 5]
45
+ *
46
+ * @param inputs - All public and private inputs for the circuit
47
+ * @returns Proof bytes and public inputs as hex strings
48
+ */
49
+ generateProof(inputs: TwoTreeProofInput): Promise<TwoTreeProofResult>;
50
+ /**
51
+ * Verify a two-tree membership proof.
52
+ *
53
+ * BR5-006: Validates public input count before backend verification.
54
+ * For full public input binding (matching proof outputs to expected values),
55
+ * use verifyProofWithExpectedInputs().
56
+ *
57
+ * @param proofResult - The proof result from generateProof()
58
+ * @returns true if the proof is valid
59
+ */
60
+ verifyProof(proofResult: TwoTreeProofResult): Promise<boolean>;
61
+ /**
62
+ * Verify a proof AND validate that public inputs match expected values.
63
+ *
64
+ * BR5-006 FIX: The base verifyProof() only checks that the proof is
65
+ * cryptographically valid for its public inputs. It does NOT verify that
66
+ * those inputs match what the caller intended. An attacker could substitute
67
+ * a valid proof generated for different inputs (e.g., different districts
68
+ * or a different authority level).
69
+ *
70
+ * This method binds the proof to the caller's expected values by checking:
71
+ * - user_root matches
72
+ * - cell_map_root matches
73
+ * - All 24 districts match
74
+ * - nullifier matches
75
+ * - action_domain matches
76
+ * - authority_level matches
77
+ *
78
+ * @param proofResult - The proof from generateProof()
79
+ * @param expectedInputs - The original inputs used for proof generation
80
+ * @returns true if proof is valid AND public inputs match expectations
81
+ */
82
+ verifyProofWithExpectedInputs(proofResult: TwoTreeProofResult, expectedInputs: TwoTreeProofInput): Promise<boolean>;
83
+ /**
84
+ * Clean up resources (WASM memory, web workers).
85
+ */
86
+ destroy(): Promise<void>;
87
+ }
88
+ /**
89
+ * Get or create a TwoTreeNoirProver instance for the specified depth.
90
+ * Safe for concurrent calls - deduplicates initialization per depth.
91
+ *
92
+ * @param depth - Circuit depth (18, 20, 22, or 24). Defaults to 20.
93
+ * @param config - Optional prover configuration (threads, etc.)
94
+ */
95
+ export declare function getTwoTreeProverForDepth(depth?: CircuitDepth, config?: Omit<TwoTreeProverConfig, 'depth'>): Promise<TwoTreeNoirProver>;
96
+ /**
97
+ * Reset all two-tree singleton instances (for testing or page unload).
98
+ */
99
+ export declare function resetTwoTreeProverSingleton(): Promise<void>;
100
+ /**
101
+ * Reset a specific depth's two-tree singleton instance.
102
+ *
103
+ * @param depth - Circuit depth to reset
104
+ */
105
+ export declare function resetTwoTreeProverForDepth(depth: CircuitDepth): Promise<void>;
106
+ //# sourceMappingURL=two-tree-prover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"two-tree-prover.d.ts","sourceRoot":"","sources":["../../../src/two-tree-prover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,OAAO,KAAK,EACR,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACf,MAAM,SAAS,CAAC;AAkHjB,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,MAAM,GAAE,mBAAwB;IAS5C;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B;;OAEG;IACH,QAAQ,IAAI,YAAY;IAIxB;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B,uEAAuE;IACvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAM;IAE9C;;;OAGG;IACH,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IA8J/C;;;;;OAKG;IACH,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IA8BhE;;;;;;;;;;;;OAYG;IACG,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAwC3E;;;;;;;;;OASG;IACG,WAAW,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBpE;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,6BAA6B,CAC/B,WAAW,EAAE,kBAAkB,EAC/B,cAAc,EAAE,iBAAiB,GAClC,OAAO,CAAC,OAAO,CAAC;IAiDnB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAOjC;AAaD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC1C,KAAK,GAAE,YAAoC,EAC3C,MAAM,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAC5C,OAAO,CAAC,iBAAiB,CAAC,CAoC5B;AAED;;GAEG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAQjE;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAOnF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * TwoTreeNoirProver Unit Tests
3
+ *
4
+ * Tests the two-tree ZK proving infrastructure with the two_tree_membership circuit.
5
+ *
6
+ * Focus areas:
7
+ * - Input validation (authority level, zero secret, array lengths, bit values)
8
+ * - Input formatting (TypeScript -> Noir snake_case mapping)
9
+ * - Circuit loading per depth
10
+ * - Public input count verification
11
+ *
12
+ * NOTE: Full proof generation requires the Barretenberg backend and is slow.
13
+ * For unit tests we focus on validation, formatting, and circuit initialization.
14
+ * The circuit execute() call (witness generation) validates circuit logic without
15
+ * needing the full proving backend.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=two-tree-prover.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"two-tree-prover.test.d.ts","sourceRoot":"","sources":["../../../src/two-tree-prover.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}