@aztec/bb.js 0.76.4-devnet-test-rc3 → 0.77.0-testnet-ignition.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +10 -2
  2. package/dest/browser/barretenberg/backend.d.ts +5 -1
  3. package/dest/browser/barretenberg/backend.d.ts.map +1 -1
  4. package/dest/browser/barretenberg/index.d.ts +3 -1
  5. package/dest/browser/barretenberg/index.d.ts.map +1 -1
  6. package/dest/browser/barretenberg-threads.js +1 -1
  7. package/dest/browser/barretenberg.js +1 -1
  8. package/dest/browser/barretenberg_api/index.d.ts +1 -0
  9. package/dest/browser/barretenberg_api/index.d.ts.map +1 -1
  10. package/dest/browser/barretenberg_wasm/barretenberg_wasm_base/index.d.ts.map +1 -1
  11. package/dest/browser/barretenberg_wasm/barretenberg_wasm_main/index.d.ts.map +1 -1
  12. package/dest/browser/barretenberg_wasm/fetch_code/browser/index.d.ts.map +1 -1
  13. package/dest/browser/barretenberg_wasm/index.d.ts +2 -2
  14. package/dest/browser/barretenberg_wasm/index.d.ts.map +1 -1
  15. package/dest/browser/crs/net_crs.d.ts.map +1 -1
  16. package/dest/browser/crs/node/index.d.ts +6 -4
  17. package/dest/browser/crs/node/index.d.ts.map +1 -1
  18. package/dest/browser/index.js +98 -38
  19. package/dest/browser/retry/index.d.ts +26 -0
  20. package/dest/browser/retry/index.d.ts.map +1 -0
  21. package/dest/node/barretenberg/__snapshots__/pedersen.test.js.snap +156 -0
  22. package/dest/node/barretenberg/__snapshots__/poseidon.test.js.snap +40 -0
  23. package/dest/node/barretenberg/backend.d.ts +5 -1
  24. package/dest/node/barretenberg/backend.d.ts.map +1 -1
  25. package/dest/node/barretenberg/backend.js +21 -4
  26. package/dest/node/barretenberg/index.d.ts +3 -1
  27. package/dest/node/barretenberg/index.d.ts.map +1 -1
  28. package/dest/node/barretenberg/index.js +11 -12
  29. package/dest/node/barretenberg_api/index.d.ts +1 -0
  30. package/dest/node/barretenberg_api/index.d.ts.map +1 -1
  31. package/dest/node/barretenberg_api/index.js +25 -1
  32. package/dest/node/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  33. package/dest/node/barretenberg_wasm/barretenberg_wasm_base/index.d.ts.map +1 -1
  34. package/dest/node/barretenberg_wasm/barretenberg_wasm_base/index.js +5 -6
  35. package/dest/node/barretenberg_wasm/barretenberg_wasm_main/index.d.ts.map +1 -1
  36. package/dest/node/barretenberg_wasm/barretenberg_wasm_main/index.js +6 -7
  37. package/dest/node/barretenberg_wasm/fetch_code/browser/index.d.ts.map +1 -1
  38. package/dest/node/barretenberg_wasm/fetch_code/browser/index.js +5 -2
  39. package/dest/node/barretenberg_wasm/fetch_code/node/index.js +2 -2
  40. package/dest/node/barretenberg_wasm/index.d.ts +2 -2
  41. package/dest/node/barretenberg_wasm/index.d.ts.map +1 -1
  42. package/dest/node/barretenberg_wasm/index.js +11 -9
  43. package/dest/node/barretenberg_wasm/index.test.js +3 -3
  44. package/dest/node/crs/net_crs.d.ts.map +1 -1
  45. package/dest/node/crs/net_crs.js +6 -5
  46. package/dest/node/crs/node/index.d.ts +6 -4
  47. package/dest/node/crs/node/index.d.ts.map +1 -1
  48. package/dest/node/crs/node/index.js +16 -13
  49. package/dest/node/examples/simple.test.js +2 -2
  50. package/dest/node/main.d.ts.map +1 -1
  51. package/dest/node/main.js +55 -65
  52. package/dest/node/retry/index.d.ts +26 -0
  53. package/dest/node/retry/index.d.ts.map +1 -0
  54. package/dest/node/retry/index.js +50 -0
  55. package/dest/node-cjs/barretenberg/backend.d.ts +5 -1
  56. package/dest/node-cjs/barretenberg/backend.d.ts.map +1 -1
  57. package/dest/node-cjs/barretenberg/backend.js +23 -5
  58. package/dest/node-cjs/barretenberg/index.d.ts +3 -1
  59. package/dest/node-cjs/barretenberg/index.d.ts.map +1 -1
  60. package/dest/node-cjs/barretenberg/index.js +11 -12
  61. package/dest/node-cjs/barretenberg_api/index.d.ts +1 -0
  62. package/dest/node-cjs/barretenberg_api/index.d.ts.map +1 -1
  63. package/dest/node-cjs/barretenberg_api/index.js +25 -1
  64. package/dest/node-cjs/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  65. package/dest/node-cjs/barretenberg_wasm/barretenberg_wasm_base/index.d.ts.map +1 -1
  66. package/dest/node-cjs/barretenberg_wasm/barretenberg_wasm_base/index.js +5 -6
  67. package/dest/node-cjs/barretenberg_wasm/barretenberg_wasm_main/index.d.ts.map +1 -1
  68. package/dest/node-cjs/barretenberg_wasm/barretenberg_wasm_main/index.js +6 -7
  69. package/dest/node-cjs/barretenberg_wasm/fetch_code/browser/index.d.ts.map +1 -1
  70. package/dest/node-cjs/barretenberg_wasm/fetch_code/browser/index.js +5 -2
  71. package/dest/node-cjs/barretenberg_wasm/fetch_code/node/index.js +2 -2
  72. package/dest/node-cjs/barretenberg_wasm/index.d.ts +2 -2
  73. package/dest/node-cjs/barretenberg_wasm/index.d.ts.map +1 -1
  74. package/dest/node-cjs/barretenberg_wasm/index.js +11 -9
  75. package/dest/node-cjs/barretenberg_wasm/index.test.js +3 -3
  76. package/dest/node-cjs/crs/net_crs.d.ts.map +1 -1
  77. package/dest/node-cjs/crs/net_crs.js +6 -5
  78. package/dest/node-cjs/crs/node/index.d.ts +6 -4
  79. package/dest/node-cjs/crs/node/index.d.ts.map +1 -1
  80. package/dest/node-cjs/crs/node/index.js +16 -13
  81. package/dest/node-cjs/examples/simple.test.js +2 -2
  82. package/dest/node-cjs/main.d.ts.map +1 -1
  83. package/dest/node-cjs/main.js +55 -65
  84. package/dest/node-cjs/retry/index.d.ts +26 -0
  85. package/dest/node-cjs/retry/index.d.ts.map +1 -0
  86. package/dest/node-cjs/retry/index.js +56 -0
  87. package/package.json +3 -3
  88. package/src/barretenberg/backend.ts +22 -3
  89. package/src/barretenberg/index.ts +19 -12
  90. package/src/barretenberg_api/index.ts +35 -0
  91. package/src/barretenberg_wasm/barretenberg_wasm_base/index.ts +4 -6
  92. package/src/barretenberg_wasm/barretenberg_wasm_main/index.ts +5 -7
  93. package/src/barretenberg_wasm/fetch_code/browser/index.ts +4 -1
  94. package/src/barretenberg_wasm/fetch_code/node/index.ts +1 -1
  95. package/src/barretenberg_wasm/index.test.ts +2 -2
  96. package/src/barretenberg_wasm/index.ts +21 -10
  97. package/src/crs/net_crs.ts +18 -9
  98. package/src/crs/node/index.ts +31 -15
  99. package/src/examples/simple.test.ts +1 -1
  100. package/src/main.ts +59 -70
  101. package/src/retry/index.ts +50 -0
