@izi-noir/sdk 0.1.9 → 0.1.11

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.
@@ -45,7 +45,9 @@ var init_Barretenberg = __esm({
45
45
  "src/infra/provingSystems/Barretenberg.ts"() {
46
46
  "use strict";
47
47
  Barretenberg = class {
48
- async compile(noirCode) {
48
+ // Note: options parameter is accepted but not used - Barretenberg uses Noir's ACIR directly
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
+ async compile(noirCode, _options) {
49
51
  const { basePath, cleanup } = await createTempDir();
50
52
  const fm = createFileManager(basePath);
51
53
  const nargoToml = `[package]
@@ -103,6 +105,377 @@ authors = [""]
103
105
  }
104
106
  });
105
107
 
108
+ // src/infra/provingSystems/R1csBuilder.ts
109
+ var R1csBuilder;
110
+ var init_R1csBuilder = __esm({
111
+ "src/infra/provingSystems/R1csBuilder.ts"() {
112
+ "use strict";
113
+ R1csBuilder = class {
114
+ constructor(parsedCircuit) {
115
+ this.parsedCircuit = parsedCircuit;
116
+ }
117
+ constraints = [];
118
+ witnessMap = /* @__PURE__ */ new Map();
119
+ nextWitnessIdx = 1;
120
+ // w_0 = 1 is reserved
121
+ publicIndices = [];
122
+ privateIndices = [];
123
+ // BN254 scalar field modulus - 1 (for representing -1)
124
+ // Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
125
+ // -1 mod Fr = Fr - 1
126
+ NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
127
+ /**
128
+ * Build R1CS definition from the parsed circuit
129
+ */
130
+ build() {
131
+ this.registerInputs();
132
+ for (const stmt of this.parsedCircuit.statements) {
133
+ this.processStatement(stmt);
134
+ }
135
+ return {
136
+ num_witnesses: this.nextWitnessIdx,
137
+ public_inputs: this.publicIndices,
138
+ private_inputs: this.privateIndices,
139
+ constraints: this.constraints
140
+ };
141
+ }
142
+ /**
143
+ * Get the witness index for an input parameter name
144
+ */
145
+ getWitnessIndex(name) {
146
+ return this.witnessMap.get(name);
147
+ }
148
+ /**
149
+ * Register all circuit inputs as witnesses
150
+ * Public inputs come first, then private inputs
151
+ */
152
+ registerInputs() {
153
+ for (const param of this.parsedCircuit.publicParams) {
154
+ const idx = this.nextWitnessIdx++;
155
+ this.witnessMap.set(param.name, idx);
156
+ this.publicIndices.push(idx);
157
+ }
158
+ for (const param of this.parsedCircuit.privateParams) {
159
+ const idx = this.nextWitnessIdx++;
160
+ this.witnessMap.set(param.name, idx);
161
+ this.privateIndices.push(idx);
162
+ }
163
+ }
164
+ /**
165
+ * Process a single statement and generate constraints
166
+ */
167
+ processStatement(stmt) {
168
+ switch (stmt.kind) {
169
+ case "assert":
170
+ this.processAssert(stmt.condition);
171
+ break;
172
+ case "variable_declaration":
173
+ this.processVariableDecl(stmt.name, stmt.initializer);
174
+ break;
175
+ case "assignment":
176
+ this.processAssignment(stmt.target, stmt.value);
177
+ break;
178
+ case "if_statement":
179
+ for (const s of stmt.consequent) {
180
+ this.processStatement(s);
181
+ }
182
+ if (stmt.alternate) {
183
+ for (const s of stmt.alternate) {
184
+ this.processStatement(s);
185
+ }
186
+ }
187
+ break;
188
+ case "for_statement":
189
+ throw new Error(
190
+ "For loops are not yet supported in R1CS generation. Use the Barretenberg backend for complex circuits."
191
+ );
192
+ }
193
+ }
194
+ /**
195
+ * Process an assert statement
196
+ * The condition must evaluate to true for a valid proof
197
+ */
198
+ processAssert(condition) {
199
+ if (condition.kind === "binary") {
200
+ this.processBinaryAssert(condition);
201
+ } else if (condition.kind === "identifier") {
202
+ const idx = this.getOrCreateWitness(condition);
203
+ this.constraints.push({
204
+ a: [["0x1", idx]],
205
+ b: [["0x1", 0]],
206
+ // * 1
207
+ c: [["0x1", 0]]
208
+ // = 1 (w_0)
209
+ });
210
+ } else {
211
+ throw new Error(`Unsupported assert condition kind: ${condition.kind}`);
212
+ }
213
+ }
214
+ /**
215
+ * Process a binary expression in an assert
216
+ */
217
+ processBinaryAssert(expr) {
218
+ const { left, operator, right } = expr;
219
+ switch (operator) {
220
+ case "==":
221
+ this.processEquality(left, right);
222
+ break;
223
+ case "!=":
224
+ throw new Error(
225
+ "Inequality (!=) is not yet supported in R1CS. Use equality (==) instead."
226
+ );
227
+ case "+":
228
+ case "-":
229
+ case "*":
230
+ case "/":
231
+ case "%":
232
+ throw new Error(
233
+ `Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
234
+ );
235
+ case "<":
236
+ case ">":
237
+ case "<=":
238
+ case ">=":
239
+ throw new Error(
240
+ `Comparison operators (${operator}) require range proofs which are not yet supported. Use the Barretenberg backend for comparison operations.`
241
+ );
242
+ case "&":
243
+ case "|":
244
+ throw new Error(
245
+ `Logical operator ${operator} is not yet supported in R1CS.`
246
+ );
247
+ default:
248
+ throw new Error(`Unsupported operator in assert: ${operator}`);
249
+ }
250
+ }
251
+ /**
252
+ * Process an equality assertion: assert(left == right)
253
+ */
254
+ processEquality(left, right) {
255
+ if (left.kind === "binary" && left.operator === "*") {
256
+ this.processMultiplicationEquality(left.left, left.right, right);
257
+ return;
258
+ }
259
+ if (right.kind === "binary" && right.operator === "*") {
260
+ this.processMultiplicationEquality(right.left, right.right, left);
261
+ return;
262
+ }
263
+ if (left.kind === "binary" && left.operator === "+") {
264
+ this.processAdditionEquality(left.left, left.right, right);
265
+ return;
266
+ }
267
+ if (right.kind === "binary" && right.operator === "+") {
268
+ this.processAdditionEquality(right.left, right.right, left);
269
+ return;
270
+ }
271
+ if (left.kind === "binary" && left.operator === "-") {
272
+ this.processSubtractionEquality(left.left, left.right, right);
273
+ return;
274
+ }
275
+ if (right.kind === "binary" && right.operator === "-") {
276
+ this.processSubtractionEquality(right.left, right.right, left);
277
+ return;
278
+ }
279
+ const leftIdx = this.getOrCreateWitness(left);
280
+ const rightIdx = this.getOrCreateWitness(right);
281
+ this.constraints.push({
282
+ a: [
283
+ ["0x1", leftIdx],
284
+ [this.NEG_ONE, rightIdx]
285
+ ],
286
+ // a - b
287
+ b: [["0x1", 0]],
288
+ // * 1 (w_0 = 1)
289
+ c: []
290
+ // = 0
291
+ });
292
+ }
293
+ /**
294
+ * Process multiplication equality: assert(a * b == c)
295
+ * R1CS: a * b = c
296
+ */
297
+ processMultiplicationEquality(left, right, result) {
298
+ const leftIdx = this.getOrCreateWitness(left);
299
+ const rightIdx = this.getOrCreateWitness(right);
300
+ const resultIdx = this.getOrCreateWitness(result);
301
+ this.constraints.push({
302
+ a: [["0x1", leftIdx]],
303
+ b: [["0x1", rightIdx]],
304
+ c: [["0x1", resultIdx]]
305
+ });
306
+ }
307
+ /**
308
+ * Process addition equality: assert(a + b == c)
309
+ * R1CS: (a + b - c) * 1 = 0
310
+ * Which is: (a + b) * 1 = c
311
+ */
312
+ processAdditionEquality(left, right, result) {
313
+ const leftIdx = this.getOrCreateWitness(left);
314
+ const rightIdx = this.getOrCreateWitness(right);
315
+ const resultIdx = this.getOrCreateWitness(result);
316
+ this.constraints.push({
317
+ a: [
318
+ ["0x1", leftIdx],
319
+ ["0x1", rightIdx]
320
+ ],
321
+ // a + b
322
+ b: [["0x1", 0]],
323
+ // * 1
324
+ c: [["0x1", resultIdx]]
325
+ // = c
326
+ });
327
+ }
328
+ /**
329
+ * Process subtraction equality: assert(a - b == c)
330
+ * R1CS: (a - b) * 1 = c
331
+ */
332
+ processSubtractionEquality(left, right, result) {
333
+ const leftIdx = this.getOrCreateWitness(left);
334
+ const rightIdx = this.getOrCreateWitness(right);
335
+ const resultIdx = this.getOrCreateWitness(result);
336
+ this.constraints.push({
337
+ a: [
338
+ ["0x1", leftIdx],
339
+ [this.NEG_ONE, rightIdx]
340
+ ],
341
+ // a - b
342
+ b: [["0x1", 0]],
343
+ // * 1
344
+ c: [["0x1", resultIdx]]
345
+ // = c
346
+ });
347
+ }
348
+ /**
349
+ * Process a variable declaration: let x = expr
350
+ * Creates a new witness for x and adds constraint if needed
351
+ */
352
+ processVariableDecl(name, initializer) {
353
+ const varIdx = this.nextWitnessIdx++;
354
+ this.witnessMap.set(name, varIdx);
355
+ if (initializer.kind === "identifier") {
356
+ const initIdx = this.getOrCreateWitness(initializer);
357
+ this.constraints.push({
358
+ a: [
359
+ ["0x1", varIdx],
360
+ [this.NEG_ONE, initIdx]
361
+ ],
362
+ b: [["0x1", 0]],
363
+ c: []
364
+ });
365
+ } else if (initializer.kind === "literal") {
366
+ } else if (initializer.kind === "binary") {
367
+ this.processVariableInitBinary(varIdx, initializer);
368
+ } else {
369
+ throw new Error(
370
+ `Unsupported initializer kind for variable declaration: ${initializer.kind}`
371
+ );
372
+ }
373
+ }
374
+ /**
375
+ * Process a binary expression as variable initializer
376
+ */
377
+ processVariableInitBinary(varIdx, expr) {
378
+ const { left, operator, right } = expr;
379
+ const leftIdx = this.getOrCreateWitness(left);
380
+ const rightIdx = this.getOrCreateWitness(right);
381
+ switch (operator) {
382
+ case "*":
383
+ this.constraints.push({
384
+ a: [["0x1", leftIdx]],
385
+ b: [["0x1", rightIdx]],
386
+ c: [["0x1", varIdx]]
387
+ });
388
+ break;
389
+ case "+":
390
+ this.constraints.push({
391
+ a: [
392
+ ["0x1", leftIdx],
393
+ ["0x1", rightIdx]
394
+ ],
395
+ b: [["0x1", 0]],
396
+ c: [["0x1", varIdx]]
397
+ });
398
+ break;
399
+ case "-":
400
+ this.constraints.push({
401
+ a: [
402
+ ["0x1", leftIdx],
403
+ [this.NEG_ONE, rightIdx]
404
+ ],
405
+ b: [["0x1", 0]],
406
+ c: [["0x1", varIdx]]
407
+ });
408
+ break;
409
+ default:
410
+ throw new Error(
411
+ `Unsupported operator in variable initializer: ${operator}`
412
+ );
413
+ }
414
+ }
415
+ /**
416
+ * Process an assignment: x = expr
417
+ * Updates the witness mapping
418
+ */
419
+ processAssignment(target, value) {
420
+ const existingIdx = this.witnessMap.get(target);
421
+ if (existingIdx === void 0) {
422
+ throw new Error(`Assignment to undeclared variable: ${target}`);
423
+ }
424
+ if (value.kind === "identifier") {
425
+ const valueIdx = this.getOrCreateWitness(value);
426
+ this.constraints.push({
427
+ a: [
428
+ ["0x1", existingIdx],
429
+ [this.NEG_ONE, valueIdx]
430
+ ],
431
+ b: [["0x1", 0]],
432
+ c: []
433
+ });
434
+ } else if (value.kind === "binary") {
435
+ this.processVariableInitBinary(existingIdx, value);
436
+ }
437
+ }
438
+ /**
439
+ * Get or create a witness index for an expression
440
+ */
441
+ getOrCreateWitness(expr) {
442
+ if (expr.kind === "identifier") {
443
+ const existing = this.witnessMap.get(expr.name);
444
+ if (existing !== void 0) {
445
+ return existing;
446
+ }
447
+ const idx = this.nextWitnessIdx++;
448
+ this.witnessMap.set(expr.name, idx);
449
+ return idx;
450
+ }
451
+ if (expr.kind === "literal") {
452
+ const idx = this.nextWitnessIdx++;
453
+ return idx;
454
+ }
455
+ if (expr.kind === "binary") {
456
+ const idx = this.nextWitnessIdx++;
457
+ this.processVariableInitBinary(idx, expr);
458
+ return idx;
459
+ }
460
+ if (expr.kind === "unary") {
461
+ const operandIdx = this.getOrCreateWitness(expr.operand);
462
+ if (expr.operator === "-") {
463
+ const idx = this.nextWitnessIdx++;
464
+ this.constraints.push({
465
+ a: [[this.NEG_ONE, operandIdx]],
466
+ b: [["0x1", 0]],
467
+ c: [["0x1", idx]]
468
+ });
469
+ return idx;
470
+ }
471
+ throw new Error(`Unsupported unary operator: ${expr.operator}`);
472
+ }
473
+ throw new Error(`Unsupported expression kind: ${expr.kind}`);
474
+ }
475
+ };
476
+ }
477
+ });
478
+
106
479
  // src/infra/provingSystems/ArkworksWasm.ts
