@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
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.retry = exports.makeBackoff = exports.backoffGenerator = void 0;
4
+ /**
5
+ * Generates a backoff sequence for retrying operations with an increasing delay.
6
+ * The backoff sequence follows this pattern: 1, 1, 1, 2, 4, 8, 16, 32, 64, ...
7
+ * This generator can be used in combination with the `retry` function to perform
8
+ * retries with exponential backoff and capped at 64 seconds between attempts.
9
+ *
10
+ * @returns A generator that yields the next backoff value in seconds as an integer.
11
+ */
12
+ function* backoffGenerator() {
13
+ const v = [1, 1, 1, 2, 4, 8, 16, 32, 64];
14
+ let i = 0;
15
+ while (true) {
16
+ yield v[Math.min(i++, v.length - 1)];
17
+ }
18
+ }
19
+ exports.backoffGenerator = backoffGenerator;
20
+ /**
21
+ * Generates a backoff sequence based on the array of retry intervals to use with the `retry` function.
22
+ * @param retries - Intervals to retry (in seconds).
23
+ * @returns A generator sequence.
24
+ */
25
+ function* makeBackoff(retries) {
26
+ for (const retry of retries) {
27
+ yield retry;
28
+ }
29
+ }
30
+ exports.makeBackoff = makeBackoff;
31
+ /**
32
+ * Retry a given asynchronous function with a specific backoff strategy, until it succeeds or backoff generator ends.
33
+ * It logs the error and retry interval in case an error is caught. The function can be named for better log output.
34
+ *
35
+ * @param fn - The asynchronous function to be retried.
36
+ * @param backoff - The optional backoff generator providing the intervals in seconds between retries. Defaults to a predefined series.
37
+ * @returns A Promise that resolves with the successful result of the provided function, or rejects if backoff generator ends.
38
+ * @throws If `NoRetryError` is thrown by the `fn`, it is rethrown.
39
+ */
40
+ async function retry(fn, backoff = backoffGenerator()) {
41
+ while (true) {
42
+ try {
43
+ return await fn();
44
+ }
45
+ catch (err) {
46
+ const s = backoff.next().value;
47
+ if (s === undefined) {
48
+ throw err;
49
+ }
50
+ await new Promise(resolve => setTimeout(resolve, s * 1000));
51
+ continue;
52
+ }
53
+ }
54
+ }
55
+ exports.retry = retry;
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcmV0cnkvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUE7Ozs7Ozs7R0FPRztBQUNILFFBQWUsQ0FBQyxDQUFDLGdCQUFnQjtJQUMvQixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDekMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUNaLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7QUFDSCxDQUFDO0FBTkQsNENBTUM7QUFFRDs7OztHQUlHO0FBQ0gsUUFBZSxDQUFDLENBQUMsV0FBVyxDQUFDLE9BQWlCO0lBQzVDLEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7UUFDNUIsTUFBTSxLQUFLLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUpELGtDQUlDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSSxLQUFLLFVBQVUsS0FBSyxDQUFTLEVBQXlCLEVBQUUsT0FBTyxHQUFHLGdCQUFnQixFQUFFO0lBQ3pGLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDWixJQUFJLENBQUM7WUFDSCxPQUFPLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDcEIsQ0FBQztRQUFDLE9BQU8sR0FBUSxFQUFFLENBQUM7WUFDbEIsTUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQztZQUMvQixJQUFJLENBQUMsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxHQUFHLENBQUM7WUFDWixDQUFDO1lBQ0QsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDNUQsU0FBUztRQUNYLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQWJELHNCQWFDIn0=
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aztec/bb.js",
3
3
  "packageManager": "yarn@4.5.2",
4
- "version": "0.76.4-devnet-test-rc3",
4
+ "version": "0.77.0-testnet-ignition.4",
5
5
  "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts",
6
6
  "license": "MIT",
7
7
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "default": "./dest/node/index.js"
14
14
  }
15
15
  },