package/src/main.ts CHANGED
@@ -22,18 +22,18 @@ const debug = createDebug('bb.js');
22
22
  const MAX_ULTRAPLONK_CIRCUIT_SIZE_IN_WASM = 2 ** 19;
23
23
  const threads = +process.env.HARDWARE_CONCURRENCY! || undefined;
24
24
 
25
- function getBytecode(bytecodePath: string) {
25
+ function getBytecode(bytecodePath: string): Uint8Array {
26
26
  const extension = bytecodePath.substring(bytecodePath.lastIndexOf('.') + 1);
27
27
 
28
28
  if (extension == 'json') {
29
29
  const encodedCircuit = JSON.parse(readFileSync(bytecodePath, 'utf8'));
30
30
  const decompressed = gunzipSync(Buffer.from(encodedCircuit.bytecode, 'base64'));
31
- return decompressed;
31
+ return Uint8Array.from(decompressed);
32
32
  }
33
33
 
34
34
  const encodedCircuit = readFileSync(bytecodePath);
35
35
  const decompressed = gunzipSync(encodedCircuit);
36
- return decompressed;
36
+ return Uint8Array.from(decompressed);
37
37
  }
38
38
 
39
39
  function base64ToUint8Array(base64: string) {
@@ -62,14 +62,14 @@ async function getGatesUltra(bytecodePath: string, recursive: boolean, honkRecur
62
62
  return total;
63
63
  }
64
64
 
65
- function getWitness(witnessPath: string) {
65
+ function getWitness(witnessPath: string): Uint8Array {
66
66
  const data = readFileSync(witnessPath);
67
67
  const decompressed = gunzipSync(data);
68
- return decompressed;
68
+ return Uint8Array.from(decompressed);
69
69
  }
70
70
 
71
71
  async function computeCircuitSize(bytecodePath: string, recursive: boolean, honkRecursion: boolean, api: Barretenberg) {
72
- debug(`computing circuit size...`);
72
+ debug(`Computing circuit size for ${bytecodePath}`);
73
73
  const bytecode = getBytecode(bytecodePath);
74
74
  const [total, subgroup] = await api.acirGetCircuitSizes(bytecode, recursive, honkRecursion);
75
75
  return { total, subgroup };
@@ -93,9 +93,7 @@ async function initUltraPlonk(
93
93
  if (subgroupSize > MAX_ULTRAPLONK_CIRCUIT_SIZE_IN_WASM) {
94
94
  throw new Error(`Circuit size of ${subgroupSize} exceeds max supported of ${MAX_ULTRAPLONK_CIRCUIT_SIZE_IN_WASM}`);
95
95
  }
96
- debug(`circuit size: ${circuitSize}`);
97
- debug(`subgroup size: ${subgroupSize}`);
98
- debug('loading crs...');
96
+ debug(`Loading CRS for UltraPlonk with circuit-size=${circuitSize} subgroup-size=${subgroupSize}`);
99
97
  // Plus 1 needed! (Move +1 into Crs?)
100
98
  const crs = await Crs.new(subgroupSize + 1, crsPath);
101
99
 
@@ -119,9 +117,7 @@ async function initUltraHonk(bytecodePath: string, recursive: boolean, crsPath:
119
117
  // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): remove subgroupSizeOverride hack for goblin
120
118
  const dyadicCircuitSize = Math.pow(2, Math.ceil(Math.log2(circuitSize)));
121
119
 
122
- debug(`circuit size: ${circuitSize}`);
123
- debug(`dyadic circuit size size: ${dyadicCircuitSize}`);
124
- debug('loading crs...');
120
+ debug(`Loading CRS for UltraHonk with circuit-size=${circuitSize} dyadic-circuit-size=${dyadicCircuitSize}`);
125
121
  const crs = await Crs.new(dyadicCircuitSize + 1, crsPath);
126
122
 
127
123
  // Load CRS into wasm global CRS state.
@@ -133,7 +129,7 @@ async function initUltraHonk(bytecodePath: string, recursive: boolean, crsPath:
133
129
  async function initClientIVC(crsPath: string) {
134
130
  const api = await Barretenberg.new({ threads });
135
131
 
136
- debug('loading BN254 and Grumpkin crs...');
132
+ debug('Loading CRS for ClientIVC');
137
133
  const crs = await Crs.new(2 ** 21 + 1, crsPath);
138
134
  const grumpkinCrs = await GrumpkinCrs.new(2 ** 16 + 1, crsPath);
139
135
 
@@ -163,7 +159,7 @@ export async function proveAndVerify(bytecodePath: string, recursive: boolean, w
163
159
 
164
160
  const { api, acirComposer, circuitSize, subgroupSize } = await initUltraPlonk(bytecodePath, recursive, crsPath);
165
161
  try {
166
- debug(`creating proof...`);
162
+ debug(`Creating proof bytecode=${bytecodePath} witness=${witnessPath} recursive=${recursive}`);
167
163
  const bytecode = getBytecode(bytecodePath);
168
164
  const witness = getWitness(witnessPath);
169
165
 
@@ -177,9 +173,9 @@ export async function proveAndVerify(bytecodePath: string, recursive: boolean, w
177
173
  const proof = await api.acirCreateProof(acirComposer, bytecode, recursive, witness);
178
174
  writeBenchmark('proof_construction_time', proofTimer.ms(), { acir_test, threads });
179
175
 
180
- debug(`verifying...`);
176
+ debug(`Proof complete. Verifying.`);
181
177
  const verified = await api.acirVerifyProof(acirComposer, proof);
182
- debug(`verified: ${verified}`);
178
+ debug(`Verification ${verified ? 'successful' : 'failed'}`);
183
179
  return verified;
184
180
  } finally {
185
181
  await api.destroy();
@@ -235,7 +231,7 @@ export async function proveAndVerifyAztecClient(bytecodePath: string, witnessPat
235
231
  const witness = readStack(witnessPath);
236
232
 
237
233
  const verified = await api.acirProveAndVerifyAztecClient(bytecode, witness);
238
- console.log(`verified?: ${verified}`);
234
+ debug(`Verification ${verified ? 'successful' : 'failed'}`);
239
235
  return verified;
240
236
  } finally {
241
237
  await api.destroy();
@@ -256,7 +252,7 @@ export async function foldAndVerifyProgram(
256
252
  const witness = getWitness(witnessPath);
257
253
 
258
254
  const verified = await api.acirFoldAndVerifyProgramStack(bytecode, recursive, witness);
259
- debug(`verified: ${verified}`);
255
+ debug(`Verification ${verified ? 'successful' : 'failed'}`);
260
256
  return verified;
261
257
  } finally {
262
258
  await api.destroy();
@@ -273,18 +269,17 @@ export async function prove(
273
269
  ) {
274
270
  const { api, acirComposer } = await initUltraPlonk(bytecodePath, recursive, crsPath);
275
271
  try {
276
- debug(`creating proof...`);
272
+ debug(`Creating proof bytecode=${bytecodePath} witness=${witnessPath} recursive=${recursive}`);
277
273
  const bytecode = getBytecode(bytecodePath);
278
274
  const witness = getWitness(witnessPath);
279
275
  const proof = await api.acirCreateProof(acirComposer, bytecode, recursive, witness);
280
- debug(`done.`);
281
276
 
282
277
  if (outputPath === '-') {
283
278
  process.stdout.write(proof);
284
- debug(`proof written to stdout`);
279
+ debug(`Proof written to stdout`);
285
280
  } else {
286
281
  writeFileSync(outputPath, proof);
287
- debug(`proof written to: ${outputPath}`);
282
+ debug(`Proof written to ${outputPath}`);
288
283
  }
289
284
  } finally {
290
285
  await api.destroy();
@@ -295,14 +290,14 @@ export async function gateCountUltra(bytecodePath: string, recursive: boolean, h
295
290
  const api = await Barretenberg.new({ threads: 1 });
296
291
  try {
297
292
  const numberOfGates = await getGatesUltra(bytecodePath, recursive, honkRecursion, api);
298
- debug(`number of gates: : ${numberOfGates}`);
293
+ debug(`Number of gates: ${numberOfGates}`);
299
294
  // Create an 8-byte buffer and write the number into it.
300
295
  // Writing number directly to stdout will result in a variable sized
301
296
  // input depending on the size.
302
297
  const buffer = Buffer.alloc(8);
303
298
  buffer.writeBigInt64LE(BigInt(numberOfGates));
304
299
 
305
- process.stdout.write(buffer);
300
+ process.stdout.write(Uint8Array.from(buffer));
306
301
  } finally {
307
302
  await api.destroy();
308
303
  }
@@ -312,8 +307,8 @@ export async function verify(proofPath: string, vkPath: string, crsPath: string)
312
307
  const { api, acirComposer } = await initLite(crsPath);
313
308
  try {
314
309
  await api.acirLoadVerificationKey(acirComposer, new RawBuffer(readFileSync(vkPath)));
315
- const verified = await api.acirVerifyProof(acirComposer, readFileSync(proofPath));
316
- debug(`verified: ${verified}`);
310
+ const verified = await api.acirVerifyProof(acirComposer, Uint8Array.from(readFileSync(proofPath)));
311
+ debug(`Verification ${verified ? 'successful' : 'failed'}`);
317
312
  return verified;
318
313
  } finally {
319
314
  await api.destroy();
@@ -323,15 +318,16 @@ export async function verify(proofPath: string, vkPath: string, crsPath: string)
323
318
  export async function contract(outputPath: string, vkPath: string, crsPath: string) {
324
319
  const { api, acirComposer } = await initLite(crsPath);
325
320
  try {
321
+ debug(`Creating verifier contract vk=${vkPath}`);
326
322
  await api.acirLoadVerificationKey(acirComposer, new RawBuffer(readFileSync(vkPath)));
327
323
  const contract = await api.acirGetSolidityVerifier(acirComposer);
328
324
 
329
325
  if (outputPath === '-') {
330
326
  process.stdout.write(contract);
331
- debug(`contract written to stdout`);
327
+ debug(`Solidity verifier contract written to stdout`);
332
328
  } else {
333
329
  writeFileSync(outputPath, contract);
334
- debug(`contract written to: ${outputPath}`);
330
+ debug(`Solidity verifier contract written to ${outputPath}`);
335
331
  }
336
332
  } finally {
337
333
  await api.destroy();
@@ -341,18 +337,17 @@ export async function contract(outputPath: string, vkPath: string, crsPath: stri
341
337
  export async function contractUltraHonk(bytecodePath: string, vkPath: string, crsPath: string, outputPath: string) {
342
338
  const { api } = await initUltraHonk(bytecodePath, false, crsPath);
343
339
  try {
344
- console.log('bytecodePath', bytecodePath);
340
+ debug(`Creating UltraHonk verifier contract bytecode=${bytecodePath} vk=${vkPath}`);
345
341
  const bytecode = getBytecode(bytecodePath);
346
- console.log('vkPath', vkPath);
347
342
  const vk = new RawBuffer(readFileSync(vkPath));
348
343
  const contract = await api.acirHonkSolidityVerifier(bytecode, vk);
349
344
 
350
345
  if (outputPath === '-') {
351
346
  process.stdout.write(contract);
352
- debug(`contract written to stdout`);
347
+ debug(`Solidity verifier contract written to stdout`);
353
348
  } else {
354
349
  writeFileSync(outputPath, contract);
355
- debug(`contract written to: ${outputPath}`);
350
+ debug(`Solidity verifier contract written to ${outputPath}`);
356
351
  }
357
352
  } finally {
358
353
  await api.destroy();
@@ -362,19 +357,19 @@ export async function contractUltraHonk(bytecodePath: string, vkPath: string, cr
362
357
  export async function writeVk(bytecodePath: string, recursive: boolean, crsPath: string, outputPath: string) {
363
358
  const { api, acirComposer } = await initUltraPlonk(bytecodePath, recursive, crsPath);
364
359
  try {
365
- debug('initing proving key...');
360
+ debug(`Initializing proving key bytecode=${bytecodePath} recursive=${recursive}`);
366
361
  const bytecode = getBytecode(bytecodePath);
367
362
  await api.acirInitProvingKey(acirComposer, bytecode, recursive);
368
363
 
369
- debug('initing verification key...');
364
+ debug(`Initializing verification key`);
370
365
  const vk = await api.acirGetVerificationKey(acirComposer);
371
366
 
372
367
  if (outputPath === '-') {
373
368
  process.stdout.write(vk);
374
- debug(`vk written to stdout`);
369
+ debug(`Verification key written to stdout`);
375
370
  } else {
376
371
  writeFileSync(outputPath, vk);
377
- debug(`vk written to: ${outputPath}`);
372
+ debug(`Verification key written to ${outputPath}`);
378
373
  }
379
374
  } finally {
380
375
  await api.destroy();
@@ -384,16 +379,16 @@ export async function writeVk(bytecodePath: string, recursive: boolean, crsPath:
384
379
  export async function writePk(bytecodePath: string, recursive: boolean, crsPath: string, outputPath: string) {
385
380
  const { api, acirComposer } = await initUltraPlonk(bytecodePath, recursive, crsPath);
386
381
  try {
387
- debug('initing proving key...');
382
+ debug(`Initializing proving key bytecode=${bytecodePath} recursive=${recursive}`);
388
383
  const bytecode = getBytecode(bytecodePath);
389
384
  const pk = await api.acirGetProvingKey(acirComposer, bytecode, recursive);
390
385
 
391
386
  if (outputPath === '-') {
392
387
  process.stdout.write(pk);
393
- debug(`pk written to stdout`);
388
+ debug(`Proving key written to stdout`);
394
389
  } else {
395
390
  writeFileSync(outputPath, pk);
396
- debug(`pk written to: ${outputPath}`);
391
+ debug(`Proving key written to ${outputPath}`);
397
392
  }
398
393
  } finally {
399
394
  await api.destroy();
@@ -404,24 +399,22 @@ export async function proofAsFields(proofPath: string, vkPath: string, outputPat
404
399
  const { api, acirComposer } = await initLite(crsPath);
405
400
 
406
401
  try {
407
- debug('serializing proof byte array into field elements');
402
+ debug(`Serializing proof byte array into field elements proof=${proofPath} vk=${vkPath}`);
408
403
  const numPublicInputs = readFileSync(vkPath).readUint32BE(8);
409
404
  const proofAsFields = await api.acirSerializeProofIntoFields(
410
405
  acirComposer,
411
- readFileSync(proofPath),
406
+ Uint8Array.from(readFileSync(proofPath)),
412
407
  numPublicInputs,
413
408
  );
414
409
  const jsonProofAsFields = JSON.stringify(proofAsFields.map(f => f.toString()));
415
410
 
416
411
  if (outputPath === '-') {
417
412
  process.stdout.write(jsonProofAsFields);
418
- debug(`proofAsFields written to stdout`);
413
+ debug(`Proof as fields written to stdout`);
419
414
  } else {
420
415
  writeFileSync(outputPath, jsonProofAsFields);
421
- debug(`proofAsFields written to: ${outputPath}`);
416
+ debug(`Proof as fields written to ${outputPath}`);
422
417
  }
423
-
424
- debug('done.');
425
418
  } finally {
426
419
  await api.destroy();
427
420
  }
@@ -431,7 +424,7 @@ export async function vkAsFields(vkPath: string, vkeyOutputPath: string, crsPath
431
424
  const { api, acirComposer } = await initLite(crsPath);
432
425
 
433
426
  try {
434
- debug('serializing vk byte array into field elements');
427
+ debug(`Serializing vk byte array into field elements vk=${vkPath}`);
435
428
  await api.acirLoadVerificationKey(acirComposer, new RawBuffer(readFileSync(vkPath)));
436
429
  const [vkAsFields, vkHash] = await api.acirSerializeVerificationKeyIntoFields(acirComposer);
437
430
  const output = [vkHash, ...vkAsFields].map(f => f.toString());
@@ -439,13 +432,11 @@ export async function vkAsFields(vkPath: string, vkeyOutputPath: string, crsPath
439
432
 
440
433
  if (vkeyOutputPath === '-') {
441
434
  process.stdout.write(jsonVKAsFields);
442
- debug(`vkAsFields written to stdout`);
435
+ debug(`Verification key as fields written to stdout`);
443
436
  } else {
444
437
  writeFileSync(vkeyOutputPath, jsonVKAsFields);
445
- debug(`vkAsFields written to: ${vkeyOutputPath}`);
438
+ debug(`Verification key as fields written to ${vkeyOutputPath}`);
446
439
  }
447
-
448
- debug('done.');
449
440
  } finally {
450
441
  await api.destroy();
451
442
  }
@@ -461,7 +452,7 @@ export async function proveUltraHonk(
461
452
  ) {
462
453
  const { api } = await initUltraHonk(bytecodePath, recursive, crsPath);
463
454
  try {
464
- debug(`creating proof...`);
455
+ debug(`Creating UltraHonk proof bytecode=${bytecodePath} recursive=${recursive}`);
465
456
  const bytecode = getBytecode(bytecodePath);
466
457
  const witness = getWitness(witnessPath);
467
458
 
@@ -469,14 +460,13 @@ export async function proveUltraHonk(
469
460
  ? api.acirProveUltraKeccakHonk.bind(api)
470
461
  : api.acirProveUltraHonk.bind(api);
471
462
  const proof = await acirProveUltraHonk(bytecode, recursive, witness);
472
- debug(`done.`);
473
463
 
474
464
  if (outputPath === '-') {
475
465
  process.stdout.write(proof);
476
- debug(`proof written to stdout`);
466
+ debug(`Proof written to stdout`);
477
467
  } else {
478
468
  writeFileSync(outputPath, proof);
479
- debug(`proof written to: ${outputPath}`);
469
+ debug(`Proof written to ${outputPath}`);
480
470
  }
481
471
  } finally {
482
472
  await api.destroy();
@@ -493,7 +483,7 @@ export async function writeVkUltraHonk(
493
483
  const { api } = await initUltraHonk(bytecodePath, recursive, crsPath);
494
484
  try {
495
485
  const bytecode = getBytecode(bytecodePath);
496
- debug('initing verification key...');
486
+ debug(`Initializing UltraHonk verification key bytecode=${bytecodePath} recursive=${recursive}`);
497
487
 
498
488
  const acirWriteVkUltraHonk = options?.keccak
499
489
  ? api.acirWriteVkUltraKeccakHonk.bind(api)
@@ -502,10 +492,10 @@ export async function writeVkUltraHonk(
502
492
 
503
493
  if (outputPath === '-') {
504
494
  process.stdout.write(vk);
505
- debug(`vk written to stdout`);
495
+ debug(`Verification key written to stdout`);
506
496
  } else {
507
497
  writeFileSync(outputPath, vk);
508
- debug(`vk written to: ${outputPath}`);
498
+ debug(`Verification key written to ${outputPath}`);
509
499
  }
510
500
  } finally {
511
501
  await api.destroy();
@@ -523,9 +513,12 @@ export async function verifyUltraHonk(
523
513
  const acirVerifyUltraHonk = options?.keccak
524
514
  ? api.acirVerifyUltraKeccakHonk.bind(api)
525
515
  : api.acirVerifyUltraHonk.bind(api);
526
- const verified = await acirVerifyUltraHonk(readFileSync(proofPath), new RawBuffer(readFileSync(vkPath)));
516
+ const verified = await acirVerifyUltraHonk(
517
+ Uint8Array.from(readFileSync(proofPath)),
518
+ new RawBuffer(readFileSync(vkPath)),
519
+ );
527
520
 
528
- debug(`verified: ${verified}`);
521
+ debug(`Verification ${verified ? 'successful' : 'failed'}`);
529
522
  return verified;
530
523
  } finally {
531
524
  await api.destroy();
@@ -535,19 +528,17 @@ export async function verifyUltraHonk(
535
528
  export async function proofAsFieldsUltraHonk(proofPath: string, outputPath: string, crsPath: string) {
536
529
  const { api } = await initLite(crsPath);
537
530
  try {
538
- debug('outputting proof as vector of fields');
539
- const proofAsFields = await api.acirProofAsFieldsUltraHonk(readFileSync(proofPath));
531
+ debug(`Outputting UltraHonk proof as vector of fields proof=${proofPath}`);
532
+ const proofAsFields = await api.acirProofAsFieldsUltraHonk(Uint8Array.from(readFileSync(proofPath)));
540
533
  const jsonProofAsFields = JSON.stringify(proofAsFields.map(f => f.toString()));
541
534
 
542
535
  if (outputPath === '-') {
543
536
  process.stdout.write(jsonProofAsFields);
544
- debug(`proofAsFieldsUltraHonk written to stdout`);
537
+ debug(`Proof as fields written to stdout`);
545
538
  } else {
546
539
  writeFileSync(outputPath, jsonProofAsFields);
547
- debug(`proofAsFieldsUltraHonk written to: ${outputPath}`);
540
+ debug(`Proof as fields written to ${outputPath}`);
548
541
  }
549
-
550
- debug('done.');
551
542
  } finally {
552
543
  await api.destroy();
553
544
  }
@@ -557,19 +548,17 @@ export async function vkAsFieldsUltraHonk(vkPath: string, vkeyOutputPath: string
557
548
  const { api } = await initLite(crsPath);
558
549
 
559
550
  try {
560
- debug('serializing vk byte array into field elements');
551
+ debug(`Serializing vk byte array into field elements vk=${vkPath}`);
561
552
  const vkAsFields = await api.acirVkAsFieldsUltraHonk(new RawBuffer(readFileSync(vkPath)));
562
553
  const jsonVKAsFields = JSON.stringify(vkAsFields.map(f => f.toString()));
563
554
 
564
555
  if (vkeyOutputPath === '-') {
565
556
  process.stdout.write(jsonVKAsFields);
566
- debug(`vkAsFieldsUltraHonk written to stdout`);
557
+ debug(`Verification key as fields written to stdout`);
567
558
  } else {
568
559
  writeFileSync(vkeyOutputPath, jsonVKAsFields);
569
- debug(`vkAsFieldsUltraHonk written to: ${vkeyOutputPath}`);
560
+ debug(`Verification key as fields written to ${vkeyOutputPath}`);
570
561
  }
571
-
572
- debug('done.');
573
562
  } finally {
574
563
  await api.destroy();
575
564
  }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Generates a backoff sequence for retrying operations with an increasing delay.
3
+ * The backoff sequence follows this pattern: 1, 1, 1, 2, 4, 8, 16, 32, 64, ...
4
+ * This generator can be used in combination with the `retry` function to perform
5
+ * retries with exponential backoff and capped at 64 seconds between attempts.
6
+ *
7
+ * @returns A generator that yields the next backoff value in seconds as an integer.
8
+ */
9
+ export function* backoffGenerator() {
10
+ const v = [1, 1, 1, 2, 4, 8, 16, 32, 64];
11
+ let i = 0;
12
+ while (true) {
13
+ yield v[Math.min(i++, v.length - 1)];
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Generates a backoff sequence based on the array of retry intervals to use with the `retry` function.
19
+ * @param retries - Intervals to retry (in seconds).
20
+ * @returns A generator sequence.
21
+ */
22
+ export function* makeBackoff(retries: number[]) {
23
+ for (const retry of retries) {
24
+ yield retry;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Retry a given asynchronous function with a specific backoff strategy, until it succeeds or backoff generator ends.
30
+ * It logs the error and retry interval in case an error is caught. The function can be named for better log output.
31
+ *
32
+ * @param fn - The asynchronous function to be retried.
33
+ * @param backoff - The optional backoff generator providing the intervals in seconds between retries. Defaults to a predefined series.
34
+ * @returns A Promise that resolves with the successful result of the provided function, or rejects if backoff generator ends.
35
+ * @throws If `NoRetryError` is thrown by the `fn`, it is rethrown.
36
+ */
37
+ export async function retry<Result>(fn: () => Promise<Result>, backoff = backoffGenerator()) {
38
+ while (true) {
39
+ try {
40
+ return await fn();
41
+ } catch (err: any) {
42
+ const s = backoff.next().value;
43
+ if (s === undefined) {
44
+ throw err;
45
+ }
46
+ await new Promise(resolve => setTimeout(resolve, s * 1000));
47
+ continue;
48
+ }
49
+ }
50
+ }