@izi-noir/sdk 0.1.5 → 0.1.7
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.
- package/dist/index.cjs +74 -58
- package/dist/index.js +74 -58
- package/dist/providers/arkworks.cjs +79 -58
- package/dist/providers/arkworks.js +79 -58
- package/dist/providers/barretenberg.cjs +79 -58
- package/dist/providers/barretenberg.js +79 -58
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -191,8 +191,15 @@ async function initWasm() {
|
|
|
191
191
|
} else {
|
|
192
192
|
const moduleUrl = new URL(import_meta.url);
|
|
193
193
|
const isSourceFile = moduleUrl.pathname.includes("/src/");
|
|
194
|
-
const
|
|
195
|
-
|
|
194
|
+
const isViteProduction = moduleUrl.pathname.includes("/assets/");
|
|
195
|
+
let wasmJsUrl;
|
|
196
|
+
if (isSourceFile) {
|
|
197
|
+
wasmJsUrl = new URL("../../wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
198
|
+
} else if (isViteProduction) {
|
|
199
|
+
wasmJsUrl = new URL("/wasm/web/arkworks_groth16_wasm.js", moduleUrl.origin);
|
|
200
|
+
} else {
|
|
201
|
+
wasmJsUrl = new URL("./wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
202
|
+
}
|
|
196
203
|
const module2 = await import(
|
|
197
204
|
/* @vite-ignore */
|
|
198
205
|
wasmJsUrl.href
|
|
@@ -297,18 +304,12 @@ authors = [""]
|
|
|
297
304
|
parameters.forEach((p, noirIndex) => {
|
|
298
305
|
const r1csIndex = noirIndex + 1;
|
|
299
306
|
witnessIndexMapping.set(noirIndex, r1csIndex);
|
|
300
|
-
console.log(` Parameter "${p.name}" (${p.visibility}): noir[${noirIndex}] \u2192 R1CS w_${r1csIndex}`);
|
|
301
307
|
if (p.visibility === "public") {
|
|
302
308
|
publicR1csIndices.push(r1csIndex);
|
|
303
309
|
} else if (p.visibility === "private") {
|
|
304
310
|
privateR1csIndices.push(r1csIndex);
|
|
305
311
|
}
|
|
306
312
|
});
|
|
307
|
-
console.log("=== COMPILE: R1CS Witness Assignment ===");
|
|
308
|
-
console.log("Public R1CS indices:", publicR1csIndices);
|
|
309
|
-
console.log("Private R1CS indices:", privateR1csIndices);
|
|
310
|
-
console.log("Witness mapping:", Object.fromEntries(witnessIndexMapping));
|
|
311
|
-
console.log("=========================================");
|
|
312
313
|
const r1cs = {
|
|
313
314
|
num_witnesses: parameters.length + 1,
|
|
314
315
|
// +1 for w_0
|
|
@@ -327,25 +328,18 @@ authors = [""]
|
|
|
327
328
|
c: [["0x1", publicIdx]]
|
|
328
329
|
// expected
|
|
329
330
|
});
|
|
330
|
-
console.log(` Added constraint: w_${privateIdx} * w_${privateIdx} = w_${publicIdx}`);
|
|
331
|
-
} else {
|
|
332
|
-
console.warn("Complex circuit detected - R1CS constraint generation may be incomplete");
|
|
333
331
|
}
|
|
334
332
|
const r1csJson = JSON.stringify(r1cs);
|
|
335
|
-
console.log("R1CS JSON:", r1csJson);
|
|
336
333
|
let provingKey;
|
|
337
334
|
let verifyingKey;
|
|
338
335
|
let verifyingKeyGnark;
|
|
339
336
|
if (this.config.cacheKeys) {
|
|
340
337
|
try {
|
|
341
|
-
console.log("Running trusted setup from R1CS...");
|
|
342
338
|
const setupResult = wasm.setup_from_r1cs(r1csJson);
|
|
343
339
|
provingKey = setupResult.proving_key;
|
|
344
340
|
verifyingKey = setupResult.verifying_key;
|
|
345
341
|
verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
346
|
-
console.log("Setup complete!");
|
|
347
342
|
} catch (error) {
|
|
348
|
-
console.error("Setup failed:", error);
|
|
349
343
|
throw new Error(`R1CS setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
350
344
|
}
|
|
351
345
|
}
|
|
@@ -382,60 +376,23 @@ authors = [""]
|
|
|
382
376
|
const noir = new import_noir_js2.Noir(circuit);
|
|
383
377
|
const { witness: compressedWitness } = await noir.execute(inputs);
|
|
384
378
|
const witnessMapNoir = (0, import_acvm_js.decompressWitness)(compressedWitness);
|
|
385
|
-
console.log("=== ARKWORKS WASM DEBUG ===");
|
|
386
|
-
console.log("Circuit ABI parameters:", circuit.abi.parameters);
|
|
387
|
-
console.log("Inputs provided:", JSON.stringify(inputs));
|
|
388
|
-
console.log("Compressed witness size:", compressedWitness.length, "bytes");
|
|
389
|
-
console.log("Decompressed witness entries:", witnessMapNoir.size);
|
|
390
|
-
console.log("Witness map entries (first 10):");
|
|
391
|
-
const sortedWitness = Array.from(witnessMapNoir.entries()).sort(([a], [b]) => a - b);
|
|
392
|
-
for (const [index, value] of sortedWitness.slice(0, 10)) {
|
|
393
|
-
const strVal = String(value);
|
|
394
|
-
console.log(` witness[${index}] = "${strVal.slice(0, 66)}${strVal.length > 66 ? "..." : ""}"`);
|
|
395
|
-
if (strVal.startsWith("0x")) {
|
|
396
|
-
try {
|
|
397
|
-
const decVal = BigInt(strVal).toString(10);
|
|
398
|
-
console.log(` \u2192 decimal: ${decVal}`);
|
|
399
|
-
} catch {
|
|
400
|
-
console.log(` \u2192 failed to parse as BigInt`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
379
|
const witnessMap = {};
|
|
405
380
|
const witnessMapping = circuit.witnessIndexMapping;
|
|
406
|
-
console.log("Converting noir witness to R1CS witness:");
|
|
407
381
|
for (const [noirIndex, value] of witnessMapNoir.entries()) {
|
|
408
382
|
const r1csIndex = witnessMapping.get(noirIndex) ?? noirIndex + 1;
|
|
409
383
|
const strVal = String(value);
|
|
410
384
|
witnessMap[r1csIndex.toString()] = strVal;
|
|
411
|
-
console.log(` noir[${noirIndex}] \u2192 R1CS w_${r1csIndex} = ${strVal.slice(0, 20)}...`);
|
|
412
385
|
}
|
|
413
386
|
const witnessJson = JSON.stringify(witnessMap);
|
|
414
|
-
console.log("Witness JSON for prove:", witnessJson.slice(0, 200) + "...");
|
|
415
|
-
const r1csParsed = JSON.parse(circuit.r1csJson);
|
|
416
|
-
console.log("R1CS public_inputs:", r1csParsed.public_inputs);
|
|
417
|
-
console.log("R1CS private_inputs:", r1csParsed.private_inputs);
|
|
418
|
-
console.log("R1CS num_witnesses:", r1csParsed.num_witnesses);
|
|
419
|
-
console.log("R1CS constraints:", r1csParsed.constraints.length);
|
|
420
387
|
let provingKey = circuit.provingKey;
|
|
421
388
|
if (!provingKey) {
|
|
422
|
-
console.log("Running setup_from_r1cs...");
|
|
423
389
|
const setupResult = wasm.setup_from_r1cs(circuit.r1csJson);
|
|
424
390
|
provingKey = setupResult.proving_key;
|
|
425
391
|
circuit.provingKey = provingKey;
|
|
426
392
|
circuit.verifyingKey = setupResult.verifying_key;
|
|
427
393
|
circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
428
394
|
}
|
|
429
|
-
console.log("Generating proof from R1CS...");
|
|
430
395
|
const proofResult = wasm.prove_from_r1cs(provingKey, circuit.r1csJson, witnessJson);
|
|
431
|
-
console.log("=== PROOF RESULT DEBUG ===");
|
|
432
|
-
console.log("Proof public inputs from arkworks:", proofResult.public_inputs);
|
|
433
|
-
proofResult.public_inputs.forEach((input, i) => {
|
|
434
|
-
const hexValue = input.startsWith("0x") ? input : `0x${input}`;
|
|
435
|
-
const decValue = BigInt(hexValue).toString(10);
|
|
436
|
-
console.log(` Public input ${i}: ${input} (dec: ${decValue})`);
|
|
437
|
-
});
|
|
438
|
-
console.log("===========================");
|
|
439
396
|
const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
|
|
440
397
|
return {
|
|
441
398
|
proof: proofBytes,
|
|
@@ -1529,6 +1486,18 @@ var IziNoir = class _IziNoir {
|
|
|
1529
1486
|
const networkConfig = NETWORK_CONFIG[this._network];
|
|
1530
1487
|
const { Connection, Transaction, PublicKey } = await import("@solana/web3.js");
|
|
1531
1488
|
const connection = new Connection(networkConfig.rpcUrl, "confirmed");
|
|
1489
|
+
const vkPubkey = new PublicKey(vk);
|
|
1490
|
+
const accountInfo = await connection.getAccountInfo(vkPubkey);
|
|
1491
|
+
if (!accountInfo) {
|
|
1492
|
+
throw new Error(
|
|
1493
|
+
`VK account ${vk} does not exist on ${this._network}. Did deploy() succeed? Check the account on explorer: ${getExplorerAccountUrl(this._network, vk)}`
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
if (accountInfo.data.length < 8) {
|
|
1497
|
+
throw new Error(
|
|
1498
|
+
`VK account ${vk} has invalid data (${accountInfo.data.length} bytes). Expected at least 8 bytes for a valid account.`
|
|
1499
|
+
);
|
|
1500
|
+
}
|
|
1532
1501
|
const builder = new SolanaTransactionBuilder({
|
|
1533
1502
|
programId: networkConfig.programId,
|
|
1534
1503
|
computeUnits: 4e5
|
|
@@ -1556,12 +1525,59 @@ var IziNoir = class _IziNoir {
|
|
|
1556
1525
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
1557
1526
|
tx.recentBlockhash = blockhash;
|
|
1558
1527
|
tx.feePayer = new PublicKey(wallet.publicKey.toBase58());
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1528
|
+
try {
|
|
1529
|
+
const simulation = await connection.simulateTransaction(tx);
|
|
1530
|
+
if (simulation.value.err) {
|
|
1531
|
+
const logs = simulation.value.logs?.join("\n") || "No logs available";
|
|
1532
|
+
throw new Error(
|
|
1533
|
+
`Transaction simulation failed:
|
|
1534
|
+
Error: ${JSON.stringify(simulation.value.err)}
|
|
1535
|
+
Logs:
|
|
1536
|
+
${logs}`
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
} catch (simError) {
|
|
1540
|
+
if (simError instanceof Error && simError.message.includes("Transaction simulation failed")) {
|
|
1541
|
+
throw simError;
|
|
1542
|
+
}
|
|
1543
|
+
const err = simError;
|
|
1544
|
+
throw new Error(
|
|
1545
|
+
`Failed to simulate transaction: ${err.message}
|
|
1546
|
+
VK Account: ${vk}
|
|
1547
|
+
Network: ${this._network}
|
|
1548
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1549
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1550
|
+
);
|
|
1551
|
+
}
|
|
1552
|
+
let signature;
|
|
1553
|
+
try {
|
|
1554
|
+
signature = await wallet.sendTransaction(tx, connection);
|
|
1555
|
+
} catch (sendError) {
|
|
1556
|
+
const originalError = sendError;
|
|
1557
|
+
const enhancedError = new Error(
|
|
1558
|
+
`Failed to send verify transaction: ${originalError.message}
|
|
1559
|
+
VK Account: ${vk}
|
|
1560
|
+
Network: ${this._network}
|
|
1561
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1562
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1563
|
+
);
|
|
1564
|
+
enhancedError.cause = originalError;
|
|
1565
|
+
throw enhancedError;
|
|
1566
|
+
}
|
|
1567
|
+
try {
|
|
1568
|
+
await connection.confirmTransaction({
|
|
1569
|
+
signature,
|
|
1570
|
+
blockhash,
|
|
1571
|
+
lastValidBlockHeight
|
|
1572
|
+
});
|
|
1573
|
+
} catch (confirmError) {
|
|
1574
|
+
const err = confirmError;
|
|
1575
|
+
throw new Error(
|
|
1576
|
+
`Transaction sent but confirmation failed: ${err.message}
|
|
1577
|
+
Signature: ${signature}
|
|
1578
|
+
Check on explorer: ${getExplorerTxUrl(this._network, signature)}`
|
|
1579
|
+
);
|
|
1580
|
+
}
|
|
1565
1581
|
return {
|
|
1566
1582
|
verified: true,
|
|
1567
1583
|
signature,
|
package/dist/index.js
CHANGED
|
@@ -172,8 +172,15 @@ async function initWasm() {
|
|
|
172
172
|
} else {
|
|
173
173
|
const moduleUrl = new URL(import.meta.url);
|
|
174
174
|
const isSourceFile = moduleUrl.pathname.includes("/src/");
|
|
175
|
-
const
|
|
176
|
-
|
|
175
|
+
const isViteProduction = moduleUrl.pathname.includes("/assets/");
|
|
176
|
+
let wasmJsUrl;
|
|
177
|
+
if (isSourceFile) {
|
|
178
|
+
wasmJsUrl = new URL("../../wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
179
|
+
} else if (isViteProduction) {
|
|
180
|
+
wasmJsUrl = new URL("/wasm/web/arkworks_groth16_wasm.js", moduleUrl.origin);
|
|
181
|
+
} else {
|
|
182
|
+
wasmJsUrl = new URL("./wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
183
|
+
}
|
|
177
184
|
const module = await import(
|
|
178
185
|
/* @vite-ignore */
|
|
179
186
|
wasmJsUrl.href
|
|
@@ -274,18 +281,12 @@ authors = [""]
|
|
|
274
281
|
parameters.forEach((p, noirIndex) => {
|
|
275
282
|
const r1csIndex = noirIndex + 1;
|
|
276
283
|
witnessIndexMapping.set(noirIndex, r1csIndex);
|
|
277
|
-
console.log(` Parameter "${p.name}" (${p.visibility}): noir[${noirIndex}] \u2192 R1CS w_${r1csIndex}`);
|
|
278
284
|
if (p.visibility === "public") {
|
|
279
285
|
publicR1csIndices.push(r1csIndex);
|
|
280
286
|
} else if (p.visibility === "private") {
|
|
281
287
|
privateR1csIndices.push(r1csIndex);
|
|
282
288
|
}
|
|
283
289
|
});
|
|
284
|
-
console.log("=== COMPILE: R1CS Witness Assignment ===");
|
|
285
|
-
console.log("Public R1CS indices:", publicR1csIndices);
|
|
286
|
-
console.log("Private R1CS indices:", privateR1csIndices);
|
|
287
|
-
console.log("Witness mapping:", Object.fromEntries(witnessIndexMapping));
|
|
288
|
-
console.log("=========================================");
|
|
289
290
|
const r1cs = {
|
|
290
291
|
num_witnesses: parameters.length + 1,
|
|
291
292
|
// +1 for w_0
|
|
@@ -304,25 +305,18 @@ authors = [""]
|
|
|
304
305
|
c: [["0x1", publicIdx]]
|
|
305
306
|
// expected
|
|
306
307
|
});
|
|
307
|
-
console.log(` Added constraint: w_${privateIdx} * w_${privateIdx} = w_${publicIdx}`);
|
|
308
|
-
} else {
|
|
309
|
-
console.warn("Complex circuit detected - R1CS constraint generation may be incomplete");
|
|
310
308
|
}
|
|
311
309
|
const r1csJson = JSON.stringify(r1cs);
|
|
312
|
-
console.log("R1CS JSON:", r1csJson);
|
|
313
310
|
let provingKey;
|
|
314
311
|
let verifyingKey;
|
|
315
312
|
let verifyingKeyGnark;
|
|
316
313
|
if (this.config.cacheKeys) {
|
|
317
314
|
try {
|
|
318
|
-
console.log("Running trusted setup from R1CS...");
|
|
319
315
|
const setupResult = wasm.setup_from_r1cs(r1csJson);
|
|
320
316
|
provingKey = setupResult.proving_key;
|
|
321
317
|
verifyingKey = setupResult.verifying_key;
|
|
322
318
|
verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
323
|
-
console.log("Setup complete!");
|
|
324
319
|
} catch (error) {
|
|
325
|
-
console.error("Setup failed:", error);
|
|
326
320
|
throw new Error(`R1CS setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
327
321
|
}
|
|
328
322
|
}
|
|
@@ -359,60 +353,23 @@ authors = [""]
|
|
|
359
353
|
const noir = new Noir2(circuit);
|
|
360
354
|
const { witness: compressedWitness } = await noir.execute(inputs);
|
|
361
355
|
const witnessMapNoir = decompressWitness(compressedWitness);
|
|
362
|
-
console.log("=== ARKWORKS WASM DEBUG ===");
|
|
363
|
-
console.log("Circuit ABI parameters:", circuit.abi.parameters);
|
|
364
|
-
console.log("Inputs provided:", JSON.stringify(inputs));
|
|
365
|
-
console.log("Compressed witness size:", compressedWitness.length, "bytes");
|
|
366
|
-
console.log("Decompressed witness entries:", witnessMapNoir.size);
|
|
367
|
-
console.log("Witness map entries (first 10):");
|
|
368
|
-
const sortedWitness = Array.from(witnessMapNoir.entries()).sort(([a], [b]) => a - b);
|
|
369
|
-
for (const [index, value] of sortedWitness.slice(0, 10)) {
|
|
370
|
-
const strVal = String(value);
|
|
371
|
-
console.log(` witness[${index}] = "${strVal.slice(0, 66)}${strVal.length > 66 ? "..." : ""}"`);
|
|
372
|
-
if (strVal.startsWith("0x")) {
|
|
373
|
-
try {
|
|
374
|
-
const decVal = BigInt(strVal).toString(10);
|
|
375
|
-
console.log(` \u2192 decimal: ${decVal}`);
|
|
376
|
-
} catch {
|
|
377
|
-
console.log(` \u2192 failed to parse as BigInt`);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
356
|
const witnessMap = {};
|
|
382
357
|
const witnessMapping = circuit.witnessIndexMapping;
|
|
383
|
-
console.log("Converting noir witness to R1CS witness:");
|
|
384
358
|
for (const [noirIndex, value] of witnessMapNoir.entries()) {
|
|
385
359
|
const r1csIndex = witnessMapping.get(noirIndex) ?? noirIndex + 1;
|
|
386
360
|
const strVal = String(value);
|
|
387
361
|
witnessMap[r1csIndex.toString()] = strVal;
|
|
388
|
-
console.log(` noir[${noirIndex}] \u2192 R1CS w_${r1csIndex} = ${strVal.slice(0, 20)}...`);
|
|
389
362
|
}
|
|
390
363
|
const witnessJson = JSON.stringify(witnessMap);
|
|
391
|
-
console.log("Witness JSON for prove:", witnessJson.slice(0, 200) + "...");
|
|
392
|
-
const r1csParsed = JSON.parse(circuit.r1csJson);
|
|
393
|
-
console.log("R1CS public_inputs:", r1csParsed.public_inputs);
|
|
394
|
-
console.log("R1CS private_inputs:", r1csParsed.private_inputs);
|
|
395
|
-
console.log("R1CS num_witnesses:", r1csParsed.num_witnesses);
|
|
396
|
-
console.log("R1CS constraints:", r1csParsed.constraints.length);
|
|
397
364
|
let provingKey = circuit.provingKey;
|
|
398
365
|
if (!provingKey) {
|
|
399
|
-
console.log("Running setup_from_r1cs...");
|
|
400
366
|
const setupResult = wasm.setup_from_r1cs(circuit.r1csJson);
|
|
401
367
|
provingKey = setupResult.proving_key;
|
|
402
368
|
circuit.provingKey = provingKey;
|
|
403
369
|
circuit.verifyingKey = setupResult.verifying_key;
|
|
404
370
|
circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
405
371
|
}
|
|
406
|
-
console.log("Generating proof from R1CS...");
|
|
407
372
|
const proofResult = wasm.prove_from_r1cs(provingKey, circuit.r1csJson, witnessJson);
|
|
408
|
-
console.log("=== PROOF RESULT DEBUG ===");
|
|
409
|
-
console.log("Proof public inputs from arkworks:", proofResult.public_inputs);
|
|
410
|
-
proofResult.public_inputs.forEach((input, i) => {
|
|
411
|
-
const hexValue = input.startsWith("0x") ? input : `0x${input}`;
|
|
412
|
-
const decValue = BigInt(hexValue).toString(10);
|
|
413
|
-
console.log(` Public input ${i}: ${input} (dec: ${decValue})`);
|
|
414
|
-
});
|
|
415
|
-
console.log("===========================");
|
|
416
373
|
const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
|
|
417
374
|
return {
|
|
418
375
|
proof: proofBytes,
|
|
@@ -1461,6 +1418,18 @@ var IziNoir = class _IziNoir {
|
|
|
1461
1418
|
const networkConfig = NETWORK_CONFIG[this._network];
|
|
1462
1419
|
const { Connection, Transaction, PublicKey } = await import("@solana/web3.js");
|
|
1463
1420
|
const connection = new Connection(networkConfig.rpcUrl, "confirmed");
|
|
1421
|
+
const vkPubkey = new PublicKey(vk);
|
|
1422
|
+
const accountInfo = await connection.getAccountInfo(vkPubkey);
|
|
1423
|
+
if (!accountInfo) {
|
|
1424
|
+
throw new Error(
|
|
1425
|
+
`VK account ${vk} does not exist on ${this._network}. Did deploy() succeed? Check the account on explorer: ${getExplorerAccountUrl(this._network, vk)}`
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
if (accountInfo.data.length < 8) {
|
|
1429
|
+
throw new Error(
|
|
1430
|
+
`VK account ${vk} has invalid data (${accountInfo.data.length} bytes). Expected at least 8 bytes for a valid account.`
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1464
1433
|
const builder = new SolanaTransactionBuilder({
|
|
1465
1434
|
programId: networkConfig.programId,
|
|
1466
1435
|
computeUnits: 4e5
|
|
@@ -1488,12 +1457,59 @@ var IziNoir = class _IziNoir {
|
|
|
1488
1457
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
1489
1458
|
tx.recentBlockhash = blockhash;
|
|
1490
1459
|
tx.feePayer = new PublicKey(wallet.publicKey.toBase58());
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1460
|
+
try {
|
|
1461
|
+
const simulation = await connection.simulateTransaction(tx);
|
|
1462
|
+
if (simulation.value.err) {
|
|
1463
|
+
const logs = simulation.value.logs?.join("\n") || "No logs available";
|
|
1464
|
+
throw new Error(
|
|
1465
|
+
`Transaction simulation failed:
|
|
1466
|
+
Error: ${JSON.stringify(simulation.value.err)}
|
|
1467
|
+
Logs:
|
|
1468
|
+
${logs}`
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
} catch (simError) {
|
|
1472
|
+
if (simError instanceof Error && simError.message.includes("Transaction simulation failed")) {
|
|
1473
|
+
throw simError;
|
|
1474
|
+
}
|
|
1475
|
+
const err = simError;
|
|
1476
|
+
throw new Error(
|
|
1477
|
+
`Failed to simulate transaction: ${err.message}
|
|
1478
|
+
VK Account: ${vk}
|
|
1479
|
+
Network: ${this._network}
|
|
1480
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1481
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
let signature;
|
|
1485
|
+
try {
|
|
1486
|
+
signature = await wallet.sendTransaction(tx, connection);
|
|
1487
|
+
} catch (sendError) {
|
|
1488
|
+
const originalError = sendError;
|
|
1489
|
+
const enhancedError = new Error(
|
|
1490
|
+
`Failed to send verify transaction: ${originalError.message}
|
|
1491
|
+
VK Account: ${vk}
|
|
1492
|
+
Network: ${this._network}
|
|
1493
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1494
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1495
|
+
);
|
|
1496
|
+
enhancedError.cause = originalError;
|
|
1497
|
+
throw enhancedError;
|
|
1498
|
+
}
|
|
1499
|
+
try {
|
|
1500
|
+
await connection.confirmTransaction({
|
|
1501
|
+
signature,
|
|
1502
|
+
blockhash,
|
|
1503
|
+
lastValidBlockHeight
|
|
1504
|
+
});
|
|
1505
|
+
} catch (confirmError) {
|
|
1506
|
+
const err = confirmError;
|
|
1507
|
+
throw new Error(
|
|
1508
|
+
`Transaction sent but confirmation failed: ${err.message}
|
|
1509
|
+
Signature: ${signature}
|
|
1510
|
+
Check on explorer: ${getExplorerTxUrl(this._network, signature)}`
|
|
1511
|
+
);
|
|
1512
|
+
}
|
|
1497
1513
|
return {
|
|
1498
1514
|
verified: true,
|
|
1499
1515
|
signature,
|
|
@@ -96,8 +96,15 @@ async function initWasm() {
|
|
|
96
96
|
} else {
|
|
97
97
|
const moduleUrl = new URL(import_meta.url);
|
|
98
98
|
const isSourceFile = moduleUrl.pathname.includes("/src/");
|
|
99
|
-
const
|
|
100
|
-
|
|
99
|
+
const isViteProduction = moduleUrl.pathname.includes("/assets/");
|
|
100
|
+
let wasmJsUrl;
|
|
101
|
+
if (isSourceFile) {
|
|
102
|
+
wasmJsUrl = new URL("../../wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
103
|
+
} else if (isViteProduction) {
|
|
104
|
+
wasmJsUrl = new URL("/wasm/web/arkworks_groth16_wasm.js", moduleUrl.origin);
|
|
105
|
+
} else {
|
|
106
|
+
wasmJsUrl = new URL("./wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
107
|
+
}
|
|
101
108
|
const module2 = await import(
|
|
102
109
|
/* @vite-ignore */
|
|
103
110
|
wasmJsUrl.href
|
|
@@ -202,18 +209,12 @@ authors = [""]
|
|
|
202
209
|
parameters.forEach((p, noirIndex) => {
|
|
203
210
|
const r1csIndex = noirIndex + 1;
|
|
204
211
|
witnessIndexMapping.set(noirIndex, r1csIndex);
|
|
205
|
-
console.log(` Parameter "${p.name}" (${p.visibility}): noir[${noirIndex}] \u2192 R1CS w_${r1csIndex}`);
|
|
206
212
|
if (p.visibility === "public") {
|
|
207
213
|
publicR1csIndices.push(r1csIndex);
|
|
208
214
|
} else if (p.visibility === "private") {
|
|
209
215
|
privateR1csIndices.push(r1csIndex);
|
|
210
216
|
}
|
|
211
217
|
});
|
|
212
|
-
console.log("=== COMPILE: R1CS Witness Assignment ===");
|
|
213
|
-
console.log("Public R1CS indices:", publicR1csIndices);
|
|
214
|
-
console.log("Private R1CS indices:", privateR1csIndices);
|
|
215
|
-
console.log("Witness mapping:", Object.fromEntries(witnessIndexMapping));
|
|
216
|
-
console.log("=========================================");
|
|
217
218
|
const r1cs = {
|
|
218
219
|
num_witnesses: parameters.length + 1,
|
|
219
220
|
// +1 for w_0
|
|
@@ -232,25 +233,18 @@ authors = [""]
|
|
|
232
233
|
c: [["0x1", publicIdx]]
|
|
233
234
|
// expected
|
|
234
235
|
});
|
|
235
|
-
console.log(` Added constraint: w_${privateIdx} * w_${privateIdx} = w_${publicIdx}`);
|
|
236
|
-
} else {
|
|
237
|
-
console.warn("Complex circuit detected - R1CS constraint generation may be incomplete");
|
|
238
236
|
}
|
|
239
237
|
const r1csJson = JSON.stringify(r1cs);
|
|
240
|
-
console.log("R1CS JSON:", r1csJson);
|
|
241
238
|
let provingKey;
|
|
242
239
|
let verifyingKey;
|
|
243
240
|
let verifyingKeyGnark;
|
|
244
241
|
if (this.config.cacheKeys) {
|
|
245
242
|
try {
|
|
246
|
-
console.log("Running trusted setup from R1CS...");
|
|
247
243
|
const setupResult = wasm.setup_from_r1cs(r1csJson);
|
|
248
244
|
provingKey = setupResult.proving_key;
|
|
249
245
|
verifyingKey = setupResult.verifying_key;
|
|
250
246
|
verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
251
|
-
console.log("Setup complete!");
|
|
252
247
|
} catch (error) {
|
|
253
|
-
console.error("Setup failed:", error);
|
|
254
248
|
throw new Error(`R1CS setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
255
249
|
}
|
|
256
250
|
}
|
|
@@ -287,60 +281,23 @@ authors = [""]
|
|
|
287
281
|
const noir = new import_noir_js.Noir(circuit);
|
|
288
282
|
const { witness: compressedWitness } = await noir.execute(inputs);
|
|
289
283
|
const witnessMapNoir = (0, import_acvm_js.decompressWitness)(compressedWitness);
|
|
290
|
-
console.log("=== ARKWORKS WASM DEBUG ===");
|
|
291
|
-
console.log("Circuit ABI parameters:", circuit.abi.parameters);
|
|
292
|
-
console.log("Inputs provided:", JSON.stringify(inputs));
|
|
293
|
-
console.log("Compressed witness size:", compressedWitness.length, "bytes");
|
|
294
|
-
console.log("Decompressed witness entries:", witnessMapNoir.size);
|
|
295
|
-
console.log("Witness map entries (first 10):");
|
|
296
|
-
const sortedWitness = Array.from(witnessMapNoir.entries()).sort(([a], [b]) => a - b);
|
|
297
|
-
for (const [index, value] of sortedWitness.slice(0, 10)) {
|
|
298
|
-
const strVal = String(value);
|
|
299
|
-
console.log(` witness[${index}] = "${strVal.slice(0, 66)}${strVal.length > 66 ? "..." : ""}"`);
|
|
300
|
-
if (strVal.startsWith("0x")) {
|
|
301
|
-
try {
|
|
302
|
-
const decVal = BigInt(strVal).toString(10);
|
|
303
|
-
console.log(` \u2192 decimal: ${decVal}`);
|
|
304
|
-
} catch {
|
|
305
|
-
console.log(` \u2192 failed to parse as BigInt`);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
284
|
const witnessMap = {};
|
|
310
285
|
const witnessMapping = circuit.witnessIndexMapping;
|
|
311
|
-
console.log("Converting noir witness to R1CS witness:");
|
|
312
286
|
for (const [noirIndex, value] of witnessMapNoir.entries()) {
|
|
313
287
|
const r1csIndex = witnessMapping.get(noirIndex) ?? noirIndex + 1;
|
|
314
288
|
const strVal = String(value);
|
|
315
289
|
witnessMap[r1csIndex.toString()] = strVal;
|
|
316
|
-
console.log(` noir[${noirIndex}] \u2192 R1CS w_${r1csIndex} = ${strVal.slice(0, 20)}...`);
|
|
317
290
|
}
|
|
318
291
|
const witnessJson = JSON.stringify(witnessMap);
|
|
319
|
-
console.log("Witness JSON for prove:", witnessJson.slice(0, 200) + "...");
|
|
320
|
-
const r1csParsed = JSON.parse(circuit.r1csJson);
|
|
321
|
-
console.log("R1CS public_inputs:", r1csParsed.public_inputs);
|
|
322
|
-
console.log("R1CS private_inputs:", r1csParsed.private_inputs);
|
|
323
|
-
console.log("R1CS num_witnesses:", r1csParsed.num_witnesses);
|
|
324
|
-
console.log("R1CS constraints:", r1csParsed.constraints.length);
|
|
325
292
|
let provingKey = circuit.provingKey;
|
|
326
293
|
if (!provingKey) {
|
|
327
|
-
console.log("Running setup_from_r1cs...");
|
|
328
294
|
const setupResult = wasm.setup_from_r1cs(circuit.r1csJson);
|
|
329
295
|
provingKey = setupResult.proving_key;
|
|
330
296
|
circuit.provingKey = provingKey;
|
|
331
297
|
circuit.verifyingKey = setupResult.verifying_key;
|
|
332
298
|
circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
333
299
|
}
|
|
334
|
-
console.log("Generating proof from R1CS...");
|
|
335
300
|
const proofResult = wasm.prove_from_r1cs(provingKey, circuit.r1csJson, witnessJson);
|
|
336
|
-
console.log("=== PROOF RESULT DEBUG ===");
|
|
337
|
-
console.log("Proof public inputs from arkworks:", proofResult.public_inputs);
|
|
338
|
-
proofResult.public_inputs.forEach((input, i) => {
|
|
339
|
-
const hexValue = input.startsWith("0x") ? input : `0x${input}`;
|
|
340
|
-
const decValue = BigInt(hexValue).toString(10);
|
|
341
|
-
console.log(` Public input ${i}: ${input} (dec: ${decValue})`);
|
|
342
|
-
});
|
|
343
|
-
console.log("===========================");
|
|
344
301
|
const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
|
|
345
302
|
return {
|
|
346
303
|
proof: proofBytes,
|
|
@@ -643,6 +600,11 @@ function getExplorerTxUrl(network, signature) {
|
|
|
643
600
|
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
644
601
|
return `${config.explorerUrl.replace(/\?.*$/, "")}/tx/${signature}${clusterParam}`;
|
|
645
602
|
}
|
|
603
|
+
function getExplorerAccountUrl(network, address) {
|
|
604
|
+
const config = NETWORK_CONFIG[network];
|
|
605
|
+
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
606
|
+
return `${config.explorerUrl.replace(/\?.*$/, "")}/address/${address}${clusterParam}`;
|
|
607
|
+
}
|
|
646
608
|
|
|
647
609
|
// src/domain/types/provider.ts
|
|
648
610
|
var Provider = /* @__PURE__ */ ((Provider2) => {
|
|
@@ -1402,6 +1364,18 @@ var IziNoir = class _IziNoir {
|
|
|
1402
1364
|
const networkConfig = NETWORK_CONFIG[this._network];
|
|
1403
1365
|
const { Connection, Transaction, PublicKey } = await import("@solana/web3.js");
|
|
1404
1366
|
const connection = new Connection(networkConfig.rpcUrl, "confirmed");
|
|
1367
|
+
const vkPubkey = new PublicKey(vk);
|
|
1368
|
+
const accountInfo = await connection.getAccountInfo(vkPubkey);
|
|
1369
|
+
if (!accountInfo) {
|
|
1370
|
+
throw new Error(
|
|
1371
|
+
`VK account ${vk} does not exist on ${this._network}. Did deploy() succeed? Check the account on explorer: ${getExplorerAccountUrl(this._network, vk)}`
|
|
1372
|
+
);
|
|
1373
|
+
}
|
|
1374
|
+
if (accountInfo.data.length < 8) {
|
|
1375
|
+
throw new Error(
|
|
1376
|
+
`VK account ${vk} has invalid data (${accountInfo.data.length} bytes). Expected at least 8 bytes for a valid account.`
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1405
1379
|
const builder = new SolanaTransactionBuilder({
|
|
1406
1380
|
programId: networkConfig.programId,
|
|
1407
1381
|
computeUnits: 4e5
|
|
@@ -1429,12 +1403,59 @@ var IziNoir = class _IziNoir {
|
|
|
1429
1403
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
1430
1404
|
tx.recentBlockhash = blockhash;
|
|
1431
1405
|
tx.feePayer = new PublicKey(wallet.publicKey.toBase58());
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1406
|
+
try {
|
|
1407
|
+
const simulation = await connection.simulateTransaction(tx);
|
|
1408
|
+
if (simulation.value.err) {
|
|
1409
|
+
const logs = simulation.value.logs?.join("\n") || "No logs available";
|
|
1410
|
+
throw new Error(
|
|
1411
|
+
`Transaction simulation failed:
|
|
1412
|
+
Error: ${JSON.stringify(simulation.value.err)}
|
|
1413
|
+
Logs:
|
|
1414
|
+
${logs}`
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
} catch (simError) {
|
|
1418
|
+
if (simError instanceof Error && simError.message.includes("Transaction simulation failed")) {
|
|
1419
|
+
throw simError;
|
|
1420
|
+
}
|
|
1421
|
+
const err = simError;
|
|
1422
|
+
throw new Error(
|
|
1423
|
+
`Failed to simulate transaction: ${err.message}
|
|
1424
|
+
VK Account: ${vk}
|
|
1425
|
+
Network: ${this._network}
|
|
1426
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1427
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1430
|
+
let signature;
|
|
1431
|
+
try {
|
|
1432
|
+
signature = await wallet.sendTransaction(tx, connection);
|
|
1433
|
+
} catch (sendError) {
|
|
1434
|
+
const originalError = sendError;
|
|
1435
|
+
const enhancedError = new Error(
|
|
1436
|
+
`Failed to send verify transaction: ${originalError.message}
|
|
1437
|
+
VK Account: ${vk}
|
|
1438
|
+
Network: ${this._network}
|
|
1439
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1440
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1441
|
+
);
|
|
1442
|
+
enhancedError.cause = originalError;
|
|
1443
|
+
throw enhancedError;
|
|
1444
|
+
}
|
|
1445
|
+
try {
|
|
1446
|
+
await connection.confirmTransaction({
|
|
1447
|
+
signature,
|
|
1448
|
+
blockhash,
|
|
1449
|
+
lastValidBlockHeight
|
|
1450
|
+
});
|
|
1451
|
+
} catch (confirmError) {
|
|
1452
|
+
const err = confirmError;
|
|
1453
|
+
throw new Error(
|
|
1454
|
+
`Transaction sent but confirmation failed: ${err.message}
|
|
1455
|
+
Signature: ${signature}
|
|
1456
|
+
Check on explorer: ${getExplorerTxUrl(this._network, signature)}`
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1438
1459
|
return {
|
|
1439
1460
|
verified: true,
|
|
1440
1461
|
signature,
|
|
@@ -77,8 +77,15 @@ async function initWasm() {
|
|
|
77
77
|
} else {
|
|
78
78
|
const moduleUrl = new URL(import.meta.url);
|
|
79
79
|
const isSourceFile = moduleUrl.pathname.includes("/src/");
|
|
80
|
-
const
|
|
81
|
-
|
|
80
|
+
const isViteProduction = moduleUrl.pathname.includes("/assets/");
|
|
81
|
+
let wasmJsUrl;
|
|
82
|
+
if (isSourceFile) {
|
|
83
|
+
wasmJsUrl = new URL("../../wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
84
|
+
} else if (isViteProduction) {
|
|
85
|
+
wasmJsUrl = new URL("/wasm/web/arkworks_groth16_wasm.js", moduleUrl.origin);
|
|
86
|
+
} else {
|
|
87
|
+
wasmJsUrl = new URL("./wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
88
|
+
}
|
|
82
89
|
const module = await import(
|
|
83
90
|
/* @vite-ignore */
|
|
84
91
|
wasmJsUrl.href
|
|
@@ -179,18 +186,12 @@ authors = [""]
|
|
|
179
186
|
parameters.forEach((p, noirIndex) => {
|
|
180
187
|
const r1csIndex = noirIndex + 1;
|
|
181
188
|
witnessIndexMapping.set(noirIndex, r1csIndex);
|
|
182
|
-
console.log(` Parameter "${p.name}" (${p.visibility}): noir[${noirIndex}] \u2192 R1CS w_${r1csIndex}`);
|
|
183
189
|
if (p.visibility === "public") {
|
|
184
190
|
publicR1csIndices.push(r1csIndex);
|
|
185
191
|
} else if (p.visibility === "private") {
|
|
186
192
|
privateR1csIndices.push(r1csIndex);
|
|
187
193
|
}
|
|
188
194
|
});
|
|
189
|
-
console.log("=== COMPILE: R1CS Witness Assignment ===");
|
|
190
|
-
console.log("Public R1CS indices:", publicR1csIndices);
|
|
191
|
-
console.log("Private R1CS indices:", privateR1csIndices);
|
|
192
|
-
console.log("Witness mapping:", Object.fromEntries(witnessIndexMapping));
|
|
193
|
-
console.log("=========================================");
|
|
194
195
|
const r1cs = {
|
|
195
196
|
num_witnesses: parameters.length + 1,
|
|
196
197
|
// +1 for w_0
|
|
@@ -209,25 +210,18 @@ authors = [""]
|
|
|
209
210
|
c: [["0x1", publicIdx]]
|
|
210
211
|
// expected
|
|
211
212
|
});
|
|
212
|
-
console.log(` Added constraint: w_${privateIdx} * w_${privateIdx} = w_${publicIdx}`);
|
|
213
|
-
} else {
|
|
214
|
-
console.warn("Complex circuit detected - R1CS constraint generation may be incomplete");
|
|
215
213
|
}
|
|
216
214
|
const r1csJson = JSON.stringify(r1cs);
|
|
217
|
-
console.log("R1CS JSON:", r1csJson);
|
|
218
215
|
let provingKey;
|
|
219
216
|
let verifyingKey;
|
|
220
217
|
let verifyingKeyGnark;
|
|
221
218
|
if (this.config.cacheKeys) {
|
|
222
219
|
try {
|
|
223
|
-
console.log("Running trusted setup from R1CS...");
|
|
224
220
|
const setupResult = wasm.setup_from_r1cs(r1csJson);
|
|
225
221
|
provingKey = setupResult.proving_key;
|
|
226
222
|
verifyingKey = setupResult.verifying_key;
|
|
227
223
|
verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
228
|
-
console.log("Setup complete!");
|
|
229
224
|
} catch (error) {
|
|
230
|
-
console.error("Setup failed:", error);
|
|
231
225
|
throw new Error(`R1CS setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
232
226
|
}
|
|
233
227
|
}
|
|
@@ -264,60 +258,23 @@ authors = [""]
|
|
|
264
258
|
const noir = new Noir(circuit);
|
|
265
259
|
const { witness: compressedWitness } = await noir.execute(inputs);
|
|
266
260
|
const witnessMapNoir = decompressWitness(compressedWitness);
|
|
267
|
-
console.log("=== ARKWORKS WASM DEBUG ===");
|
|
268
|
-
console.log("Circuit ABI parameters:", circuit.abi.parameters);
|
|
269
|
-
console.log("Inputs provided:", JSON.stringify(inputs));
|
|
270
|
-
console.log("Compressed witness size:", compressedWitness.length, "bytes");
|
|
271
|
-
console.log("Decompressed witness entries:", witnessMapNoir.size);
|
|
272
|
-
console.log("Witness map entries (first 10):");
|
|
273
|
-
const sortedWitness = Array.from(witnessMapNoir.entries()).sort(([a], [b]) => a - b);
|
|
274
|
-
for (const [index, value] of sortedWitness.slice(0, 10)) {
|
|
275
|
-
const strVal = String(value);
|
|
276
|
-
console.log(` witness[${index}] = "${strVal.slice(0, 66)}${strVal.length > 66 ? "..." : ""}"`);
|
|
277
|
-
if (strVal.startsWith("0x")) {
|
|
278
|
-
try {
|
|
279
|
-
const decVal = BigInt(strVal).toString(10);
|
|
280
|
-
console.log(` \u2192 decimal: ${decVal}`);
|
|
281
|
-
} catch {
|
|
282
|
-
console.log(` \u2192 failed to parse as BigInt`);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
261
|
const witnessMap = {};
|
|
287
262
|
const witnessMapping = circuit.witnessIndexMapping;
|
|
288
|
-
console.log("Converting noir witness to R1CS witness:");
|
|
289
263
|
for (const [noirIndex, value] of witnessMapNoir.entries()) {
|
|
290
264
|
const r1csIndex = witnessMapping.get(noirIndex) ?? noirIndex + 1;
|
|
291
265
|
const strVal = String(value);
|
|
292
266
|
witnessMap[r1csIndex.toString()] = strVal;
|
|
293
|
-
console.log(` noir[${noirIndex}] \u2192 R1CS w_${r1csIndex} = ${strVal.slice(0, 20)}...`);
|
|
294
267
|
}
|
|
295
268
|
const witnessJson = JSON.stringify(witnessMap);
|
|
296
|
-
console.log("Witness JSON for prove:", witnessJson.slice(0, 200) + "...");
|
|
297
|
-
const r1csParsed = JSON.parse(circuit.r1csJson);
|
|
298
|
-
console.log("R1CS public_inputs:", r1csParsed.public_inputs);
|
|
299
|
-
console.log("R1CS private_inputs:", r1csParsed.private_inputs);
|
|
300
|
-
console.log("R1CS num_witnesses:", r1csParsed.num_witnesses);
|
|
301
|
-
console.log("R1CS constraints:", r1csParsed.constraints.length);
|
|
302
269
|
let provingKey = circuit.provingKey;
|
|
303
270
|
if (!provingKey) {
|
|
304
|
-
console.log("Running setup_from_r1cs...");
|
|
305
271
|
const setupResult = wasm.setup_from_r1cs(circuit.r1csJson);
|
|
306
272
|
provingKey = setupResult.proving_key;
|
|
307
273
|
circuit.provingKey = provingKey;
|
|
308
274
|
circuit.verifyingKey = setupResult.verifying_key;
|
|
309
275
|
circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
310
276
|
}
|
|
311
|
-
console.log("Generating proof from R1CS...");
|
|
312
277
|
const proofResult = wasm.prove_from_r1cs(provingKey, circuit.r1csJson, witnessJson);
|
|
313
|
-
console.log("=== PROOF RESULT DEBUG ===");
|
|
314
|
-
console.log("Proof public inputs from arkworks:", proofResult.public_inputs);
|
|
315
|
-
proofResult.public_inputs.forEach((input, i) => {
|
|
316
|
-
const hexValue = input.startsWith("0x") ? input : `0x${input}`;
|
|
317
|
-
const decValue = BigInt(hexValue).toString(10);
|
|
318
|
-
console.log(` Public input ${i}: ${input} (dec: ${decValue})`);
|
|
319
|
-
});
|
|
320
|
-
console.log("===========================");
|
|
321
278
|
const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
|
|
322
279
|
return {
|
|
323
280
|
proof: proofBytes,
|
|
@@ -610,6 +567,11 @@ function getExplorerTxUrl(network, signature) {
|
|
|
610
567
|
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
611
568
|
return `${config.explorerUrl.replace(/\?.*$/, "")}/tx/${signature}${clusterParam}`;
|
|
612
569
|
}
|
|
570
|
+
function getExplorerAccountUrl(network, address) {
|
|
571
|
+
const config = NETWORK_CONFIG[network];
|
|
572
|
+
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
573
|
+
return `${config.explorerUrl.replace(/\?.*$/, "")}/address/${address}${clusterParam}`;
|
|
574
|
+
}
|
|
613
575
|
|
|
614
576
|
// src/domain/types/provider.ts
|
|
615
577
|
var Provider = /* @__PURE__ */ ((Provider2) => {
|
|
@@ -1369,6 +1331,18 @@ var IziNoir = class _IziNoir {
|
|
|
1369
1331
|
const networkConfig = NETWORK_CONFIG[this._network];
|
|
1370
1332
|
const { Connection, Transaction, PublicKey } = await import("@solana/web3.js");
|
|
1371
1333
|
const connection = new Connection(networkConfig.rpcUrl, "confirmed");
|
|
1334
|
+
const vkPubkey = new PublicKey(vk);
|
|
1335
|
+
const accountInfo = await connection.getAccountInfo(vkPubkey);
|
|
1336
|
+
if (!accountInfo) {
|
|
1337
|
+
throw new Error(
|
|
1338
|
+
`VK account ${vk} does not exist on ${this._network}. Did deploy() succeed? Check the account on explorer: ${getExplorerAccountUrl(this._network, vk)}`
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
if (accountInfo.data.length < 8) {
|
|
1342
|
+
throw new Error(
|
|
1343
|
+
`VK account ${vk} has invalid data (${accountInfo.data.length} bytes). Expected at least 8 bytes for a valid account.`
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1372
1346
|
const builder = new SolanaTransactionBuilder({
|
|
1373
1347
|
programId: networkConfig.programId,
|
|
1374
1348
|
computeUnits: 4e5
|
|
@@ -1396,12 +1370,59 @@ var IziNoir = class _IziNoir {
|
|
|
1396
1370
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
1397
1371
|
tx.recentBlockhash = blockhash;
|
|
1398
1372
|
tx.feePayer = new PublicKey(wallet.publicKey.toBase58());
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1373
|
+
try {
|
|
1374
|
+
const simulation = await connection.simulateTransaction(tx);
|
|
1375
|
+
if (simulation.value.err) {
|
|
1376
|
+
const logs = simulation.value.logs?.join("\n") || "No logs available";
|
|
1377
|
+
throw new Error(
|
|
1378
|
+
`Transaction simulation failed:
|
|
1379
|
+
Error: ${JSON.stringify(simulation.value.err)}
|
|
1380
|
+
Logs:
|
|
1381
|
+
${logs}`
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
} catch (simError) {
|
|
1385
|
+
if (simError instanceof Error && simError.message.includes("Transaction simulation failed")) {
|
|
1386
|
+
throw simError;
|
|
1387
|
+
}
|
|
1388
|
+
const err = simError;
|
|
1389
|
+
throw new Error(
|
|
1390
|
+
`Failed to simulate transaction: ${err.message}
|
|
1391
|
+
VK Account: ${vk}
|
|
1392
|
+
Network: ${this._network}
|
|
1393
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1394
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1395
|
+
);
|
|
1396
|
+
}
|
|
1397
|
+
let signature;
|
|
1398
|
+
try {
|
|
1399
|
+
signature = await wallet.sendTransaction(tx, connection);
|
|
1400
|
+
} catch (sendError) {
|
|
1401
|
+
const originalError = sendError;
|
|
1402
|
+
const enhancedError = new Error(
|
|
1403
|
+
`Failed to send verify transaction: ${originalError.message}
|
|
1404
|
+
VK Account: ${vk}
|
|
1405
|
+
Network: ${this._network}
|
|
1406
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1407
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1408
|
+
);
|
|
1409
|
+
enhancedError.cause = originalError;
|
|
1410
|
+
throw enhancedError;
|
|
1411
|
+
}
|
|
1412
|
+
try {
|
|
1413
|
+
await connection.confirmTransaction({
|
|
1414
|
+
signature,
|
|
1415
|
+
blockhash,
|
|
1416
|
+
lastValidBlockHeight
|
|
1417
|
+
});
|
|
1418
|
+
} catch (confirmError) {
|
|
1419
|
+
const err = confirmError;
|
|
1420
|
+
throw new Error(
|
|
1421
|
+
`Transaction sent but confirmation failed: ${err.message}
|
|
1422
|
+
Signature: ${signature}
|
|
1423
|
+
Check on explorer: ${getExplorerTxUrl(this._network, signature)}`
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1405
1426
|
return {
|
|
1406
1427
|
verified: true,
|
|
1407
1428
|
signature,
|
|
@@ -191,8 +191,15 @@ async function initWasm() {
|
|
|
191
191
|
} else {
|
|
192
192
|
const moduleUrl = new URL(import_meta.url);
|
|
193
193
|
const isSourceFile = moduleUrl.pathname.includes("/src/");
|
|
194
|
-
const
|
|
195
|
-
|
|
194
|
+
const isViteProduction = moduleUrl.pathname.includes("/assets/");
|
|
195
|
+
let wasmJsUrl;
|
|
196
|
+
if (isSourceFile) {
|
|
197
|
+
wasmJsUrl = new URL("../../wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
198
|
+
} else if (isViteProduction) {
|
|
199
|
+
wasmJsUrl = new URL("/wasm/web/arkworks_groth16_wasm.js", moduleUrl.origin);
|
|
200
|
+
} else {
|
|
201
|
+
wasmJsUrl = new URL("./wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
202
|
+
}
|
|
196
203
|
const module2 = await import(
|
|
197
204
|
/* @vite-ignore */
|
|
198
205
|
wasmJsUrl.href
|
|
@@ -297,18 +304,12 @@ authors = [""]
|
|
|
297
304
|
parameters.forEach((p, noirIndex) => {
|
|
298
305
|
const r1csIndex = noirIndex + 1;
|
|
299
306
|
witnessIndexMapping.set(noirIndex, r1csIndex);
|
|
300
|
-
console.log(` Parameter "${p.name}" (${p.visibility}): noir[${noirIndex}] \u2192 R1CS w_${r1csIndex}`);
|
|
301
307
|
if (p.visibility === "public") {
|
|
302
308
|
publicR1csIndices.push(r1csIndex);
|
|
303
309
|
} else if (p.visibility === "private") {
|
|
304
310
|
privateR1csIndices.push(r1csIndex);
|
|
305
311
|
}
|
|
306
312
|
});
|
|
307
|
-
console.log("=== COMPILE: R1CS Witness Assignment ===");
|
|
308
|
-
console.log("Public R1CS indices:", publicR1csIndices);
|
|
309
|
-
console.log("Private R1CS indices:", privateR1csIndices);
|
|
310
|
-
console.log("Witness mapping:", Object.fromEntries(witnessIndexMapping));
|
|
311
|
-
console.log("=========================================");
|
|
312
313
|
const r1cs = {
|
|
313
314
|
num_witnesses: parameters.length + 1,
|
|
314
315
|
// +1 for w_0
|
|
@@ -327,25 +328,18 @@ authors = [""]
|
|
|
327
328
|
c: [["0x1", publicIdx]]
|
|
328
329
|
// expected
|
|
329
330
|
});
|
|
330
|
-
console.log(` Added constraint: w_${privateIdx} * w_${privateIdx} = w_${publicIdx}`);
|
|
331
|
-
} else {
|
|
332
|
-
console.warn("Complex circuit detected - R1CS constraint generation may be incomplete");
|
|
333
331
|
}
|
|
334
332
|
const r1csJson = JSON.stringify(r1cs);
|
|
335
|
-
console.log("R1CS JSON:", r1csJson);
|
|
336
333
|
let provingKey;
|
|
337
334
|
let verifyingKey;
|
|
338
335
|
let verifyingKeyGnark;
|
|
339
336
|
if (this.config.cacheKeys) {
|
|
340
337
|
try {
|
|
341
|
-
console.log("Running trusted setup from R1CS...");
|
|
342
338
|
const setupResult = wasm.setup_from_r1cs(r1csJson);
|
|
343
339
|
provingKey = setupResult.proving_key;
|
|
344
340
|
verifyingKey = setupResult.verifying_key;
|
|
345
341
|
verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
346
|
-
console.log("Setup complete!");
|
|
347
342
|
} catch (error) {
|
|
348
|
-
console.error("Setup failed:", error);
|
|
349
343
|
throw new Error(`R1CS setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
350
344
|
}
|
|
351
345
|
}
|
|
@@ -382,60 +376,23 @@ authors = [""]
|
|
|
382
376
|
const noir = new import_noir_js2.Noir(circuit);
|
|
383
377
|
const { witness: compressedWitness } = await noir.execute(inputs);
|
|
384
378
|
const witnessMapNoir = (0, import_acvm_js.decompressWitness)(compressedWitness);
|
|
385
|
-
console.log("=== ARKWORKS WASM DEBUG ===");
|
|
386
|
-
console.log("Circuit ABI parameters:", circuit.abi.parameters);
|
|
387
|
-
console.log("Inputs provided:", JSON.stringify(inputs));
|
|
388
|
-
console.log("Compressed witness size:", compressedWitness.length, "bytes");
|
|
389
|
-
console.log("Decompressed witness entries:", witnessMapNoir.size);
|
|
390
|
-
console.log("Witness map entries (first 10):");
|
|
391
|
-
const sortedWitness = Array.from(witnessMapNoir.entries()).sort(([a], [b]) => a - b);
|
|
392
|
-
for (const [index, value] of sortedWitness.slice(0, 10)) {
|
|
393
|
-
const strVal = String(value);
|
|
394
|
-
console.log(` witness[${index}] = "${strVal.slice(0, 66)}${strVal.length > 66 ? "..." : ""}"`);
|
|
395
|
-
if (strVal.startsWith("0x")) {
|
|
396
|
-
try {
|
|
397
|
-
const decVal = BigInt(strVal).toString(10);
|
|
398
|
-
console.log(` \u2192 decimal: ${decVal}`);
|
|
399
|
-
} catch {
|
|
400
|
-
console.log(` \u2192 failed to parse as BigInt`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
379
|
const witnessMap = {};
|
|
405
380
|
const witnessMapping = circuit.witnessIndexMapping;
|
|
406
|
-
console.log("Converting noir witness to R1CS witness:");
|
|
407
381
|
for (const [noirIndex, value] of witnessMapNoir.entries()) {
|
|
408
382
|
const r1csIndex = witnessMapping.get(noirIndex) ?? noirIndex + 1;
|
|
409
383
|
const strVal = String(value);
|
|
410
384
|
witnessMap[r1csIndex.toString()] = strVal;
|
|
411
|
-
console.log(` noir[${noirIndex}] \u2192 R1CS w_${r1csIndex} = ${strVal.slice(0, 20)}...`);
|
|
412
385
|
}
|
|
413
386
|
const witnessJson = JSON.stringify(witnessMap);
|
|
414
|
-
console.log("Witness JSON for prove:", witnessJson.slice(0, 200) + "...");
|
|
415
|
-
const r1csParsed = JSON.parse(circuit.r1csJson);
|
|
416
|
-
console.log("R1CS public_inputs:", r1csParsed.public_inputs);
|
|
417
|
-
console.log("R1CS private_inputs:", r1csParsed.private_inputs);
|
|
418
|
-
console.log("R1CS num_witnesses:", r1csParsed.num_witnesses);
|
|
419
|
-
console.log("R1CS constraints:", r1csParsed.constraints.length);
|
|
420
387
|
let provingKey = circuit.provingKey;
|
|
421
388
|
if (!provingKey) {
|
|
422
|
-
console.log("Running setup_from_r1cs...");
|
|
423
389
|
const setupResult = wasm.setup_from_r1cs(circuit.r1csJson);
|
|
424
390
|
provingKey = setupResult.proving_key;
|
|
425
391
|
circuit.provingKey = provingKey;
|
|
426
392
|
circuit.verifyingKey = setupResult.verifying_key;
|
|
427
393
|
circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
428
394
|
}
|
|
429
|
-
console.log("Generating proof from R1CS...");
|
|
430
395
|
const proofResult = wasm.prove_from_r1cs(provingKey, circuit.r1csJson, witnessJson);
|
|
431
|
-
console.log("=== PROOF RESULT DEBUG ===");
|
|
432
|
-
console.log("Proof public inputs from arkworks:", proofResult.public_inputs);
|
|
433
|
-
proofResult.public_inputs.forEach((input, i) => {
|
|
434
|
-
const hexValue = input.startsWith("0x") ? input : `0x${input}`;
|
|
435
|
-
const decValue = BigInt(hexValue).toString(10);
|
|
436
|
-
console.log(` Public input ${i}: ${input} (dec: ${decValue})`);
|
|
437
|
-
});
|
|
438
|
-
console.log("===========================");
|
|
439
396
|
const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
|
|
440
397
|
return {
|
|
441
398
|
proof: proofBytes,
|
|
@@ -642,6 +599,11 @@ function getExplorerTxUrl(network, signature) {
|
|
|
642
599
|
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
643
600
|
return `${config.explorerUrl.replace(/\?.*$/, "")}/tx/${signature}${clusterParam}`;
|
|
644
601
|
}
|
|
602
|
+
function getExplorerAccountUrl(network, address) {
|
|
603
|
+
const config = NETWORK_CONFIG[network];
|
|
604
|
+
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
605
|
+
return `${config.explorerUrl.replace(/\?.*$/, "")}/address/${address}${clusterParam}`;
|
|
606
|
+
}
|
|
645
607
|
|
|
646
608
|
// src/domain/types/provider.ts
|
|
647
609
|
var Provider = /* @__PURE__ */ ((Provider2) => {
|
|
@@ -1401,6 +1363,18 @@ var IziNoir = class _IziNoir {
|
|
|
1401
1363
|
const networkConfig = NETWORK_CONFIG[this._network];
|
|
1402
1364
|
const { Connection, Transaction, PublicKey } = await import("@solana/web3.js");
|
|
1403
1365
|
const connection = new Connection(networkConfig.rpcUrl, "confirmed");
|
|
1366
|
+
const vkPubkey = new PublicKey(vk);
|
|
1367
|
+
const accountInfo = await connection.getAccountInfo(vkPubkey);
|
|
1368
|
+
if (!accountInfo) {
|
|
1369
|
+
throw new Error(
|
|
1370
|
+
`VK account ${vk} does not exist on ${this._network}. Did deploy() succeed? Check the account on explorer: ${getExplorerAccountUrl(this._network, vk)}`
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
if (accountInfo.data.length < 8) {
|
|
1374
|
+
throw new Error(
|
|
1375
|
+
`VK account ${vk} has invalid data (${accountInfo.data.length} bytes). Expected at least 8 bytes for a valid account.`
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1404
1378
|
const builder = new SolanaTransactionBuilder({
|
|
1405
1379
|
programId: networkConfig.programId,
|
|
1406
1380
|
computeUnits: 4e5
|
|
@@ -1428,12 +1402,59 @@ var IziNoir = class _IziNoir {
|
|
|
1428
1402
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
1429
1403
|
tx.recentBlockhash = blockhash;
|
|
1430
1404
|
tx.feePayer = new PublicKey(wallet.publicKey.toBase58());
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1405
|
+
try {
|
|
1406
|
+
const simulation = await connection.simulateTransaction(tx);
|
|
1407
|
+
if (simulation.value.err) {
|
|
1408
|
+
const logs = simulation.value.logs?.join("\n") || "No logs available";
|
|
1409
|
+
throw new Error(
|
|
1410
|
+
`Transaction simulation failed:
|
|
1411
|
+
Error: ${JSON.stringify(simulation.value.err)}
|
|
1412
|
+
Logs:
|
|
1413
|
+
${logs}`
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
} catch (simError) {
|
|
1417
|
+
if (simError instanceof Error && simError.message.includes("Transaction simulation failed")) {
|
|
1418
|
+
throw simError;
|
|
1419
|
+
}
|
|
1420
|
+
const err = simError;
|
|
1421
|
+
throw new Error(
|
|
1422
|
+
`Failed to simulate transaction: ${err.message}
|
|
1423
|
+
VK Account: ${vk}
|
|
1424
|
+
Network: ${this._network}
|
|
1425
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1426
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
let signature;
|
|
1430
|
+
try {
|
|
1431
|
+
signature = await wallet.sendTransaction(tx, connection);
|
|
1432
|
+
} catch (sendError) {
|
|
1433
|
+
const originalError = sendError;
|
|
1434
|
+
const enhancedError = new Error(
|
|
1435
|
+
`Failed to send verify transaction: ${originalError.message}
|
|
1436
|
+
VK Account: ${vk}
|
|
1437
|
+
Network: ${this._network}
|
|
1438
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1439
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1440
|
+
);
|
|
1441
|
+
enhancedError.cause = originalError;
|
|
1442
|
+
throw enhancedError;
|
|
1443
|
+
}
|
|
1444
|
+
try {
|
|
1445
|
+
await connection.confirmTransaction({
|
|
1446
|
+
signature,
|
|
1447
|
+
blockhash,
|
|
1448
|
+
lastValidBlockHeight
|
|
1449
|
+
});
|
|
1450
|
+
} catch (confirmError) {
|
|
1451
|
+
const err = confirmError;
|
|
1452
|
+
throw new Error(
|
|
1453
|
+
`Transaction sent but confirmation failed: ${err.message}
|
|
1454
|
+
Signature: ${signature}
|
|
1455
|
+
Check on explorer: ${getExplorerTxUrl(this._network, signature)}`
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1437
1458
|
return {
|
|
1438
1459
|
verified: true,
|
|
1439
1460
|
signature,
|
|
@@ -172,8 +172,15 @@ async function initWasm() {
|
|
|
172
172
|
} else {
|
|
173
173
|
const moduleUrl = new URL(import.meta.url);
|
|
174
174
|
const isSourceFile = moduleUrl.pathname.includes("/src/");
|
|
175
|
-
const
|
|
176
|
-
|
|
175
|
+
const isViteProduction = moduleUrl.pathname.includes("/assets/");
|
|
176
|
+
let wasmJsUrl;
|
|
177
|
+
if (isSourceFile) {
|
|
178
|
+
wasmJsUrl = new URL("../../wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
179
|
+
} else if (isViteProduction) {
|
|
180
|
+
wasmJsUrl = new URL("/wasm/web/arkworks_groth16_wasm.js", moduleUrl.origin);
|
|
181
|
+
} else {
|
|
182
|
+
wasmJsUrl = new URL("./wasm/web/arkworks_groth16_wasm.js", moduleUrl);
|
|
183
|
+
}
|
|
177
184
|
const module = await import(
|
|
178
185
|
/* @vite-ignore */
|
|
179
186
|
wasmJsUrl.href
|
|
@@ -274,18 +281,12 @@ authors = [""]
|
|
|
274
281
|
parameters.forEach((p, noirIndex) => {
|
|
275
282
|
const r1csIndex = noirIndex + 1;
|
|
276
283
|
witnessIndexMapping.set(noirIndex, r1csIndex);
|
|
277
|
-
console.log(` Parameter "${p.name}" (${p.visibility}): noir[${noirIndex}] \u2192 R1CS w_${r1csIndex}`);
|
|
278
284
|
if (p.visibility === "public") {
|
|
279
285
|
publicR1csIndices.push(r1csIndex);
|
|
280
286
|
} else if (p.visibility === "private") {
|
|
281
287
|
privateR1csIndices.push(r1csIndex);
|
|
282
288
|
}
|
|
283
289
|
});
|
|
284
|
-
console.log("=== COMPILE: R1CS Witness Assignment ===");
|
|
285
|
-
console.log("Public R1CS indices:", publicR1csIndices);
|
|
286
|
-
console.log("Private R1CS indices:", privateR1csIndices);
|
|
287
|
-
console.log("Witness mapping:", Object.fromEntries(witnessIndexMapping));
|
|
288
|
-
console.log("=========================================");
|
|
289
290
|
const r1cs = {
|
|
290
291
|
num_witnesses: parameters.length + 1,
|
|
291
292
|
// +1 for w_0
|
|
@@ -304,25 +305,18 @@ authors = [""]
|
|
|
304
305
|
c: [["0x1", publicIdx]]
|
|
305
306
|
// expected
|
|
306
307
|
});
|
|
307
|
-
console.log(` Added constraint: w_${privateIdx} * w_${privateIdx} = w_${publicIdx}`);
|
|
308
|
-
} else {
|
|
309
|
-
console.warn("Complex circuit detected - R1CS constraint generation may be incomplete");
|
|
310
308
|
}
|
|
311
309
|
const r1csJson = JSON.stringify(r1cs);
|
|
312
|
-
console.log("R1CS JSON:", r1csJson);
|
|
313
310
|
let provingKey;
|
|
314
311
|
let verifyingKey;
|
|
315
312
|
let verifyingKeyGnark;
|
|
316
313
|
if (this.config.cacheKeys) {
|
|
317
314
|
try {
|
|
318
|
-
console.log("Running trusted setup from R1CS...");
|
|
319
315
|
const setupResult = wasm.setup_from_r1cs(r1csJson);
|
|
320
316
|
provingKey = setupResult.proving_key;
|
|
321
317
|
verifyingKey = setupResult.verifying_key;
|
|
322
318
|
verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
323
|
-
console.log("Setup complete!");
|
|
324
319
|
} catch (error) {
|
|
325
|
-
console.error("Setup failed:", error);
|
|
326
320
|
throw new Error(`R1CS setup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
327
321
|
}
|
|
328
322
|
}
|
|
@@ -359,60 +353,23 @@ authors = [""]
|
|
|
359
353
|
const noir = new Noir2(circuit);
|
|
360
354
|
const { witness: compressedWitness } = await noir.execute(inputs);
|
|
361
355
|
const witnessMapNoir = decompressWitness(compressedWitness);
|
|
362
|
-
console.log("=== ARKWORKS WASM DEBUG ===");
|
|
363
|
-
console.log("Circuit ABI parameters:", circuit.abi.parameters);
|
|
364
|
-
console.log("Inputs provided:", JSON.stringify(inputs));
|
|
365
|
-
console.log("Compressed witness size:", compressedWitness.length, "bytes");
|
|
366
|
-
console.log("Decompressed witness entries:", witnessMapNoir.size);
|
|
367
|
-
console.log("Witness map entries (first 10):");
|
|
368
|
-
const sortedWitness = Array.from(witnessMapNoir.entries()).sort(([a], [b]) => a - b);
|
|
369
|
-
for (const [index, value] of sortedWitness.slice(0, 10)) {
|
|
370
|
-
const strVal = String(value);
|
|
371
|
-
console.log(` witness[${index}] = "${strVal.slice(0, 66)}${strVal.length > 66 ? "..." : ""}"`);
|
|
372
|
-
if (strVal.startsWith("0x")) {
|
|
373
|
-
try {
|
|
374
|
-
const decVal = BigInt(strVal).toString(10);
|
|
375
|
-
console.log(` \u2192 decimal: ${decVal}`);
|
|
376
|
-
} catch {
|
|
377
|
-
console.log(` \u2192 failed to parse as BigInt`);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
356
|
const witnessMap = {};
|
|
382
357
|
const witnessMapping = circuit.witnessIndexMapping;
|
|
383
|
-
console.log("Converting noir witness to R1CS witness:");
|
|
384
358
|
for (const [noirIndex, value] of witnessMapNoir.entries()) {
|
|
385
359
|
const r1csIndex = witnessMapping.get(noirIndex) ?? noirIndex + 1;
|
|
386
360
|
const strVal = String(value);
|
|
387
361
|
witnessMap[r1csIndex.toString()] = strVal;
|
|
388
|
-
console.log(` noir[${noirIndex}] \u2192 R1CS w_${r1csIndex} = ${strVal.slice(0, 20)}...`);
|
|
389
362
|
}
|
|
390
363
|
const witnessJson = JSON.stringify(witnessMap);
|
|
391
|
-
console.log("Witness JSON for prove:", witnessJson.slice(0, 200) + "...");
|
|
392
|
-
const r1csParsed = JSON.parse(circuit.r1csJson);
|
|
393
|
-
console.log("R1CS public_inputs:", r1csParsed.public_inputs);
|
|
394
|
-
console.log("R1CS private_inputs:", r1csParsed.private_inputs);
|
|
395
|
-
console.log("R1CS num_witnesses:", r1csParsed.num_witnesses);
|
|
396
|
-
console.log("R1CS constraints:", r1csParsed.constraints.length);
|
|
397
364
|
let provingKey = circuit.provingKey;
|
|
398
365
|
if (!provingKey) {
|
|
399
|
-
console.log("Running setup_from_r1cs...");
|
|
400
366
|
const setupResult = wasm.setup_from_r1cs(circuit.r1csJson);
|
|
401
367
|
provingKey = setupResult.proving_key;
|
|
402
368
|
circuit.provingKey = provingKey;
|
|
403
369
|
circuit.verifyingKey = setupResult.verifying_key;
|
|
404
370
|
circuit.verifyingKeyGnark = setupResult.verifying_key_gnark;
|
|
405
371
|
}
|
|
406
|
-
console.log("Generating proof from R1CS...");
|
|
407
372
|
const proofResult = wasm.prove_from_r1cs(provingKey, circuit.r1csJson, witnessJson);
|
|
408
|
-
console.log("=== PROOF RESULT DEBUG ===");
|
|
409
|
-
console.log("Proof public inputs from arkworks:", proofResult.public_inputs);
|
|
410
|
-
proofResult.public_inputs.forEach((input, i) => {
|
|
411
|
-
const hexValue = input.startsWith("0x") ? input : `0x${input}`;
|
|
412
|
-
const decValue = BigInt(hexValue).toString(10);
|
|
413
|
-
console.log(` Public input ${i}: ${input} (dec: ${decValue})`);
|
|
414
|
-
});
|
|
415
|
-
console.log("===========================");
|
|
416
373
|
const proofBytes = base64ToUint8Array(proofResult.proof_gnark);
|
|
417
374
|
return {
|
|
418
375
|
proof: proofBytes,
|
|
@@ -610,6 +567,11 @@ function getExplorerTxUrl(network, signature) {
|
|
|
610
567
|
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
611
568
|
return `${config.explorerUrl.replace(/\?.*$/, "")}/tx/${signature}${clusterParam}`;
|
|
612
569
|
}
|
|
570
|
+
function getExplorerAccountUrl(network, address) {
|
|
571
|
+
const config = NETWORK_CONFIG[network];
|
|
572
|
+
const clusterParam = network === "mainnet-beta" /* Mainnet */ ? "" : `?cluster=${network}`;
|
|
573
|
+
return `${config.explorerUrl.replace(/\?.*$/, "")}/address/${address}${clusterParam}`;
|
|
574
|
+
}
|
|
613
575
|
|
|
614
576
|
// src/domain/types/provider.ts
|
|
615
577
|
var Provider = /* @__PURE__ */ ((Provider2) => {
|
|
@@ -1369,6 +1331,18 @@ var IziNoir = class _IziNoir {
|
|
|
1369
1331
|
const networkConfig = NETWORK_CONFIG[this._network];
|
|
1370
1332
|
const { Connection, Transaction, PublicKey } = await import("@solana/web3.js");
|
|
1371
1333
|
const connection = new Connection(networkConfig.rpcUrl, "confirmed");
|
|
1334
|
+
const vkPubkey = new PublicKey(vk);
|
|
1335
|
+
const accountInfo = await connection.getAccountInfo(vkPubkey);
|
|
1336
|
+
if (!accountInfo) {
|
|
1337
|
+
throw new Error(
|
|
1338
|
+
`VK account ${vk} does not exist on ${this._network}. Did deploy() succeed? Check the account on explorer: ${getExplorerAccountUrl(this._network, vk)}`
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
if (accountInfo.data.length < 8) {
|
|
1342
|
+
throw new Error(
|
|
1343
|
+
`VK account ${vk} has invalid data (${accountInfo.data.length} bytes). Expected at least 8 bytes for a valid account.`
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1372
1346
|
const builder = new SolanaTransactionBuilder({
|
|
1373
1347
|
programId: networkConfig.programId,
|
|
1374
1348
|
computeUnits: 4e5
|
|
@@ -1396,12 +1370,59 @@ var IziNoir = class _IziNoir {
|
|
|
1396
1370
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
1397
1371
|
tx.recentBlockhash = blockhash;
|
|
1398
1372
|
tx.feePayer = new PublicKey(wallet.publicKey.toBase58());
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1373
|
+
try {
|
|
1374
|
+
const simulation = await connection.simulateTransaction(tx);
|
|
1375
|
+
if (simulation.value.err) {
|
|
1376
|
+
const logs = simulation.value.logs?.join("\n") || "No logs available";
|
|
1377
|
+
throw new Error(
|
|
1378
|
+
`Transaction simulation failed:
|
|
1379
|
+
Error: ${JSON.stringify(simulation.value.err)}
|
|
1380
|
+
Logs:
|
|
1381
|
+
${logs}`
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
} catch (simError) {
|
|
1385
|
+
if (simError instanceof Error && simError.message.includes("Transaction simulation failed")) {
|
|
1386
|
+
throw simError;
|
|
1387
|
+
}
|
|
1388
|
+
const err = simError;
|
|
1389
|
+
throw new Error(
|
|
1390
|
+
`Failed to simulate transaction: ${err.message}
|
|
1391
|
+
VK Account: ${vk}
|
|
1392
|
+
Network: ${this._network}
|
|
1393
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1394
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1395
|
+
);
|
|
1396
|
+
}
|
|
1397
|
+
let signature;
|
|
1398
|
+
try {
|
|
1399
|
+
signature = await wallet.sendTransaction(tx, connection);
|
|
1400
|
+
} catch (sendError) {
|
|
1401
|
+
const originalError = sendError;
|
|
1402
|
+
const enhancedError = new Error(
|
|
1403
|
+
`Failed to send verify transaction: ${originalError.message}
|
|
1404
|
+
VK Account: ${vk}
|
|
1405
|
+
Network: ${this._network}
|
|
1406
|
+
Proof size: ${proofData.proof.bytes.length} bytes
|
|
1407
|
+
Public inputs: ${proofData.publicInputs.hex.length} items`
|
|
1408
|
+
);
|
|
1409
|
+
enhancedError.cause = originalError;
|
|
1410
|
+
throw enhancedError;
|
|
1411
|
+
}
|
|
1412
|
+
try {
|
|
1413
|
+
await connection.confirmTransaction({
|
|
1414
|
+
signature,
|
|
1415
|
+
blockhash,
|
|
1416
|
+
lastValidBlockHeight
|
|
1417
|
+
});
|
|
1418
|
+
} catch (confirmError) {
|
|
1419
|
+
const err = confirmError;
|
|
1420
|
+
throw new Error(
|
|
1421
|
+
`Transaction sent but confirmation failed: ${err.message}
|
|
1422
|
+
Signature: ${signature}
|
|
1423
|
+
Check on explorer: ${getExplorerTxUrl(this._network, signature)}`
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1405
1426
|
return {
|
|
1406
1427
|
verified: true,
|
|
1407
1428
|
signature,
|