16
- "bin": "./dest/node/main.js",
16
+ "bin": "dest/node/main.js",
17
17
  "files": [
18
18
  "src/",
19
19
  "dest/",
@@ -96,7 +96,7 @@
96
96
  "ts-jest": "^29.1.0",
97
97
  "ts-loader": "^9.4.2",
98
98
  "ts-node": "^10.9.1",
99
- "typescript": "^5.0.4",
99
+ "typescript": "5.4.5",
100
100
  "webpack": "^5.82.1",
101
101
  "webpack-cli": "^5.1.1",
102
102
  "webpack-dev-server": "^5.2.0",
@@ -10,6 +10,12 @@ import {
10
10
  reconstructUltraPlonkProof,
11
11
  } from '../proof/index.js';
12
12
 
13
+ export class AztecClientBackendError extends Error {
14
+ constructor(message: string) {
15
+ super(message);
16
+ }
17
+ }
18
+
13
19
  export class UltraPlonkBackend {
14
20
  // These type assertions are used so that we don't
15
21
  // have to initialize `api` and `acirComposer` in the constructor.
@@ -302,9 +308,11 @@ export class UltraHonkBackend {
302
308
  return await verifyUltraHonk(proof, new RawBuffer(vkBuf));
303
309
  }
304
310
 
305
- async getVerificationKey(): Promise<Uint8Array> {
311
+ async getVerificationKey(options?: UltraHonkBackendOptions): Promise<Uint8Array> {
306
312
  await this.instantiate();
307
- return await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode, this.circuitOptions.recursive);
313
+ return options?.keccak
314
+ ? await this.api.acirWriteVkUltraKeccakHonk(this.acirUncompressedBytecode, this.circuitOptions.recursive)
315
+ : await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode, this.circuitOptions.recursive);
308
316
  }
309
317
 
310
318
  /** @description Returns a solidity verifier */
@@ -376,7 +384,12 @@ export class AztecClientBackend {
376
384
 
377
385
  async prove(witnessMsgpack: Uint8Array[]): Promise<[Uint8Array, Uint8Array]> {
378
386
  await this.instantiate();
379
- return this.api.acirProveAztecClient(this.acirMsgpack, witnessMsgpack);
387
+ const proofAndVk = await this.api.acirProveAztecClient(this.acirMsgpack, witnessMsgpack);
388
+ const [proof, vk] = proofAndVk;
389
+ if (!await this.verify(proof, vk)) {
390
+ throw new AztecClientBackendError("Failed to verify the private (ClientIVC) transaction proof!");
391
+ }
392
+ return proofAndVk;
380
393
  }
381
394
 
382
395
  async verify(proof: Uint8Array, vk: Uint8Array): Promise<boolean> {
@@ -389,6 +402,12 @@ export class AztecClientBackend {
389
402
  return this.api.acirProveAndVerifyAztecClient(this.acirMsgpack, witnessMsgpack);
390
403
  }
391
404
 
405
+ async gates(): Promise<number[]> {
406
+ // call function on API
407
+ await this.instantiate();
408
+ return this.api.acirGatesAztecClient(this.acirMsgpack);
409
+ }
410
+
392
411
  async destroy(): Promise<void> {
393
412
  if (!this.api) {
394
413
  return;
@@ -11,8 +11,6 @@ import { RawBuffer } from '../types/raw_buffer.js';
11
11
  export { BarretenbergVerifier } from './verifier.js';
12
12
  export { UltraPlonkBackend, UltraHonkBackend, AztecClientBackend } from './backend.js';
13
13
 
14
- const debug = createDebug('bb.js:wasm');
15
-
16
14
  export type BackendOptions = {
17
15
  /** @description Number of threads to run the backend worker on */
18
16
  threads?: number;
@@ -25,6 +23,9 @@ export type BackendOptions = {
25
23
 
26
24
  /** @description Path to download WASM files */
27
25
  wasmPath?: string;
26
+
27
+ /** @description Logging function */
28
+ logger?: (msg: string) => void;
28
29
  };
29
30
 
30
31
  export type CircuitOptions = {
@@ -53,8 +54,14 @@ export class Barretenberg extends BarretenbergApi {
53
54
  static async new(options: BackendOptions = {}) {
54
55
  const worker = createMainWorker();
55
56
  const wasm = getRemoteBarretenbergWasm<BarretenbergWasmMainWorker>(worker);
56
- const { module, threads } = await fetchModuleAndThreads(options.threads, options.wasmPath);
57
- await wasm.init(module, threads, proxy(debug), options.memory?.initial, options.memory?.maximum);
57
+ const { module, threads } = await fetchModuleAndThreads(options.threads, options.wasmPath, options.logger);
58
+ await wasm.init(
59
+ module,
60
+ threads,
61
+ proxy(options.logger ?? createDebug('bb.js:bb_wasm_async')),
62
+ options.memory?.initial,
63
+ options.memory?.maximum,
64
+ );
58
65
  return new Barretenberg(worker, wasm, options);
59
66
  }
60
67
 
@@ -63,7 +70,7 @@ export class Barretenberg extends BarretenbergApi {
63
70
  }
64
71
 
65
72
  async initSRSForCircuitSize(circuitSize: number): Promise<void> {
66
- const crs = await Crs.new(circuitSize + 1, this.options.crsPath);
73
+ const crs = await Crs.new(circuitSize + 1, this.options.crsPath, this.options.logger);
67
74
  // TODO(https://github.com/AztecProtocol/barretenberg/issues/1129): Do slab allocator initialization?
68
75
  // await this.commonInitSlabAllocator(circuitSize);
69
76
  await this.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
@@ -71,8 +78,8 @@ export class Barretenberg extends BarretenbergApi {
71
78
 
72
79
  async initSRSClientIVC(): Promise<void> {
73
80
  // crsPath can be undefined
74
- const crs = await Crs.new(2 ** 20 + 1, this.options.crsPath);
75
- const grumpkinCrs = await GrumpkinCrs.new(2 ** 16 + 1, this.options.crsPath);
81
+ const crs = await Crs.new(2 ** 20 + 1, this.options.crsPath, this.options.logger);
82
+ const grumpkinCrs = await GrumpkinCrs.new(2 ** 16 + 1, this.options.crsPath, this.options.logger);
76
83
 
77
84
  // Load CRS into wasm global CRS state.
78
85
  // TODO: Make RawBuffer be default behavior, and have a specific Vector type for when wanting length prefixed.
@@ -100,16 +107,16 @@ export class BarretenbergSync extends BarretenbergApiSync {
100
107
  super(wasm);
101
108
  }
102
109
 
103
- private static async new(wasmPath?: string) {
110
+ private static async new(wasmPath?: string, logger: (msg: string) => void = createDebug('bb.js:bb_wasm_sync')) {
104
111
  const wasm = new BarretenbergWasmMain();
105
- const { module, threads } = await fetchModuleAndThreads(1, wasmPath);
106
- await wasm.init(module, threads);
112
+ const { module, threads } = await fetchModuleAndThreads(1, wasmPath, logger);
113
+ await wasm.init(module, threads, logger);
107
114
  return new BarretenbergSync(wasm);
108
115
  }
109
116
 
110
- static async initSingleton(wasmPath?: string) {
117
+ static async initSingleton(wasmPath?: string, logger: (msg: string) => void = createDebug('bb.js:bb_wasm_sync')) {
111
118
  if (!barrentenbergSyncSingletonPromise) {
112
- barrentenbergSyncSingletonPromise = BarretenbergSync.new(wasmPath);
119
+ barrentenbergSyncSingletonPromise = BarretenbergSync.new(wasmPath, logger);
113
120
  }
114
121
 
115
122
  barretenbergSyncSingleton = await barrentenbergSyncSingletonPromise;
@@ -12,6 +12,26 @@ import {
12
12
  OutputType,
13
13
  } from '../serialize/index.js';
14
14
  import { Fr, Fq, Point, Buffer32, Buffer128, Ptr } from '../types/index.js';
15
+ function parseBigEndianU32Array(buffer: Uint8Array, hasSizePrefix = false): number[] {
16
+ const dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
17
+
18
+ let offset = 0;
19
+ let count = buffer.byteLength >>> 2; // default is entire buffer length / 4
20
+
21
+ if (hasSizePrefix) {
22
+ // Read the first 4 bytes as the size (big-endian).
23
+ count = dv.getUint32(0, /* littleEndian= */ false);
24
+ offset = 4;
25
+ }
26
+
27
+ const out: number[] = new Array(count);
28
+ for (let i = 0; i < count; i++) {
29
+ out[i] = dv.getUint32(offset, false);
30
+ offset += 4;
31
+ }
32
+
33
+ return out;
34
+ }
15
35
 
16
36
  export class BarretenbergApi {
17
37
  constructor(protected wasm: BarretenbergWasmWorker | BarretenbergWasmMain) {}
@@ -357,6 +377,21 @@ export class BarretenbergApi {
357
377
  return out as [number, number];
358
378
  }
359
379
 
380
+ async acirGatesAztecClient(
381
+ // cf acirProveAztecClient
382
+ acirVec: Uint8Array[],
383
+ ): Promise<number[]> {
384
+ const inArgs = [acirVec].map(serializeBufferable);
385
+ const outTypes: OutputType[] = [BufferDeserializer()];
386
+ const resultBuffer = await this.wasm.callWasmExport(
387
+ 'acir_gates_aztec_client',
388
+ inArgs,
389
+ outTypes.map(t => t.SIZE_IN_BYTES),
390
+ );
391
+
392
+ return parseBigEndianU32Array(resultBuffer[0], /*hasSizePrefix=*/ true);
393
+ }
394
+
360
395
  async acirNewAcirComposer(sizeHint: number): Promise<Ptr> {
361
396
  const inArgs = [sizeHint].map(serializeBufferable);
362
397
  const outTypes: OutputType[] = [Ptr];
@@ -1,8 +1,6 @@
1
1
  import createDebug from 'debug';
2
2
  import { randomBytes } from '../../random/index.js';
3
3
 
4
- const debug = createDebug('bb.js:wasm');
5
-
6
4
  /**
7
5
  * Base implementation of BarretenbergWasm.
8
6
  * Contains code that is common to the "main thread" implementation and the "child thread" implementation.
@@ -11,7 +9,7 @@ export class BarretenbergWasmBase {
11
9
  protected memStore: { [key: string]: Uint8Array } = {};
12
10
  protected memory!: WebAssembly.Memory;
13
11
  protected instance!: WebAssembly.Instance;
14
- protected logger: (msg: string) => void = debug;
12
+ protected logger: (msg: string) => void = createDebug('bb.js:bb_wasm_base');
15
13
 
16
14
  protected getImportObj(memory: WebAssembly.Memory) {
17
15
  /* eslint-disable camelcase */
@@ -51,9 +49,9 @@ export class BarretenbergWasmBase {
51
49
  const m = this.getMemory();
52
50
  const str2 = `${str} (mem: ${(m.length / (1024 * 1024)).toFixed(2)}MiB)`;
53
51
  this.logger(str2);
54
- if (str2.startsWith('WARNING:')) {
55
- this.logger(new Error().stack!);
56
- }
52
+ // if (str2.startsWith('WARNING:')) {
53
+ // this.logger(new Error().stack!);
54
+ // }
57
55
  },
58
56
 
59
57
  get_data: (keyAddr: number, outBufAddr: number) => {
@@ -7,8 +7,6 @@ import { type BarretenbergWasmThreadWorker } from '../barretenberg_wasm_thread/i
7
7
  import { BarretenbergWasmBase } from '../barretenberg_wasm_base/index.js';
8
8
  import { HeapAllocator } from './heap_allocator.js';
9
9
 
10
- const debug = createDebug('bb.js:wasm');
11
-
12
10
  /**
13
11
  * This is the "main thread" implementation of BarretenbergWasm.
14
12
  * It spawns a bunch of "child thread" implementations.
@@ -31,7 +29,7 @@ export class BarretenbergWasmMain extends BarretenbergWasmBase {
31
29
  public async init(
32
30
  module: WebAssembly.Module,
33
31
  threads = Math.min(getNumCpu(), BarretenbergWasmMain.MAX_THREADS),
34
- logger: (msg: string) => void = debug,
32
+ logger: (msg: string) => void = createDebug('bb.js:bb_wasm'),
35
33
  initial = 32,
36
34
  maximum = 2 ** 16,
37
35
  ) {
@@ -42,9 +40,9 @@ export class BarretenbergWasmMain extends BarretenbergWasmBase {
42
40
  const shared = getSharedMemoryAvailable();
43
41
 
44
42
  this.logger(
45
- `initial mem: ${initial} pages, ${initialMb}MiB. ` +
46
- `max mem: ${maximum} pages, ${maxMb}MiB. ` +
47
- `threads: ${threads}, shared: ${shared}`,
43
+ `Initializing bb wasm: initial memory ${initial} pages ${initialMb}MiB; ` +
44
+ `max memory: ${maximum} pages, ${maxMb}MiB; ` +
45
+ `threads: ${threads}; shared memory: ${shared}`,
48
46
  );
49
47
 
50
48
  this.memory = new WebAssembly.Memory({ initial, maximum, shared });
@@ -58,7 +56,7 @@ export class BarretenbergWasmMain extends BarretenbergWasmBase {
58
56
 
59
57
  // Create worker threads. Create 1 less than requested, as main thread counts as a thread.
60
58
  if (threads > 1) {
61
- this.logger(`creating ${threads} worker threads...`);
59
+ this.logger(`Creating ${threads} worker threads`);
62
60
  this.workers = await Promise.all(Array.from({ length: threads - 1 }).map(createThreadWorker));
63
61
  this.remoteWasms = await Promise.all(this.workers.map(getRemoteBarretenbergWasm<BarretenbergWasmThreadWorker>));
64
62
  await Promise.all(this.remoteWasms.map(w => w.initThread(module, this.memory)));
@@ -6,7 +6,10 @@ export async function fetchCode(multithreaded: boolean, wasmPath?: string) {
6
6
  let url: string;
7
7
  if (wasmPath) {
8
8
  const suffix = multithreaded ? '-threads' : '';
9
- url = `${wasmPath}/barretenberg${suffix}.wasm.gz`;
9
+ const filePath = wasmPath.split('/').slice(0, -1).join('/');
10
+ const fileNameWithExtensions = wasmPath.split('/').pop();
11
+ const [fileName, ...extensions] = fileNameWithExtensions!.split('.');
12
+ url = `${filePath}/${fileName}${suffix}.${extensions.join('.')}`;
10
13
  } else {
11
14
  url = multithreaded
12
15
  ? (await import(/* webpackIgnore: true */ './barretenberg-threads.js')).default
@@ -15,7 +15,7 @@ function getCurrentDir() {
15
15
 
16
16
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
17
  export async function fetchCode(multithreaded: boolean, wasmPath?: string) {
18
- const path = getCurrentDir() + '/../../barretenberg-threads.wasm.gz';
18
+ const path = wasmPath ?? getCurrentDir() + '/../../barretenberg-threads.wasm.gz';
19
19
  const compressedData = await readFile(path);
20
20
  const decompressedData = pako.ungzip(new Uint8Array(compressedData));
21
21
  return decompressedData.buffer;
@@ -18,7 +18,7 @@ describe('barretenberg wasm', () => {
18
18
  const length = 1024;
19
19
  const ptr = await wasm.call('bbmalloc', length);
20
20
  const buf = Buffer.alloc(length, 128);
21
- await wasm.writeMemory(ptr, buf);
21
+ await wasm.writeMemory(ptr, Uint8Array.from(buf));
22
22
  const result = Buffer.from(await wasm.getMemorySlice(ptr, ptr + length));
23
23
  await wasm.call('bbfree', ptr);
24
24
  expect(result).toStrictEqual(buf);
@@ -37,7 +37,7 @@ describe('barretenberg wasm', () => {
37
37
  const length = 1024;
38
38
  const ptr = await wasm.call('bbmalloc', length);
39
39
  const buf = Buffer.alloc(length, 128);
40
- await wasm.writeMemory(ptr, buf);
40
+ await wasm.writeMemory(ptr, Uint8Array.from(buf));
41
41
  const result = Buffer.from(await wasm.getMemorySlice(ptr, ptr + length));
42
42
  await wasm.call('bbfree', ptr);
43
43
  expect(result).toStrictEqual(buf);
@@ -5,29 +5,36 @@ import { getRemoteBarretenbergWasm, getSharedMemoryAvailable } from './helpers/n
5
5
  import { BarretenbergWasmMain, BarretenbergWasmMainWorker } from './barretenberg_wasm_main/index.js';
6
6
  import { fetchCode } from './fetch_code/index.js';
7
7
 
8
- const debug = createDebug('bb.js:wasm');
9
-
10
- export async function fetchModuleAndThreads(desiredThreads = 32, wasmPath?: string) {
8
+ export async function fetchModuleAndThreads(
9
+ desiredThreads = 32,
10
+ wasmPath?: string,
11
+ logger: (msg: string) => void = createDebug('bb.js:fetch_mat'),
12
+ ) {
11
13
  const shared = getSharedMemoryAvailable();
12
14
 
13
- const availableThreads = shared ? await getAvailableThreads() : 1;
15
+ const availableThreads = shared ? await getAvailableThreads(logger) : 1;
14
16
  // We limit the number of threads to 32 as we do not benefit from greater numbers.
15
17
  const limitedThreads = Math.min(desiredThreads, availableThreads, 32);
16
18
 
19
+ logger(`Fetching bb wasm from ${wasmPath ?? 'default location'}`);
17
20
  const code = await fetchCode(shared, wasmPath);
21
+ logger(`Compiling bb wasm of ${code.byteLength} bytes`);
18
22
  const module = await WebAssembly.compile(code);
23
+ logger('Compilation of bb wasm complete');
19
24
  return { module, threads: limitedThreads };
20
25
  }
21
26
 
22
- async function getAvailableThreads(): Promise<number> {
27
+ async function getAvailableThreads(logger: (msg: string) => void): Promise<number> {
23
28
  if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {
24
29
  return navigator.hardwareConcurrency;
25
30
  } else {
26
31
  try {
27
32
  const os = await import('os');
28
33
  return os.cpus().length;
29
- } catch (e) {
30
- debug(`Could not detect environment. Falling back to one thread.: {e}`);
34
+ } catch (e: any) {
35
+ logger(
36
+ `Could not detect environment to query number of threads. Falling back to one thread. Error: ${e.message ?? e}`,
37
+ );
31
38
  return 1;
32
39
  }
33
40
  }
@@ -38,11 +45,15 @@ export class BarretenbergWasm extends BarretenbergWasmMain {
38
45
  * Construct and initialize BarretenbergWasm within a Worker. Return both the worker and the wasm proxy.
39
46
  * Used when running in the browser, because we can't block the main thread.
40
47
  */
41
- public static async new(desiredThreads?: number, wasmPath?: string) {
48
+ public static async new(
49
+ desiredThreads?: number,
50
+ wasmPath?: string,
51
+ logger: (msg: string) => void = createDebug('bb.js:bb_wasm_main'),
52
+ ) {
42
53
  const worker = createMainWorker();
43
54
  const wasm = getRemoteBarretenbergWasm<BarretenbergWasmMainWorker>(worker);
44
- const { module, threads } = await fetchModuleAndThreads(desiredThreads, wasmPath);
45
- await wasm.init(module, threads, proxy(debug));
55
+ const { module, threads } = await fetchModuleAndThreads(desiredThreads, wasmPath, logger);
56
+ await wasm.init(module, threads, proxy(logger));
46
57
  return { worker, wasm };
47
58
  }
48
59
  }
@@ -1,3 +1,4 @@
1
+ import { retry, makeBackoff } from '../retry/index.js';
1
2
  /**
2
3
  * Downloader for CRS from the web or local.
3
4
  */
@@ -28,12 +29,16 @@ export class NetCrs {
28
29
 
29
30
  const g1End = this.numPoints * 64 - 1;
30
31
 
31
- const response = await fetch('https://aztec-ignition.s3.amazonaws.com/MAIN%20IGNITION/flat/g1.dat', {
32
- headers: {
33
- Range: `bytes=0-${g1End}`,
34
- },
35
- cache: 'force-cache',
36
- });
32
+ const response = await retry(
33
+ () =>
34
+ fetch('https://aztec-ignition.s3.amazonaws.com/MAIN%20IGNITION/flat/g1.dat', {
35
+ headers: {
36
+ Range: `bytes=0-${g1End}`,
37
+ },
38
+ cache: 'force-cache',
39
+ }),
40
+ makeBackoff([5, 5, 5]),
41
+ );
37
42
 
38
43
  return (this.data = new Uint8Array(await response.arrayBuffer()));
39
44
  }
@@ -42,9 +47,13 @@ export class NetCrs {
42
47
  * Download the G2 points data.
43
48
  */
44
49
  async downloadG2Data() {
45
- const response2 = await fetch('https://aztec-ignition.s3.amazonaws.com/MAIN%20IGNITION/flat/g2.dat', {
46
- cache: 'force-cache',
47
- });
50
+ const response2 = await retry(
51
+ () =>
52
+ fetch('https://aztec-ignition.s3.amazonaws.com/MAIN%20IGNITION/flat/g2.dat', {
53
+ cache: 'force-cache',
54
+ }),
55
+ makeBackoff([5, 5, 5]),
56
+ );
48
57
 
49
58
  return (this.g2Data = new Uint8Array(await response2.arrayBuffer()));
50
59
  }
@@ -4,16 +4,22 @@ import { stat } from 'fs/promises';
4
4
  import createDebug from 'debug';
5
5
  import { homedir } from 'os';
6
6
 
7
- const debug = createDebug('bb.js:crs');
8
-
9
7
  /**
10
8
  * Generic CRS finder utility class.
11
9
  */
12
10
  export class Crs {
13
- constructor(public readonly numPoints: number, public readonly path: string) {}
14
-
15
- static async new(numPoints: number, crsPath = homedir() + '/.bb-crs') {
16
- const crs = new Crs(numPoints, crsPath);
11
+ constructor(
12
+ public readonly numPoints: number,
13
+ public readonly path: string,
14
+ private readonly logger: (msg: string) => void = createDebug('bb.js:crs'),
15
+ ) {}
16
+
17
+ static async new(
18
+ numPoints: number,
19
+ crsPath = homedir() + '/.bb-crs',
20
+ logger: (msg: string) => void = createDebug('bb.js:crs'),
21
+ ) {
22
+ const crs = new Crs(numPoints, crsPath, logger);
17
23
  await crs.init();
18
24
  return crs;
19
25
  }
@@ -29,11 +35,11 @@ export class Crs {
29
35
  .catch(() => 0);
30
36
 
31
37
  if (g1FileSize >= this.numPoints * 64 && g1FileSize % 64 == 0 && g2FileSize == 128) {
32
- debug(`using cached crs of size: ${g1FileSize / 64}`);
38
+ this.logger(`Using cached CRS of size ${g1FileSize / 64}`);
33
39
  return;
34
40
  }
35
41
 
36
- debug(`downloading crs of size: ${this.numPoints}`);
42
+ this.logger(`Downloading CRS of size ${this.numPoints} into ${this.path}`);
37
43
  const crs = new NetCrs(this.numPoints);
38
44
  await crs.init();
39
45
  writeFileSync(this.path + '/bn254_g1.dat', crs.getG1Data());
@@ -45,7 +51,9 @@ export class Crs {
45
51
  * @returns The points data.
46
52
  */
47
53
  getG1Data(): Uint8Array {
48
- const length = this.numPoints * 64;
54
+ // Ensure length > 0, otherwise we might read a huge file.
55
+ // This is a backup.
56
+ const length = Math.max(this.numPoints, 1) * 64;
49
57
  const fd = openSync(this.path + '/bn254_g1.dat', 'r');
50
58
  const buffer = new Uint8Array(length);
51
59
  readSync(fd, buffer, 0, length, 0);
@@ -66,10 +74,18 @@ export class Crs {
66
74
  * Generic Grumpkin CRS finder utility class.
67
75
  */
68
76
  export class GrumpkinCrs {
69
- constructor(public readonly numPoints: number, public readonly path: string) {}
70
-
71
- static async new(numPoints: number, crsPath = homedir() + '/.bb-crs') {
72
- const crs = new GrumpkinCrs(numPoints, crsPath);
77
+ constructor(
78
+ public readonly numPoints: number,
79
+ public readonly path: string,
80
+ private readonly logger: (msg: string) => void = createDebug('bb.js:crs'),
81
+ ) {}
82
+
83
+ static async new(
84
+ numPoints: number,
85
+ crsPath = homedir() + '/.bb-crs',
86
+ logger: (msg: string) => void = createDebug('bb.js:crs'),
87
+ ) {
88
+ const crs = new GrumpkinCrs(numPoints, crsPath, logger);
73
89
  await crs.init();
74
90
  return crs;
75
91
  }
@@ -82,11 +98,11 @@ export class GrumpkinCrs {
82
98
  .catch(() => 0);
83
99
 
84
100
  if (g1FileSize >= this.numPoints * 64 && g1FileSize % 64 == 0) {
85
- debug(`using cached crs of size: ${g1FileSize / 64}`);
101
+ this.logger(`Using cached Grumpkin CRS of size ${g1FileSize / 64}`);
86
102
  return;
87
103
  }
88
104
 
89
- debug(`downloading crs of size: ${this.numPoints}`);
105
+ this.logger(`Downloading Grumpkin CRS of size ${this.numPoints} into ${this.path}`);
90
106
  const crs = new NetGrumpkinCrs(this.numPoints);
91
107
  await crs.init();
92
108
  writeFileSync(this.path + '/grumpkin_g1.dat', crs.getG1Data());
@@ -19,7 +19,7 @@ describe('simple', () => {
19
19
 
20
20
  afterAll(async () => {
21
21
  await api.destroy();
22
- });
22
+ }, 10000);
23
23
 
24
24
  it('should construct 512k gate proof', async () => {
25
25
  const valid = await api.examplesSimpleCreateAndVerifyProof();