@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.
@@ -8,6 +8,377 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
+ // src/infra/provingSystems/R1csBuilder.ts
12
+ var R1csBuilder;
13
+ var init_R1csBuilder = __esm({
14
+ "src/infra/provingSystems/R1csBuilder.ts"() {
15
+ "use strict";
16
+ R1csBuilder = class {
17
+ constructor(parsedCircuit) {
18
+ this.parsedCircuit = parsedCircuit;
19
+ }
20
+ constraints = [];
21
+ witnessMap = /* @__PURE__ */ new Map();
22
+ nextWitnessIdx = 1;
23
+ // w_0 = 1 is reserved
24
+ publicIndices = [];
25
+ privateIndices = [];
26
+ // BN254 scalar field modulus - 1 (for representing -1)
27
+ // Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
28
+ // -1 mod Fr = Fr - 1
29
+ NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
30
+ /**
31
+ * Build R1CS definition from the parsed circuit
32
+ */
33
+ build() {
34
+ this.registerInputs();
35
+ for (const stmt of this.parsedCircuit.statements) {
36
+ this.processStatement(stmt);
37
+ }
38
+ return {
39
+ num_witnesses: this.nextWitnessIdx,
40
+ public_inputs: this.publicIndices,
41
+ private_inputs: this.privateIndices,
42
+ constraints: this.constraints
43
+ };
44
+ }
45
+ /**
46
+ * Get the witness index for an input parameter name
47
+ */
48
+ getWitnessIndex(name) {
49
+ return this.witnessMap.get(name);
50
+ }
51
+ /**
52
+ * Register all circuit inputs as witnesses
53
+ * Public inputs come first, then private inputs
54
+ */
55
+ registerInputs() {
56
+ for (const param of this.parsedCircuit.publicParams) {
57
+ const idx = this.nextWitnessIdx++;
58
+ this.witnessMap.set(param.name, idx);
59
+ this.publicIndices.push(idx);
60
+ }
61
+ for (const param of this.parsedCircuit.privateParams) {
62
+ const idx = this.nextWitnessIdx++;
63
+ this.witnessMap.set(param.name, idx);
64
+ this.privateIndices.push(idx);
65
+ }
66
+ }
67
+ /**
68
+ * Process a single statement and generate constraints
69
+ */
70
+ processStatement(stmt) {
71
+ switch (stmt.kind) {
72
+ case "assert":
73
+ this.processAssert(stmt.condition);
74
+ break;
75
+ case "variable_declaration":
76
+ this.processVariableDecl(stmt.name, stmt.initializer);
77
+ break;
78
+ case "assignment":
79
+ this.processAssignment(stmt.target, stmt.value);
80
+ break;
81
+ case "if_statement":
82
+ for (const s of stmt.consequent) {
83
+ this.processStatement(s);
84
+ }
85
+ if (stmt.alternate) {
86
+ for (const s of stmt.alternate) {
87
+ this.processStatement(s);
88
+ }
89
+ }
90
+ break;
91
+ case "for_statement":
92
+ throw new Error(
93
+ "For loops are not yet supported in R1CS generation. Use the Barretenberg backend for complex circuits."
94
+ );
95
+ }
96
+ }
97
+ /**
98
+ * Process an assert statement
99
+ * The condition must evaluate to true for a valid proof
100
+ */
101
+ processAssert(condition) {
102
+ if (condition.kind === "binary") {
103
+ this.processBinaryAssert(condition);
104
+ } else if (condition.kind === "identifier") {
105
+ const idx = this.getOrCreateWitness(condition);
106
+ this.constraints.push({
107
+ a: [["0x1", idx]],
108
+ b: [["0x1", 0]],
109
+ // * 1
110
+ c: [["0x1", 0]]
111
+ // = 1 (w_0)
112
+ });
113
+ } else {
114
+ throw new Error(`Unsupported assert condition kind: ${condition.kind}`);
115
+ }
116
+ }
117
+ /**
118
+ * Process a binary expression in an assert
119
+ */
120
+ processBinaryAssert(expr) {
121
+ const { left, operator, right } = expr;
122
+ switch (operator) {
123
+ case "==":
124
+ this.processEquality(left, right);
125
+ break;
126
+ case "!=":
127
+ throw new Error(
128
+ "Inequality (!=) is not yet supported in R1CS. Use equality (==) instead."
129
+ );
130
+ case "+":
131
+ case "-":
132
+ case "*":
133
+ case "/":
134
+ case "%":
135
+ throw new Error(
136
+ `Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
137
+ );
138
+ case "<":
139
+ case ">":
140
+ case "<=":
141
+ case ">=":
142
+ throw new Error(
143
+ `Comparison operators (${operator}) require range proofs which are not yet supported. Use the Barretenberg backend for comparison operations.`
144
+ );
145
+ case "&":
146
+ case "|":
147
+ throw new Error(
148
+ `Logical operator ${operator} is not yet supported in R1CS.`
149
+ );
150
+ default:
151
+ throw new Error(`Unsupported operator in assert: ${operator}`);
152
+ }
153
+ }
154
+ /**
155
+ * Process an equality assertion: assert(left == right)
156
+ */
157
+ processEquality(left, right) {
158
+ if (left.kind === "binary" && left.operator === "*") {
159
+ this.processMultiplicationEquality(left.left, left.right, right);
160
+ return;
161
+ }
162
+ if (right.kind === "binary" && right.operator === "*") {
163
+ this.processMultiplicationEquality(right.left, right.right, left);
164
+ return;
165
+ }
166
+ if (left.kind === "binary" && left.operator === "+") {
167
+ this.processAdditionEquality(left.left, left.right, right);
168
+ return;
169
+ }
170
+ if (right.kind === "binary" && right.operator === "+") {
171
+ this.processAdditionEquality(right.left, right.right, left);
172
+ return;
173
+ }
174
+ if (left.kind === "binary" && left.operator === "-") {
175
+ this.processSubtractionEquality(left.left, left.right, right);
176
+ return;
177
+ }
178
+ if (right.kind === "binary" && right.operator === "-") {
179
+ this.processSubtractionEquality(right.left, right.right, left);
180
+ return;
181
+ }
182
+ const leftIdx = this.getOrCreateWitness(left);
183
+ const rightIdx = this.getOrCreateWitness(right);
184
+ this.constraints.push({
185
+ a: [
186
+ ["0x1", leftIdx],
187
+ [this.NEG_ONE, rightIdx]
188
+ ],
189
+ // a - b
190
+ b: [["0x1", 0]],
191
+ // * 1 (w_0 = 1)
192
+ c: []
193
+ // = 0
194
+ });
195
+ }
196
+ /**
197
+ * Process multiplication equality: assert(a * b == c)
198
+ * R1CS: a * b = c
199
+ */
200
+ processMultiplicationEquality(left, right, result) {
201
+ const leftIdx = this.getOrCreateWitness(left);
202
+ const rightIdx = this.getOrCreateWitness(right);
203
+ const resultIdx = this.getOrCreateWitness(result);
204
+ this.constraints.push({
205
+ a: [["0x1", leftIdx]],
206
+ b: [["0x1", rightIdx]],
207
+ c: [["0x1", resultIdx]]
208
+ });
209
+ }
210
+ /**
211
+ * Process addition equality: assert(a + b == c)
212
+ * R1CS: (a + b - c) * 1 = 0
213
+ * Which is: (a + b) * 1 = c
214
+ */
215
+ processAdditionEquality(left, right, result) {
216
+ const leftIdx = this.getOrCreateWitness(left);
217
+ const rightIdx = this.getOrCreateWitness(right);
218
+ const resultIdx = this.getOrCreateWitness(result);
219
+ this.constraints.push({
220
+ a: [
221
+ ["0x1", leftIdx],
222
+ ["0x1", rightIdx]
223
+ ],
224
+ // a + b
225
+ b: [["0x1", 0]],
226
+ // * 1
227
+ c: [["0x1", resultIdx]]
228
+ // = c
229
+ });
230
+ }
231
+ /**
232
+ * Process subtraction equality: assert(a - b == c)
233
+ * R1CS: (a - b) * 1 = c
234
+ */
235
+ processSubtractionEquality(left, right, result) {
236
+ const leftIdx = this.getOrCreateWitness(left);
237
+ const rightIdx = this.getOrCreateWitness(right);
238
+ const resultIdx = this.getOrCreateWitness(result);
239
+ this.constraints.push({
240
+ a: [
241
+ ["0x1", leftIdx],
242
+ [this.NEG_ONE, rightIdx]
243
+ ],
244
+ // a - b
245
+ b: [["0x1", 0]],
246
+ // * 1
247
+ c: [["0x1", resultIdx]]
248
+ // = c
249
+ });
250
+ }
251
+ /**
252
+ * Process a variable declaration: let x = expr
253
+ * Creates a new witness for x and adds constraint if needed
254
+ */
255
+ processVariableDecl(name, initializer) {
256
+ const varIdx = this.nextWitnessIdx++;
257
+ this.witnessMap.set(name, varIdx);
258
+ if (initializer.kind === "identifier") {
259
+ const initIdx = this.getOrCreateWitness(initializer);
260
+ this.constraints.push({
261
+ a: [
262
+ ["0x1", varIdx],
263
+ [this.NEG_ONE, initIdx]
264
+ ],
265
+ b: [["0x1", 0]],
266
+ c: []
267
+ });
268
+ } else if (initializer.kind === "literal") {
269
+ } else if (initializer.kind === "binary") {
270
+ this.processVariableInitBinary(varIdx, initializer);
271
+ } else {
272
+ throw new Error(
273
+ `Unsupported initializer kind for variable declaration: ${initializer.kind}`
274
+ );
275
+ }
276
+ }
277
+ /**
278
+ * Process a binary expression as variable initializer
279
+ */
280
+ processVariableInitBinary(varIdx, expr) {
281
+ const { left, operator, right } = expr;
282
+ const leftIdx = this.getOrCreateWitness(left);
283
+ const rightIdx = this.getOrCreateWitness(right);
284
+ switch (operator) {
285
+ case "*":
286
+ this.constraints.push({
287
+ a: [["0x1", leftIdx]],
288
+ b: [["0x1", rightIdx]],
289
+ c: [["0x1", varIdx]]
290
+ });
291
+ break;
292
+ case "+":
293
+ this.constraints.push({
294
+ a: [
295
+ ["0x1", leftIdx],
296
+ ["0x1", rightIdx]
297
+ ],
298
+ b: [["0x1", 0]],
299
+ c: [["0x1", varIdx]]
300
+ });
301
+ break;
302
+ case "-":
303
+ this.constraints.push({
304
+ a: [
305
+ ["0x1", leftIdx],
306
+ [this.NEG_ONE, rightIdx]
307
+ ],
308
+ b: [["0x1", 0]],
309
+ c: [["0x1", varIdx]]
310
+ });
311
+ break;
312
+ default:
313
+ throw new Error(
314
+ `Unsupported operator in variable initializer: ${operator}`
315
+ );
316
+ }
317
+ }
318
+ /**
319
+ * Process an assignment: x = expr
320
+ * Updates the witness mapping
321
+ */
322
+ processAssignment(target, value) {
323
+ const existingIdx = this.witnessMap.get(target);
324
+ if (existingIdx === void 0) {
325
+ throw new Error(`Assignment to undeclared variable: ${target}`);
326
+ }
327
+ if (value.kind === "identifier") {
328
+ const valueIdx = this.getOrCreateWitness(value);
329
+ this.constraints.push({
330
+ a: [
331
+ ["0x1", existingIdx],
332
+ [this.NEG_ONE, valueIdx]
333
+ ],
334
+ b: [["0x1", 0]],
335
+ c: []
336
+ });
337
+ } else if (value.kind === "binary") {
338
+ this.processVariableInitBinary(existingIdx, value);
339
+ }
340
+ }
341
+ /**
342
+ * Get or create a witness index for an expression
343
+ */
344
+ getOrCreateWitness(expr) {
345
+ if (expr.kind === "identifier") {
346
+ const existing = this.witnessMap.get(expr.name);
347
+ if (existing !== void 0) {
348
+ return existing;
349
+ }
350
+ const idx = this.nextWitnessIdx++;
351
+ this.witnessMap.set(expr.name, idx);
352
+ return idx;
353
+ }
354
+ if (expr.kind === "literal") {
355
+ const idx = this.nextWitnessIdx++;
356
+ return idx;
357
+ }
358
+ if (expr.kind === "binary") {
359
+ const idx = this.nextWitnessIdx++;
360
+ this.processVariableInitBinary(idx, expr);
361
+ return idx;
362
+ }
363
+ if (expr.kind === "unary") {
364
+ const operandIdx = this.getOrCreateWitness(expr.operand);
365
+ if (expr.operator === "-") {
366
+ const idx = this.nextWitnessIdx++;
367
+ this.constraints.push({
368
+ a: [[this.NEG_ONE, operandIdx]],
369
+ b: [["0x1", 0]],
370
+ c: [["0x1", idx]]
371
+ });
372
+ return idx;
373
+ }
374
+ throw new Error(`Unsupported unary operator: ${expr.operator}`);
375
+ }
376
+ throw new Error(`Unsupported expression kind: ${expr.kind}`);
377
+ }
378
+ };
379
+ }
380
+ });
381
+
11
382
  // src/infra/provingSystems/ArkworksWasm.ts
12
383
  var ArkworksWasm_exports = {};
13
384
  __export(ArkworksWasm_exports, {
@@ -141,6 +512,7 @@ var wasmModule, wasmInitPromise, ArkworksWasm;
141
512
  var init_ArkworksWasm = __esm({
142
513
  "src/infra/provingSystems/ArkworksWasm.ts"() {
143
514
  "use strict";
515
+ init_R1csBuilder();
144
516
  wasmModule = null;
145
517
  wasmInitPromise = null;
146
518
  ArkworksWasm = class {
@@ -154,8 +526,11 @@ var init_ArkworksWasm = __esm({
154
526
  }
155
527
  /**
156
528
  * Compile Noir code to a circuit with ACIR for Groth16 proving
529
+ *
530
+ * @param noirCode - The Noir source code to compile
531
+ * @param options - Optional compilation options including ParsedCircuit for dynamic R1CS
157
532
  */
158
- async compile(noirCode) {
533
+ async compile(noirCode, options) {
159
534
  const wasm = await initWasm();
160
535
  const { basePath, cleanup } = await createTempDir();
161
536
  const fm = createFileManager(basePath);
@@ -180,36 +555,52 @@ authors = [""]
180
555
  throw new Error("Compilation failed: no bytecode generated");
181
556
  }
182
557
  const parameters = compiled.abi.parameters;
183
- const publicR1csIndices = [];
184
- const privateR1csIndices = [];
558
+ let r1cs;
185
559
  const witnessIndexMapping = /* @__PURE__ */ new Map();
186
- parameters.forEach((p, noirIndex) => {
187
- const r1csIndex = noirIndex + 1;
188
- witnessIndexMapping.set(noirIndex, r1csIndex);
189
- if (p.visibility === "public") {
190
- publicR1csIndices.push(r1csIndex);
191
- } else if (p.visibility === "private") {
192
- privateR1csIndices.push(r1csIndex);
193
- }
194
- });
195
- const r1cs = {
196
- num_witnesses: parameters.length + 1,
197
- // +1 for w_0
198
- public_inputs: publicR1csIndices,
199
- private_inputs: privateR1csIndices,
200
- constraints: []
201
- };
202
- if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
203
- const privateIdx = privateR1csIndices[0];
204
- const publicIdx = publicR1csIndices[0];
205
- r1cs.constraints.push({
206
- a: [["0x1", privateIdx]],
207
- // secret
208
- b: [["0x1", privateIdx]],
209
- // secret
210
- c: [["0x1", publicIdx]]
211
- // expected
560
+ if (options?.parsedCircuit) {
561
+ const builder = new R1csBuilder(options.parsedCircuit);
562
+ r1cs = builder.build();
563
+ parameters.forEach((p, noirIndex) => {
564
+ const r1csIndex = noirIndex + 1;
565
+ witnessIndexMapping.set(noirIndex, r1csIndex);
566
+ });
567
+ console.log("=== R1CS BUILDER DEBUG ===");
568
+ console.log("ParsedCircuit publicParams:", options.parsedCircuit.publicParams);
569
+ console.log("ParsedCircuit privateParams:", options.parsedCircuit.privateParams);
570
+ console.log("ParsedCircuit statements:", JSON.stringify(options.parsedCircuit.statements, null, 2));
571
+ console.log("Generated R1CS:", JSON.stringify(r1cs, null, 2));
572
+ console.log("==========================");
573
+ } else {
574
+ const publicR1csIndices = [];
575
+ const privateR1csIndices = [];
576
+ parameters.forEach((p, noirIndex) => {
577
+ const r1csIndex = noirIndex + 1;
578
+ witnessIndexMapping.set(noirIndex, r1csIndex);
579
+ if (p.visibility === "public") {
580
+ publicR1csIndices.push(r1csIndex);
581
+ } else if (p.visibility === "private") {
582
+ privateR1csIndices.push(r1csIndex);
583
+ }
212
584
  });
585
+ r1cs = {
586
+ num_witnesses: parameters.length + 1,
587
+ public_inputs: publicR1csIndices,
588
+ private_inputs: privateR1csIndices,
589
+ constraints: []
590
+ };
591
+ if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
592
+ const privateIdx = privateR1csIndices[0];
593
+ const publicIdx = publicR1csIndices[0];
594
+ r1cs.constraints.push({
595
+ a: [["0x1", privateIdx]],
596
+ b: [["0x1", privateIdx]],
597
+ c: [["0x1", publicIdx]]
598
+ });
599
+ }
600
+ console.log("=== R1CS HARDCODED DEBUG ===");
601
+ console.log("Using hardcoded R1CS pattern (no ParsedCircuit provided)");
602
+ console.log("R1CS:", JSON.stringify(r1cs, null, 2));
603
+ console.log("============================");
213
604
  }
214
605
  const r1csJson = JSON.stringify(r1cs);
215
606
  let provingKey;
@@ -226,7 +617,7 @@ authors = [""]
226
617
  }
227
618
  }
228
619
  const acirJson = JSON.stringify({
229
- functions: [{ current_witness_index: parameters.length, opcodes: [], private_parameters: privateR1csIndices, public_parameters: { witnesses: publicR1csIndices }, return_values: { witnesses: [] } }]
620
+ functions: [{ current_witness_index: parameters.length, opcodes: [], private_parameters: r1cs.private_inputs, public_parameters: { witnesses: r1cs.public_inputs }, return_values: { witnesses: [] } }]
230
621
  });
231
622
  const arkworksCircuit = {
232
623
  ...compiled,
@@ -274,6 +665,7 @@ authors = [""]
274
665
  circuit.verifyingKey = setupResult.verifying_key;
275
666
  circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
276
667
  }
668
+ const toHex = (arr) => Array.from(arr).map((b) => b.toString(16).padStart(2, "0")).join("");
277
669
  console.log("=== ARKWORKS PROVE DEBUG ===");
278
670
  console.log("Witness JSON:", witnessJson);
279
671
  console.log("R1CS JSON:", circuit.r1csJson);
@@ -282,7 +674,7 @@ authors = [""]
282
674
  console.log("Proof gnark base64 length:", proofResult.proof_gnark.length);
283
675
  const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
284
676
  console.log("Proof bytes length:", proofBytes.length);
285
- console.log("Proof bytes hex:", Buffer.from(proofBytes).toString("hex"));
677
+ console.log("Proof bytes hex:", toHex(proofBytes));
286
678
  console.log("============================");
287
679
  return {
288
680
  proof: proofBytes,
@@ -373,7 +765,9 @@ var init_Barretenberg = __esm({
373
765
  "src/infra/provingSystems/Barretenberg.ts"() {
374
766
  "use strict";
375
767
  Barretenberg = class {
376
- async compile(noirCode) {
768
+ // Note: options parameter is accepted but not used - Barretenberg uses Noir's ACIR directly
769
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
770
+ async compile(noirCode, _options) {
377
771
  const { basePath, cleanup } = await createTempDir2();
378
772
  const fm = createFileManager2(basePath);
379
773
  const nargoToml = `[package]
@@ -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);