@fluxpointstudios/orynq-sdk-midnight-prover 0.1.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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +78 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +89 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/linking/cardano-anchor-link.d.ts +250 -0
  7. package/dist/linking/cardano-anchor-link.d.ts.map +1 -0
  8. package/dist/linking/cardano-anchor-link.js +447 -0
  9. package/dist/linking/cardano-anchor-link.js.map +1 -0
  10. package/dist/linking/index.d.ts +33 -0
  11. package/dist/linking/index.d.ts.map +1 -0
  12. package/dist/linking/index.js +31 -0
  13. package/dist/linking/index.js.map +1 -0
  14. package/dist/linking/proof-publication.d.ts +217 -0
  15. package/dist/linking/proof-publication.d.ts.map +1 -0
  16. package/dist/linking/proof-publication.js +385 -0
  17. package/dist/linking/proof-publication.js.map +1 -0
  18. package/dist/midnight/index.d.ts +30 -0
  19. package/dist/midnight/index.d.ts.map +1 -0
  20. package/dist/midnight/index.js +27 -0
  21. package/dist/midnight/index.js.map +1 -0
  22. package/dist/midnight/proof-server-client.d.ts +236 -0
  23. package/dist/midnight/proof-server-client.d.ts.map +1 -0
  24. package/dist/midnight/proof-server-client.js +422 -0
  25. package/dist/midnight/proof-server-client.js.map +1 -0
  26. package/dist/midnight/public-inputs.d.ts +134 -0
  27. package/dist/midnight/public-inputs.d.ts.map +1 -0
  28. package/dist/midnight/public-inputs.js +338 -0
  29. package/dist/midnight/public-inputs.js.map +1 -0
  30. package/dist/midnight/witness-builder.d.ts +119 -0
  31. package/dist/midnight/witness-builder.d.ts.map +1 -0
  32. package/dist/midnight/witness-builder.js +238 -0
  33. package/dist/midnight/witness-builder.js.map +1 -0
  34. package/dist/proofs/hash-chain-proof.d.ts +171 -0
  35. package/dist/proofs/hash-chain-proof.d.ts.map +1 -0
  36. package/dist/proofs/hash-chain-proof.js +437 -0
  37. package/dist/proofs/hash-chain-proof.js.map +1 -0
  38. package/dist/proofs/index.d.ts +35 -0
  39. package/dist/proofs/index.d.ts.map +1 -0
  40. package/dist/proofs/index.js +34 -0
  41. package/dist/proofs/index.js.map +1 -0
  42. package/dist/proofs/policy-compliance-proof.d.ts +165 -0
  43. package/dist/proofs/policy-compliance-proof.d.ts.map +1 -0
  44. package/dist/proofs/policy-compliance-proof.js +514 -0
  45. package/dist/proofs/policy-compliance-proof.js.map +1 -0
  46. package/dist/proofs/selective-disclosure.d.ts +213 -0
  47. package/dist/proofs/selective-disclosure.d.ts.map +1 -0
  48. package/dist/proofs/selective-disclosure.js +629 -0
  49. package/dist/proofs/selective-disclosure.js.map +1 -0
  50. package/dist/prover-interface.d.ts +288 -0
  51. package/dist/prover-interface.d.ts.map +1 -0
  52. package/dist/prover-interface.js +114 -0
  53. package/dist/prover-interface.js.map +1 -0
  54. package/dist/prover.d.ts +163 -0
  55. package/dist/prover.d.ts.map +1 -0
  56. package/dist/prover.js +417 -0
  57. package/dist/prover.js.map +1 -0
  58. package/dist/types.d.ts +410 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +128 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +59 -0
  63. package/src/__tests__/hash-chain-proof.test.ts +709 -0
  64. package/src/__tests__/midnight-prover.test.ts +716 -0
  65. package/src/__tests__/policy-compliance.test.ts +567 -0
  66. package/src/__tests__/proof-publication.test.ts +644 -0
  67. package/src/__tests__/selective-disclosure.test.ts +921 -0
  68. package/src/index.ts +260 -0
  69. package/src/linking/cardano-anchor-link.ts +682 -0
  70. package/src/linking/index.ts +58 -0
  71. package/src/linking/proof-publication.ts +557 -0
  72. package/src/midnight/index.ts +73 -0
  73. package/src/midnight/proof-server-client.ts +595 -0
  74. package/src/midnight/public-inputs.ts +590 -0
  75. package/src/midnight/witness-builder.ts +341 -0
  76. package/src/proofs/hash-chain-proof.ts +610 -0
  77. package/src/proofs/index.ts +77 -0
  78. package/src/proofs/policy-compliance-proof.ts +717 -0
  79. package/src/proofs/selective-disclosure.ts +839 -0
  80. package/src/prover-interface.ts +410 -0
  81. package/src/prover.ts +537 -0
  82. package/src/types.ts +551 -0