107
480
  var ArkworksWasm_exports = {};
108
481
  __export(ArkworksWasm_exports, {
@@ -236,6 +609,7 @@ var wasmModule, wasmInitPromise2, ArkworksWasm;
236
609
  var init_ArkworksWasm = __esm({
237
610
  "src/infra/provingSystems/ArkworksWasm.ts"() {
238
611
  "use strict";
612
+ init_R1csBuilder();
239
613
  wasmModule = null;
240
614
  wasmInitPromise2 = null;
241
615
  ArkworksWasm = class {
@@ -249,8 +623,11 @@ var init_ArkworksWasm = __esm({
249
623
  }
250
624
  /**
251
625
  * Compile Noir code to a circuit with ACIR for Groth16 proving
626
+ *
627
+ * @param noirCode - The Noir source code to compile
628
+ * @param options - Optional compilation options including ParsedCircuit for dynamic R1CS
252
629
  */
253
- async compile(noirCode) {
630
+ async compile(noirCode, options) {
254
631
  const wasm = await initWasm();
255
632
  const { basePath, cleanup } = await createTempDir2();
256
633
  const fm = createFileManager2(basePath);
@@ -275,36 +652,52 @@ authors = [""]
275
652
  throw new Error("Compilation failed: no bytecode generated");
276
653
  }
277
654
  const parameters = compiled.abi.parameters;
278
- const publicR1csIndices = [];
279
- const privateR1csIndices = [];
655
+ let r1cs;
280
656
  const witnessIndexMapping = /* @__PURE__ */ new Map();
281
- parameters.forEach((p, noirIndex) => {
282
- const r1csIndex = noirIndex + 1;
283
- witnessIndexMapping.set(noirIndex, r1csIndex);
284
- if (p.visibility === "public") {
285
- publicR1csIndices.push(r1csIndex);
286
- } else if (p.visibility === "private") {
287
- privateR1csIndices.push(r1csIndex);
288
- }
289
- });
290
- const r1cs = {
291
- num_witnesses: parameters.length + 1,
292
- // +1 for w_0
293
- public_inputs: publicR1csIndices,
294
- private_inputs: privateR1csIndices,
295
- constraints: []
296
- };
297
- if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
298
- const privateIdx = privateR1csIndices[0];
299
- const publicIdx = publicR1csIndices[0];
300
- r1cs.constraints.push({
301
- a: [["0x1", privateIdx]],
302
- // secret
303
- b: [["0x1", privateIdx]],
304
- // secret
305
- c: [["0x1", publicIdx]]
306
- // expected
657
+ if (options?.parsedCircuit) {
658
+ const builder = new R1csBuilder(options.parsedCircuit);
659
+ r1cs = builder.build();
660
+ parameters.forEach((p, noirIndex) => {
661
+ const r1csIndex = noirIndex + 1;
662
+ witnessIndexMapping.set(noirIndex, r1csIndex);
663
+ });
664
+ console.log("=== R1CS BUILDER DEBUG ===");
665
+ console.log("ParsedCircuit publicParams:", options.parsedCircuit.publicParams);
666
+ console.log("ParsedCircuit privateParams:", options.parsedCircuit.privateParams);
667
+ console.log("ParsedCircuit statements:", JSON.stringify(options.parsedCircuit.statements, null, 2));
668
+ console.log("Generated R1CS:", JSON.stringify(r1cs, null, 2));
669
+ console.log("==========================");
670
+ } else {
671
+ const publicR1csIndices = [];
672
+ const privateR1csIndices = [];
673
+ parameters.forEach((p, noirIndex) => {
674
+ const r1csIndex = noirIndex + 1;
675
+ witnessIndexMapping.set(noirIndex, r1csIndex);
676
+ if (p.visibility === "public") {
677
+ publicR1csIndices.push(r1csIndex);
678
+ } else if (p.visibility === "private") {
679
+ privateR1csIndices.push(r1csIndex);
680
+ }
307
681
  });
682
+ r1cs = {
683
+ num_witnesses: parameters.length + 1,
684
+ public_inputs: publicR1csIndices,
685
+ private_inputs: privateR1csIndices,
686
+ constraints: []
687
+ };
688
+ if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
689
+ const privateIdx = privateR1csIndices[0];
690
+ const publicIdx = publicR1csIndices[0];
691
+ r1cs.constraints.push({
692
+ a: [["0x1", privateIdx]],
693
+ b: [["0x1", privateIdx]],
694
+ c: [["0x1", publicIdx]]
695
+ });
696
+ }
697
+ console.log("=== R1CS HARDCODED DEBUG ===");
698
+ console.log("Using hardcoded R1CS pattern (no ParsedCircuit provided)");
699
+ console.log("R1CS:", JSON.stringify(r1cs, null, 2));
700
+ console.log("============================");
308
701
  }
309
702
  const r1csJson = JSON.stringify(r1cs);
310
703
  let provingKey;
@@ -321,7 +714,7 @@ authors = [""]
321
714
  }
322
715
  }
323
716
  const acirJson = JSON.stringify({
324
- functions: [{ current_witness_index: parameters.length, opcodes: [], private_parameters: privateR1csIndices, public_parameters: { witnesses: publicR1csIndices }, return_values: { witnesses: [] } }]
717
+ functions: [{ current_witness_index: parameters.length, opcodes: [], private_parameters: r1cs.private_inputs, public_parameters: { witnesses: r1cs.public_inputs }, return_values: { witnesses: [] } }]
325
718
  });
326
719
  const arkworksCircuit = {
327
720
  ...compiled,
@@ -369,6 +762,7 @@ authors = [""]
369
762
  circuit.verifyingKey = setupResult.verifying_key;
370
763
  circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
371
764
  }
765
+ const toHex = (arr) => Array.from(arr).map((b) => b.toString(16).padStart(2, "0")).join("");
372
766
  console.log("=== ARKWORKS PROVE DEBUG ===");
373
767
  console.log("Witness JSON:", witnessJson);
374
768
  console.log("R1CS JSON:", circuit.r1csJson);
@@ -377,7 +771,7 @@ authors = [""]
377
771
  console.log("Proof gnark base64 length:", proofResult.proof_gnark.length);
378
772
  const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
379
773
  console.log("Proof bytes length:", proofBytes.length);
380
- console.log("Proof bytes hex:", Buffer.from(proofBytes).toString("hex"));
774
+ console.log("Proof bytes hex:", toHex(proofBytes));
381
775
  console.log("============================");
382
776
  return {
383
777
  proof: proofBytes,
@@ -1037,16 +1431,20 @@ var IziNoir = class _IziNoir {
1037
1431
  * After compile(), the verifying key is available via `this.vk`.
1038
1432
  *
1039
1433
  * @param noirCode - The Noir source code to compile
1434
+ * @param options - Optional compilation options including ParsedCircuit for dynamic R1CS
1040
1435
  * @returns CompileResult with circuit and verifying key
1041
1436
  *
1042
1437
  * @example
1043
1438
  * ```typescript
1439
+ * // Basic usage
1044
1440
  * const { circuit, verifyingKey } = await izi.compile(noirCode);
1045
- * console.log('VK:', izi.vk); // Available immediately after compile
1441
+ *
1442
+ * // With ParsedCircuit for dynamic R1CS generation
1443
+ * const { circuit } = await izi.compile(noirCode, { parsedCircuit });
1046
1444
  * ```
1047
1445
  */
1048
- async compile(noirCode) {
1049
- this.compiledCircuit = await this.provingSystem.compile(noirCode);
1446
+ async compile(noirCode, options) {
1447
+ this.compiledCircuit = await this.provingSystem.compile(noirCode, options);
1050
1448
  const vk = await this.extractVerifyingKey(this.compiledCircuit);
1051
1449
  if (vk) {
1052
1450
  this._verifyingKey = vk;
@@ -1261,14 +1659,15 @@ var IziNoir = class _IziNoir {
1261
1659
  const connection = new Connection(networkConfig.rpcUrl, "confirmed");
1262
1660
  const vkKeypair = Keypair.generate();
1263
1661
  const authority = wallet.publicKey;
1662
+ const toHex = (arr) => Array.from(arr).map((b) => b.toString(16).padStart(2, "0")).join("");
1264
1663
  console.log("=== DEPLOY VK DEBUG ===");
1265
1664
  console.log("VK nrPublicInputs:", proofData.verifyingKey.nrPublicInputs);
1266
1665
  console.log("VK bytes length:", proofData.verifyingKey.bytes.length);
1267
- console.log("VK bytes (first 64 - alpha_g1):", Buffer2.from(proofData.verifyingKey.bytes.slice(0, 64)).toString("hex"));
1268
- console.log("VK bytes (64-192 - beta_g2):", Buffer2.from(proofData.verifyingKey.bytes.slice(64, 192)).toString("hex"));
1269
- console.log("VK bytes (192-320 - gamma_g2):", Buffer2.from(proofData.verifyingKey.bytes.slice(192, 320)).toString("hex"));
1270
- console.log("VK bytes (320-448 - delta_g2):", Buffer2.from(proofData.verifyingKey.bytes.slice(320, 448)).toString("hex"));
1271
- console.log("VK bytes (448+ - k elements):", Buffer2.from(proofData.verifyingKey.bytes.slice(448)).toString("hex"));
1666
+ console.log("VK bytes (first 64 - alpha_g1):", toHex(proofData.verifyingKey.bytes.slice(0, 64)));
1667
+ console.log("VK bytes (64-192 - beta_g2):", toHex(proofData.verifyingKey.bytes.slice(64, 192)));
1668
+ console.log("VK bytes (192-320 - gamma_g2):", toHex(proofData.verifyingKey.bytes.slice(192, 320)));
1669
+ console.log("VK bytes (320-448 - delta_g2):", toHex(proofData.verifyingKey.bytes.slice(320, 448)));
1670
+ console.log("VK bytes (448+ - k elements):", toHex(proofData.verifyingKey.bytes.slice(448)));
1272
1671
  console.log("=======================");
1273
1672
  const builder = new SolanaTransactionBuilder({
1274
1673
  programId: networkConfig.programId,
@@ -1360,16 +1759,17 @@ var IziNoir = class _IziNoir {
1360
1759
  `VK account ${vk} has invalid data (${accountInfo.data.length} bytes). Expected at least 8 bytes for a valid account.`
1361
1760
  );
1362
1761
  }
1762
+ const toHex = (arr) => Array.from(arr).map((b) => b.toString(16).padStart(2, "0")).join("");
1363
1763
  console.log("=== VERIFY ON-CHAIN DEBUG ===");
1364
1764
  console.log("VK Account:", vk);
1365
1765
  console.log("VK Account data length:", accountInfo.data.length, "bytes");
1366
1766
  console.log("Proof size:", proofData.proof.bytes.length, "bytes");
1367
- console.log("Proof (first 64 bytes - A point):", Buffer2.from(proofData.proof.bytes.slice(0, 64)).toString("hex"));
1368
- console.log("Proof (bytes 64-192 - B point):", Buffer2.from(proofData.proof.bytes.slice(64, 192)).toString("hex"));
1369
- console.log("Proof (bytes 192-256 - C point):", Buffer2.from(proofData.proof.bytes.slice(192, 256)).toString("hex"));
1767
+ console.log("Proof (first 64 bytes - A point):", toHex(proofData.proof.bytes.slice(0, 64)));
1768
+ console.log("Proof (bytes 64-192 - B point):", toHex(proofData.proof.bytes.slice(64, 192)));
1769
+ console.log("Proof (bytes 192-256 - C point):", toHex(proofData.proof.bytes.slice(192, 256)));
1370
1770
  console.log("Public inputs count:", proofData.publicInputs.bytes.length);
1371
1771
  proofData.publicInputs.bytes.forEach((input, i) => {
1372
- console.log(` Public input[${i}]:`, Buffer2.from(input).toString("hex"));
1772
+ console.log(` Public input[${i}]:`, toHex(input));
1373
1773
  });
1374
1774
  console.log("Public inputs hex:", proofData.publicInputs.hex);
1375
1775
  console.log("VK nrPublicInputs:", proofData.verifyingKey.nrPublicInputs);
@@ -1,5 +1,5 @@
1
- import { I as IProvingSystem, C as CircuitPaths } from '../IProvingSystem-BpI0rmve.cjs';
2
- export { a as IziNoirConfig, P as Provider } from '../IProvingSystem-BpI0rmve.cjs';
1
+ import { I as IProvingSystem, C as CircuitPaths } from '../IProvingSystem-SfzgcbqH.cjs';
2
+ export { a as IziNoirConfig, P as Provider } from '../IProvingSystem-SfzgcbqH.cjs';
3
3
  import { P as ProofData } from '../types-CxkI04bP.cjs';
4
4
  import { CompiledCircuit, InputMap } from '@noir-lang/types';
5
5
  export { CompiledCircuit, InputMap } from '@noir-lang/types';
@@ -1,5 +1,5 @@
1
- import { I as IProvingSystem, C as CircuitPaths } from '../IProvingSystem-D0X9Rp3W.js';
2
- export { a as IziNoirConfig, P as Provider } from '../IProvingSystem-D0X9Rp3W.js';
1
+ import { I as IProvingSystem, C as CircuitPaths } from '../IProvingSystem-BKgFRl27.js';
2
+ export { a as IziNoirConfig, P as Provider } from '../IProvingSystem-BKgFRl27.js';
3
3
  import { P as ProofData } from '../types-CxkI04bP.js';
4
4
  import { CompiledCircuit, InputMap } from '@noir-lang/types';
5
5
  export { CompiledCircuit, InputMap } from '@noir-lang/types';
@@ -1,4 +1,4 @@
1
- import { b as ChainId, c as CircuitMetadata, d as ChainMetadataFor, N as Network, e as Chain, a as IziNoirConfig, I as IProvingSystem } from './IProvingSystem-D0X9Rp3W.js';
1
+ import { b as ChainId, c as CircuitMetadata, d as ChainMetadataFor, N as Network, e as Chain, a as IziNoirConfig, I as IProvingSystem, f as CompileOptions } from './IProvingSystem-BKgFRl27.js';
2
2
  import { P as ProofData, S as SolanaProofData, V as VerifyingKeyData, C as CompileResult } from './types-CxkI04bP.js';
3
3
  import { CompiledCircuit, InputMap } from '@noir-lang/types';
4
4
 
@@ -229,15 +229,19 @@ declare class IziNoir {
229
229
  * After compile(), the verifying key is available via `this.vk`.
230
230
  *
231
231
  * @param noirCode - The Noir source code to compile
232
+ * @param options - Optional compilation options including ParsedCircuit for dynamic R1CS
232
233
  * @returns CompileResult with circuit and verifying key
233
234
  *
234
235
  * @example
235
236
  * ```typescript
237
+ * // Basic usage
236
238
  * const { circuit, verifyingKey } = await izi.compile(noirCode);
237
- * console.log('VK:', izi.vk); // Available immediately after compile
239
+ *
240
+ * // With ParsedCircuit for dynamic R1CS generation
241
+ * const { circuit } = await izi.compile(noirCode, { parsedCircuit });
238
242
  * ```
239
243
  */
240
- compile(noirCode: string): Promise<CompileResult>;
244
+ compile(noirCode: string, options?: CompileOptions): Promise<CompileResult>;
241
245
  /**
242
246
  * Extract verifying key from compiled circuit.
243
247
  * Works for Arkworks circuits that have VK cached after setup.
@@ -1,4 +1,4 @@
1
- import { b as ChainId, c as CircuitMetadata, d as ChainMetadataFor, N as Network, e as Chain, a as IziNoirConfig, I as IProvingSystem } from './IProvingSystem-BpI0rmve.cjs';
1
+ import { b as ChainId, c as CircuitMetadata, d as ChainMetadataFor, N as Network, e as Chain, a as IziNoirConfig, I as IProvingSystem, f as CompileOptions } from './IProvingSystem-SfzgcbqH.cjs';
2
2
  import { P as ProofData, S as SolanaProofData, V as VerifyingKeyData, C as CompileResult } from './types-CxkI04bP.cjs';
3
3
  import { CompiledCircuit, InputMap } from '@noir-lang/types';
4
4
 
@@ -229,15 +229,19 @@ declare class IziNoir {
229
229
  * After compile(), the verifying key is available via `this.vk`.
230
230
  *
231
231
  * @param noirCode - The Noir source code to compile
232
+ * @param options - Optional compilation options including ParsedCircuit for dynamic R1CS
232
233
  * @returns CompileResult with circuit and verifying key
233
234
  *
234
235
  * @example
235
236
  * ```typescript
237
+ * // Basic usage
236
238
  * const { circuit, verifyingKey } = await izi.compile(noirCode);
237
- * console.log('VK:', izi.vk); // Available immediately after compile
239
+ *
240
+ * // With ParsedCircuit for dynamic R1CS generation
241
+ * const { circuit } = await izi.compile(noirCode, { parsedCircuit });
238
242
  * ```
239
243
  */
240
- compile(noirCode: string): Promise<CompileResult>;
244
+ compile(noirCode: string, options?: CompileOptions): Promise<CompileResult>;
241
245
  /**
242
246
  * Extract verifying key from compiled circuit.
243
247
  * Works for Arkworks circuits that have VK cached after setup.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izi-noir/sdk",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Write ZK circuits in JavaScript/TypeScript, generate Noir code and proofs automatically",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",