package/src/prover.ts ADDED
@@ -0,0 +1,537 @@
1
+ /**
2
+ * @fileoverview Default implementation of the MidnightProver interface.
3
+ *
4
+ * Location: packages/midnight-prover/src/prover.ts
5
+ *
6
+ * Summary:
7
+ * This module implements the DefaultMidnightProver class which provides a complete
8
+ * implementation of the MidnightProver interface. It coordinates all proof types
9
+ * (hash-chain, policy, disclosure, attestation, inference), manages connection
10
+ * lifecycle, and handles proof publication.
11
+ *
12
+ * Usage:
13
+ * - Primary entry point for ZK proof generation in the PoI system
14
+ * - Coordinates individual provers from src/proofs/
15
+ * - Manages connection to the Midnight proof server
16
+ * - Handles proof publication and verification
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { createMidnightProver } from './prover.js';
21
+ *
22
+ * const prover = createMidnightProver({ debug: true });
23
+ *
24
+ * await prover.connect({
25
+ * proofServerUrl: 'https://proof.midnight.network',
26
+ * timeout: 300000,
27
+ * retries: 3,
28
+ * });
29
+ *
30
+ * const proof = await prover.proveHashChain(input);
31
+ * const result = await prover.publish(proof);
32
+ *
33
+ * await prover.disconnect();
34
+ * ```
35
+ */
36
+
37
+ import type {
38
+ ProofServerConfig,
39
+ HashChainInput,
40
+ HashChainProof,
41
+ PolicyInput,
42
+ PolicyProof,
43
+ AttestationInput,
44
+ AttestationProof,
45
+ DisclosureInput,
46
+ DisclosureProof,
47
+ InferenceInput,
48
+ InferenceProof,
49
+ AnyProof,
50
+ PublicationResult,
51
+ ProofVerificationResult,
52
+ } from "./types.js";
53
+
54
+ import {
55
+ MidnightProverError,
56
+ MidnightProverException,
57
+ } from "./types.js";
58
+
59
+ import {
60
+ AbstractMidnightProver,
61
+ type CreateMidnightProverOptions,
62
+ proverRegistry,
63
+ } from "./prover-interface.js";
64
+
65
+ import { HashChainProver } from "./proofs/hash-chain-proof.js";
66
+ import { PolicyComplianceProver } from "./proofs/policy-compliance-proof.js";
67
+ import { SelectiveDisclosureProver } from "./proofs/selective-disclosure.js";
68
+ import { ProofPublisher } from "./linking/proof-publication.js";
69
+ import { ProofServerClient } from "./midnight/proof-server-client.js";
70
+
71
+ // =============================================================================
72
+ // DEFAULT MIDNIGHT PROVER
73
+ // =============================================================================
74
+
75
+ /**
76
+ * DefaultMidnightProver provides a complete implementation of the MidnightProver interface.
77
+ *
78
+ * This class:
79
+ * - Coordinates all proof types (hash-chain, policy, disclosure)
80
+ * - Manages connection lifecycle with the Midnight proof server
81
+ * - Handles proof publication and verification
82
+ * - Uses individual provers from src/proofs/ for specific proof types
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const prover = new DefaultMidnightProver({ debug: true });
87
+ *
88
+ * await prover.connect({
89
+ * proofServerUrl: 'https://proof.midnight.network',
90
+ * apiKey: process.env.MIDNIGHT_API_KEY,
91
+ * timeout: 300000,
92
+ * retries: 3,
93
+ * });
94
+ *
95
+ * try {
96
+ * // Generate proofs
97
+ * const hashChainProof = await prover.proveHashChain(input);
98
+ * const policyProof = await prover.provePolicyCompliance(policyInput);
99
+ *
100
+ * // Publish to network
101
+ * const result = await prover.publish(hashChainProof);
102
+ * console.log('Published:', result.midnightTxHash);
103
+ * } finally {
104
+ * await prover.disconnect();
105
+ * }
106
+ * ```
107
+ */
108
+ export class DefaultMidnightProver extends AbstractMidnightProver {
109
+ private readonly options: Required<CreateMidnightProverOptions>;
110
+
111
+ // Individual provers
112
+ private hashChainProver: HashChainProver;
113
+ private policyProver: PolicyComplianceProver;
114
+ private disclosureProver: SelectiveDisclosureProver;
115
+
116
+ // Network clients
117
+ private proofServerClient: ProofServerClient;
118
+ private proofPublisher: ProofPublisher;
119
+
120
+ // Published proofs cache
121
+ private readonly publishedProofs = new Map<string, AnyProof>();
122
+
123
+ /**
124
+ * Create a new DefaultMidnightProver instance.
125
+ *
126
+ * @param options - Configuration options
127
+ */
128
+ constructor(options: CreateMidnightProverOptions = {}) {
129
+ super();
130
+
131
+ this.options = {
132
+ debug: options.debug ?? false,
133
+ circuitsDir: options.circuitsDir ?? "./circuits",
134
+ enableInference: options.enableInference ?? false,
135
+ };
136
+
137
+ // Initialize individual provers
138
+ this.hashChainProver = new HashChainProver({
139
+ debug: this.options.debug,
140
+ simulatedProvingTimeMs: 50,
141
+ });
142
+
143
+ this.policyProver = new PolicyComplianceProver({
144
+ debug: this.options.debug,
145
+ });
146
+
147
+ this.disclosureProver = new SelectiveDisclosureProver({
148
+ debug: this.options.debug,
149
+ includeSpanData: true,
150
+ includeEventData: true,
151
+ });
152
+
153
+ // Initialize network clients
154
+ this.proofServerClient = new ProofServerClient({
155
+ debug: this.options.debug,
156
+ simulatedProvingTimeMs: 50,
157
+ });
158
+
159
+ this.proofPublisher = new ProofPublisher({
160
+ debug: this.options.debug,
161
+ maxRetries: 3,
162
+ pollIntervalMs: 1000, // Faster polling for tests
163
+ });
164
+ }
165
+
166
+ // ===========================================================================
167
+ // CONNECTION MANAGEMENT
168
+ // ===========================================================================
169
+
170
+ /**
171
+ * Connect to the Midnight proof server.
172
+ */
173
+ protected async doConnect(config: ProofServerConfig): Promise<void> {
174
+ this.debug(`Connecting to proof server at ${config.proofServerUrl}...`);
175
+
176
+ try {
177
+ // Connect proof server client
178
+ await this.proofServerClient.connect(config);
179
+
180
+ // Connect proof publisher
181
+ await this.proofPublisher.connect(config);
182
+
183
+ this.debug("Connected successfully");
184
+ } catch (error) {
185
+ // Disconnect any partially connected components
186
+ await this.doDisconnect();
187
+
188
+ if (error instanceof MidnightProverException) {
189
+ throw error;
190
+ }
191
+ throw new MidnightProverException(
192
+ MidnightProverError.CONNECTION_FAILED,
193
+ `Failed to connect: ${String(error)}`,
194
+ error instanceof Error ? error : undefined
195
+ );
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Disconnect from the proof server.
201
+ */
202
+ protected async doDisconnect(): Promise<void> {
203
+ this.debug("Disconnecting...");
204
+
205
+ // Disconnect components (ignore errors during cleanup)
206
+ try {
207
+ await this.proofServerClient.disconnect();
208
+ } catch {
209
+ // Ignore disconnect errors
210
+ }
211
+
212
+ try {
213
+ await this.proofPublisher.disconnect();
214
+ } catch {
215
+ // Ignore disconnect errors
216
+ }
217
+
218
+ this.debug("Disconnected");
219
+ }
220
+
221
+ // ===========================================================================
222
+ // PROOF GENERATION
223
+ // ===========================================================================
224
+
225
+ /**
226
+ * Generate a hash-chain validity proof.
227
+ */
228
+ async proveHashChain(input: HashChainInput): Promise<HashChainProof> {
229
+ this.ensureConnected();
230
+ this.debug(`Generating hash-chain proof for ${input.events.length} events`);
231
+
232
+ try {
233
+ const proof = await this.hashChainProver.generateProof(input);
234
+ this.debug(`Hash-chain proof generated: ${proof.proofId}`);
235
+ return proof;
236
+ } catch (error) {
237
+ if (error instanceof MidnightProverException) {
238
+ throw error;
239
+ }
240
+ throw new MidnightProverException(
241
+ MidnightProverError.PROOF_GENERATION_FAILED,
242
+ `Hash-chain proof generation failed: ${String(error)}`,
243
+ error instanceof Error ? error : undefined
244
+ );
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Generate a policy compliance proof.
250
+ */
251
+ async provePolicyCompliance(input: PolicyInput): Promise<PolicyProof> {
252
+ this.ensureConnected();
253
+ this.debug(`Generating policy compliance proof for policy ${input.policy.id}`);
254
+
255
+ try {
256
+ const proof = await this.policyProver.generateProof(input);
257
+ this.debug(`Policy proof generated: ${proof.proofId}`);
258
+ return proof;
259
+ } catch (error) {
260
+ if (error instanceof MidnightProverException) {
261
+ throw error;
262
+ }
263
+ throw new MidnightProverException(
264
+ MidnightProverError.PROOF_GENERATION_FAILED,
265
+ `Policy compliance proof generation failed: ${String(error)}`,
266
+ error instanceof Error ? error : undefined
267
+ );
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Generate an attestation validity proof.
273
+ *
274
+ * Note: Attestation proof generation is not yet implemented.
275
+ * This method throws a not-implemented error.
276
+ */
277
+ async proveAttestation(_input: AttestationInput): Promise<AttestationProof> {
278
+ this.ensureConnected();
279
+ this.debug("Attestation proofs not yet implemented");
280
+
281
+ throw new MidnightProverException(
282
+ MidnightProverError.CIRCUIT_NOT_FOUND,
283
+ "Attestation proof generation is not yet implemented"
284
+ );
285
+ }
286
+
287
+ /**
288
+ * Generate a selective disclosure proof.
289
+ */
290
+ async proveSelectiveDisclosure(input: DisclosureInput): Promise<DisclosureProof> {
291
+ this.ensureConnected();
292
+ this.debug(`Generating selective disclosure proof for span ${input.spanId}`);
293
+
294
+ try {
295
+ const proof = await this.disclosureProver.generateProof(input);
296
+ this.debug(`Disclosure proof generated: ${proof.proofId}`);
297
+ return proof;
298
+ } catch (error) {
299
+ if (error instanceof MidnightProverException) {
300
+ throw error;
301
+ }
302
+ throw new MidnightProverException(
303
+ MidnightProverError.PROOF_GENERATION_FAILED,
304
+ `Selective disclosure proof generation failed: ${String(error)}`,
305
+ error instanceof Error ? error : undefined
306
+ );
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Generate a zkML inference proof.
312
+ *
313
+ * WARNING: zkML proofs are extremely expensive and not yet supported.
314
+ * This method throws a not-implemented error unless enableInference is true.
315
+ */
316
+ proveInference(_input: InferenceInput): Promise<InferenceProof> {
317
+ this.ensureConnected();
318
+
319
+ if (!this.options.enableInference) {
320
+ throw new MidnightProverException(
321
+ MidnightProverError.CIRCUIT_NOT_FOUND,
322
+ "zkML inference proofs are disabled. Enable with { enableInference: true }"
323
+ );
324
+ }
325
+
326
+ // Even with enableInference, actual zkML is not yet implemented
327
+ throw new MidnightProverException(
328
+ MidnightProverError.CIRCUIT_NOT_FOUND,
329
+ "zkML inference proofs are not yet implemented"
330
+ );
331
+ }
332
+
333
+ // ===========================================================================
334
+ // PUBLICATION
335
+ // ===========================================================================
336
+
337
+ /**
338
+ * Publish a proof to the Midnight network.
339
+ */
340
+ async publish(proof: AnyProof): Promise<PublicationResult> {
341
+ this.ensureConnected();
342
+ this.debug(`Publishing proof: ${proof.proofId}`);
343
+
344
+ try {
345
+ const result = await this.proofPublisher.publish(proof);
346
+
347
+ // Cache the published proof
348
+ this.publishedProofs.set(proof.proofId, proof);
349
+
350
+ this.debug(`Proof published: ${result.midnightTxHash}`);
351
+ return result;
352
+ } catch (error) {
353
+ if (error instanceof MidnightProverException) {
354
+ throw error;
355
+ }
356
+ throw new MidnightProverException(
357
+ MidnightProverError.PUBLICATION_FAILED,
358
+ `Proof publication failed: ${String(error)}`,
359
+ error instanceof Error ? error : undefined
360
+ );
361
+ }
362
+ }
363
+
364
+ // ===========================================================================
365
+ // VERIFICATION
366
+ // ===========================================================================
367
+
368
+ /**
369
+ * Verify a proof locally.
370
+ */
371
+ async verify(proof: AnyProof): Promise<ProofVerificationResult> {
372
+ this.debug(`Verifying proof: ${proof.proofId}`);
373
+
374
+ const errors: string[] = [];
375
+ const warnings: string[] = [];
376
+
377
+ try {
378
+ // Verify based on proof type
379
+ let valid = false;
380
+
381
+ switch (proof.proofType) {
382
+ case "hash-chain":
383
+ valid = await this.hashChainProver.verifyProof(proof as HashChainProof);
384
+ break;
385
+
386
+ case "policy-compliance":
387
+ valid = await this.policyProver.verifyProof(proof as PolicyProof);
388
+ break;
389
+
390
+ case "selective-disclosure":
391
+ valid = await this.disclosureProver.verifyProof(proof as DisclosureProof);
392
+ break;
393
+
394
+ case "attestation-valid":
395
+ warnings.push("Attestation proof verification not yet implemented");
396
+ valid = false;
397
+ break;
398
+
399
+ case "zkml-inference":
400
+ warnings.push("zkML inference proof verification not yet implemented");
401
+ valid = false;
402
+ break;
403
+
404
+ default: {
405
+ const unknownProof = proof as { proofType: string };
406
+ errors.push(`Unknown proof type: ${unknownProof.proofType}`);
407
+ valid = false;
408
+ }
409
+ }
410
+
411
+ const result: ProofVerificationResult = {
412
+ valid,
413
+ proofType: proof.proofType,
414
+ publicInputs: this.extractPublicInputs(proof),
415
+ errors,
416
+ warnings,
417
+ verifiedAt: new Date().toISOString(),
418
+ };
419
+
420
+ this.debug(`Verification result: ${valid ? "VALID" : "INVALID"}`);
421
+
422
+ return result;
423
+ } catch (error) {
424
+ errors.push(`Verification error: ${String(error)}`);
425
+
426
+ return {
427
+ valid: false,
428
+ proofType: proof.proofType,
429
+ publicInputs: {},
430
+ errors,
431
+ warnings,
432
+ verifiedAt: new Date().toISOString(),
433
+ };
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Fetch a proof from the Midnight network by ID.
439
+ */
440
+ async fetchProof(proofId: string): Promise<AnyProof | undefined> {
441
+ this.ensureConnected();
442
+ this.debug(`Fetching proof: ${proofId}`);
443
+
444
+ // Check local cache first
445
+ const cached = this.publishedProofs.get(proofId);
446
+ if (cached) {
447
+ this.debug("Proof found in cache");
448
+ return cached;
449
+ }
450
+
451
+ // In a real implementation, this would query the Midnight network
452
+ // For now, return undefined (not found)
453
+ this.debug("Proof not found");
454
+ return undefined;
455
+ }
456
+
457
+ /**
458
+ * Check if a proof has been published to Midnight.
459
+ */
460
+ async isPublished(proofId: string): Promise<boolean> {
461
+ this.ensureConnected();
462
+
463
+ // Check publisher's status
464
+ const status = await this.proofPublisher.getProofStatus(proofId);
465
+ return status.status === "confirmed" || status.status === "pending";
466
+ }
467
+
468
+ // ===========================================================================
469
+ // UTILITY METHODS
470
+ // ===========================================================================
471
+
472
+ /**
473
+ * Get the genesis hash for hash-chain proofs.
474
+ */
475
+ async getGenesisHash(): Promise<string> {
476
+ return this.hashChainProver.getGenesisHash();
477
+ }
478
+
479
+ /**
480
+ * Wait for a proof to be confirmed on the network.
481
+ *
482
+ * @param proofId - Proof identifier
483
+ * @param timeoutMs - Maximum wait time (default: 5 minutes)
484
+ * @returns True if confirmed, false if timeout
485
+ */
486
+ async waitForConfirmation(
487
+ proofId: string,
488
+ timeoutMs?: number
489
+ ): Promise<boolean> {
490
+ this.ensureConnected();
491
+ return this.proofPublisher.waitForConfirmation(proofId, timeoutMs);
492
+ }
493
+
494
+ // ===========================================================================
495
+ // PRIVATE METHODS
496
+ // ===========================================================================
497
+
498
+ /**
499
+ * Extract public inputs from a proof for verification result.
500
+ */
501
+ private extractPublicInputs(proof: AnyProof): Record<string, unknown> {
502
+ const anyProof = proof as unknown as { publicInputs?: Record<string, unknown> };
503
+ return anyProof.publicInputs ?? {};
504
+ }
505
+
506
+ /**
507
+ * Debug logging helper.
508
+ */
509
+ private debug(message: string): void {
510
+ if (this.options.debug) {
511
+ console.log(`[DefaultMidnightProver] ${message}`);
512
+ }
513
+ }
514
+ }
515
+
516
+ // =============================================================================
517
+ // FACTORY FUNCTION
518
+ // =============================================================================
519
+
520
+ /**
521
+ * Create a new DefaultMidnightProver instance.
522
+ *
523
+ * @param options - Configuration options
524
+ * @returns New DefaultMidnightProver instance
525
+ */
526
+ export function createMidnightProver(
527
+ options?: CreateMidnightProverOptions
528
+ ): DefaultMidnightProver {
529
+ return new DefaultMidnightProver(options);
530
+ }
531
+
532
+ // =============================================================================
533
+ // REGISTER DEFAULT PROVER
534
+ // =============================================================================
535
+
536
+ // Register the default prover in the global registry
537
+ proverRegistry.register("default", () => new DefaultMidnightProver());