@aztec/bb.js 0.72.0 → 0.73.0-commit.117882ca3ed35a6df177e74f0b3d2f3e7c512184

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 (102) hide show
  1. package/README.md +10 -0
  2. package/dest/browser/barretenberg/index.d.ts +4 -9
  3. package/dest/browser/barretenberg/index.d.ts.map +1 -1
  4. package/dest/browser/barretenberg-threads.wasm.gz +0 -0
  5. package/dest/browser/barretenberg.wasm.gz +0 -0
  6. package/dest/browser/barretenberg_api/index.d.ts +1 -0
  7. package/dest/browser/barretenberg_api/index.d.ts.map +1 -1
  8. package/dest/browser/barretenberg_wasm/fetch_code/browser/index.d.ts +1 -1
  9. package/dest/browser/barretenberg_wasm/fetch_code/browser/index.d.ts.map +1 -1
  10. package/dest/browser/barretenberg_wasm/fetch_code/node/index.d.ts +1 -1
  11. package/dest/browser/barretenberg_wasm/fetch_code/node/index.d.ts.map +1 -1
  12. package/dest/browser/barretenberg_wasm/index.d.ts +2 -2
  13. package/dest/browser/barretenberg_wasm/index.d.ts.map +1 -1
  14. package/dest/browser/crs/net_crs.d.ts.map +1 -1
  15. package/dest/browser/index.d.ts +1 -1
  16. package/dest/browser/index.d.ts.map +1 -1
  17. package/dest/browser/index.js +12857 -13152
  18. package/dest/browser/retry/index.d.ts +26 -0
  19. package/dest/browser/retry/index.d.ts.map +1 -0
  20. package/dest/node/barretenberg/__snapshots__/pedersen.test.js.snap +156 -0
  21. package/dest/node/barretenberg/__snapshots__/poseidon.test.js.snap +40 -0
  22. package/dest/node/barretenberg/blake2s.test.js +2 -2
  23. package/dest/node/barretenberg/index.d.ts +4 -9
  24. package/dest/node/barretenberg/index.d.ts.map +1 -1
  25. package/dest/node/barretenberg/index.js +12 -38
  26. package/dest/node/barretenberg/pedersen.test.js +2 -2
  27. package/dest/node/barretenberg/poseidon.test.js +2 -2
  28. package/dest/node/barretenberg_api/index.d.ts +1 -0
  29. package/dest/node/barretenberg_api/index.d.ts.map +1 -1
  30. package/dest/node/barretenberg_api/index.js +8 -1
  31. package/dest/node/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  32. package/dest/node/barretenberg_wasm/barretenberg_wasm_base/index.js +5 -5
  33. package/dest/node/barretenberg_wasm/barretenberg_wasm_main/index.js +2 -2
  34. package/dest/node/barretenberg_wasm/fetch_code/browser/index.d.ts +1 -1
  35. package/dest/node/barretenberg_wasm/fetch_code/browser/index.d.ts.map +1 -1
  36. package/dest/node/barretenberg_wasm/fetch_code/browser/index.js +20 -6
  37. package/dest/node/barretenberg_wasm/fetch_code/node/index.d.ts +1 -1
  38. package/dest/node/barretenberg_wasm/fetch_code/node/index.d.ts.map +1 -1
  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 -8
  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/index.d.ts +1 -1
  47. package/dest/node/index.d.ts.map +1 -1
  48. package/dest/node/index.js +2 -2
  49. package/dest/node/main.d.ts.map +1 -1
  50. package/dest/node/main.js +9 -9
  51. package/dest/node/retry/index.d.ts +26 -0
  52. package/dest/node/retry/index.d.ts.map +1 -0
  53. package/dest/node/retry/index.js +50 -0
  54. package/dest/node-cjs/barretenberg/blake2s.test.js +2 -2
  55. package/dest/node-cjs/barretenberg/index.d.ts +4 -9
  56. package/dest/node-cjs/barretenberg/index.d.ts.map +1 -1
  57. package/dest/node-cjs/barretenberg/index.js +13 -39
  58. package/dest/node-cjs/barretenberg/pedersen.test.js +2 -2
  59. package/dest/node-cjs/barretenberg/poseidon.test.js +2 -2
  60. package/dest/node-cjs/barretenberg_api/index.d.ts +1 -0
  61. package/dest/node-cjs/barretenberg_api/index.d.ts.map +1 -1
  62. package/dest/node-cjs/barretenberg_api/index.js +8 -1
  63. package/dest/node-cjs/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  64. package/dest/node-cjs/barretenberg_wasm/barretenberg_wasm_base/index.js +5 -5
  65. package/dest/node-cjs/barretenberg_wasm/barretenberg_wasm_main/index.js +2 -2
  66. package/dest/node-cjs/barretenberg_wasm/fetch_code/browser/index.d.ts +1 -1
  67. package/dest/node-cjs/barretenberg_wasm/fetch_code/browser/index.d.ts.map +1 -1
  68. package/dest/node-cjs/barretenberg_wasm/fetch_code/browser/index.js +20 -6
  69. package/dest/node-cjs/barretenberg_wasm/fetch_code/node/index.d.ts +1 -1
  70. package/dest/node-cjs/barretenberg_wasm/fetch_code/node/index.d.ts.map +1 -1
  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 -8
  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/index.d.ts +1 -1
  79. package/dest/node-cjs/index.d.ts.map +1 -1
  80. package/dest/node-cjs/index.js +2 -3
  81. package/dest/node-cjs/main.d.ts.map +1 -1
  82. package/dest/node-cjs/main.js +9 -9
  83. package/dest/node-cjs/retry/index.d.ts +26 -0
  84. package/dest/node-cjs/retry/index.d.ts.map +1 -0
  85. package/dest/node-cjs/retry/index.js +56 -0
  86. package/package.json +5 -3
  87. package/src/barretenberg/blake2s.test.ts +1 -1
  88. package/src/barretenberg/index.ts +21 -44
  89. package/src/barretenberg/pedersen.test.ts +1 -1
  90. package/src/barretenberg/poseidon.test.ts +1 -1
  91. package/src/barretenberg_api/index.ts +12 -0
  92. package/src/barretenberg_wasm/barretenberg_wasm_base/index.ts +4 -4
  93. package/src/barretenberg_wasm/barretenberg_wasm_main/index.ts +1 -1
  94. package/src/barretenberg_wasm/fetch_code/browser/index.ts +18 -5
  95. package/src/barretenberg_wasm/fetch_code/node/index.ts +1 -1
  96. package/src/barretenberg_wasm/index.test.ts +2 -2
  97. package/src/barretenberg_wasm/index.ts +10 -7
  98. package/src/crs/net_crs.ts +18 -9
  99. package/src/crs/node/index.ts +3 -1
  100. package/src/index.ts +1 -1
  101. package/src/main.ts +13 -10
  102. package/src/retry/index.ts +50 -0
@@ -0,0 +1,26 @@
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 declare function backoffGenerator(): Generator<number, void, unknown>;
10
+ /**
11
+ * Generates a backoff sequence based on the array of retry intervals to use with the `retry` function.
12
+ * @param retries - Intervals to retry (in seconds).
13
+ * @returns A generator sequence.
14
+ */
15
+ export declare function makeBackoff(retries: number[]): Generator<number, void, unknown>;
16
+ /**
17
+ * Retry a given asynchronous function with a specific backoff strategy, until it succeeds or backoff generator ends.
18
+ * It logs the error and retry interval in case an error is caught. The function can be named for better log output.
19
+ *
20
+ * @param fn - The asynchronous function to be retried.
21
+ * @param backoff - The optional backoff generator providing the intervals in seconds between retries. Defaults to a predefined series.
22
+ * @returns A Promise that resolves with the successful result of the provided function, or rejects if backoff generator ends.
23
+ * @throws If `NoRetryError` is thrown by the `fn`, it is rethrown.
24
+ */
25
+ export declare function retry<Result>(fn: () => Promise<Result>, backoff?: Generator<number, void, unknown>): Promise<Result>;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/retry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAiB,gBAAgB,qCAMhC;AAED;;;;GAIG;AACH,wBAAiB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,oCAI7C;AAED;;;;;;;;GAQG;AACH,wBAAsB,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,mCAAqB,mBAa1F"}
@@ -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.72.0",
4
+ "version": "0.73.0-commit.117882ca3ed35a6df177e74f0b3d2f3e7c512184",
5
5
  "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts",
6
6
  "license": "MIT",
7
7
  "type": "module",
@@ -13,7 +13,9 @@
13
13
  "default": "./dest/node/index.js"
14
14
  }
15
15
  },
16
- "bin": "./dest/node/main.js",
16
+ "bin": {
17
+ "bb.js": "dest/node/main.js"
18
+ },
17
19
  "files": [
18
20
  "src/",
19
21
  "dest/",
@@ -96,7 +98,7 @@
96
98
  "ts-jest": "^29.1.0",
97
99
  "ts-loader": "^9.4.2",
98
100
  "ts-node": "^10.9.1",
99
- "typescript": "^5.0.4",
101
+ "typescript": "5.4.5",
100
102
  "webpack": "^5.82.1",
101
103
  "webpack-cli": "^5.1.1",
102
104
  "webpack-dev-server": "^4.15.0",
@@ -41,7 +41,7 @@ describe('blake2s sync', () => {
41
41
  let api: BarretenbergSync;
42
42
 
43
43
  beforeAll(async () => {
44
- api = await BarretenbergSync.new();
44
+ api = await BarretenbergSync.initSingleton();
45
45
  });
46
46
 
47
47
  it('blake2s', () => {
@@ -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;
@@ -22,6 +20,9 @@ export type BackendOptions = {
22
20
 
23
21
  /** @description Path to download CRS files */
24
22
  crsPath?: string;
23
+
24
+ /** @description Path to download WASM files */
25
+ wasmPath?: string;
25
26
  };
26
27
 
27
28
  export type CircuitOptions = {
@@ -50,8 +51,14 @@ export class Barretenberg extends BarretenbergApi {
50
51
  static async new(options: BackendOptions = {}) {
51
52
  const worker = createMainWorker();
52
53
  const wasm = getRemoteBarretenbergWasm<BarretenbergWasmMainWorker>(worker);
53
- const { module, threads } = await fetchModuleAndThreads(options.threads);
54
- await wasm.init(module, threads, proxy(debug), options.memory?.initial, options.memory?.maximum);
54
+ const { module, threads } = await fetchModuleAndThreads(options.threads, options.wasmPath);
55
+ await wasm.init(
56
+ module,
57
+ threads,
58
+ proxy(createDebug('bb.js:bb_wasm_async')),
59
+ options.memory?.initial,
60
+ options.memory?.maximum,
61
+ );
55
62
  return new Barretenberg(worker, wasm, options);
56
63
  }
57
64
 
@@ -89,26 +96,28 @@ export class Barretenberg extends BarretenbergApi {
89
96
  }
90
97
  }
91
98
 
99
+ let barrentenbergSyncSingletonPromise: Promise<BarretenbergSync>;
92
100
  let barretenbergSyncSingleton: BarretenbergSync;
93
- let barretenbergSyncSingletonPromise: Promise<BarretenbergSync>;
94
101
 
95
102
  export class BarretenbergSync extends BarretenbergApiSync {
96
103
  private constructor(wasm: BarretenbergWasmMain) {
97
104
  super(wasm);
98
105
  }
99
106
 
100
- static async new() {
107
+ private static async new(wasmPath?: string) {
101
108
  const wasm = new BarretenbergWasmMain();
102
- const { module, threads } = await fetchModuleAndThreads(1);
103
- await wasm.init(module, threads);
109
+ const { module, threads } = await fetchModuleAndThreads(1, wasmPath);
110
+ await wasm.init(module, threads, createDebug('bb.js:bb_wasm_sync'));
104
111
  return new BarretenbergSync(wasm);
105
112
  }
106
113
 
107
- static initSingleton() {
108
- if (!barretenbergSyncSingletonPromise) {
109
- barretenbergSyncSingletonPromise = BarretenbergSync.new().then(s => (barretenbergSyncSingleton = s));
114
+ static async initSingleton(wasmPath?: string) {
115
+ if (!barrentenbergSyncSingletonPromise) {
116
+ barrentenbergSyncSingletonPromise = BarretenbergSync.new(wasmPath);
110
117
  }
111
- return barretenbergSyncSingletonPromise;
118
+
119
+ barretenbergSyncSingleton = await barrentenbergSyncSingletonPromise;
120
+ return barretenbergSyncSingleton;
112
121
  }
113
122
 
114
123
  static getSingleton() {
@@ -122,35 +131,3 @@ export class BarretenbergSync extends BarretenbergApiSync {
122
131
  return this.wasm;
123
132
  }
124
133
  }
125
-
126
- let barrentenbergLazySingleton: BarretenbergLazy;
127
-
128
- export class BarretenbergLazy extends BarretenbergApi {
129
- private constructor(wasm: BarretenbergWasmMain) {
130
- super(wasm);
131
- }
132
-
133
- private static async new() {
134
- const wasm = new BarretenbergWasmMain();
135
- const { module, threads } = await fetchModuleAndThreads(1);
136
- await wasm.init(module, threads);
137
- return new BarretenbergLazy(wasm);
138
- }
139
-
140
- static async getSingleton() {
141
- if (!barrentenbergLazySingleton) {
142
- barrentenbergLazySingleton = await BarretenbergLazy.new();
143
- }
144
- return barrentenbergLazySingleton;
145
- }
146
-
147
- getWasm() {
148
- return this.wasm;
149
- }
150
- }
151
-
152
- // If we're in ESM environment, use top level await. CJS users need to call it manually.
153
- // Need to ignore for cjs build.
154
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
155
- // @ts-ignore
156
- await BarretenbergSync.initSingleton(); // POSTPROCESS ESM ONLY
@@ -6,7 +6,7 @@ describe('pedersen sync', () => {
6
6
  let api: BarretenbergSync;
7
7
 
8
8
  beforeAll(async () => {
9
- api = await BarretenbergSync.new();
9
+ api = await BarretenbergSync.initSingleton();
10
10
  });
11
11
 
12
12
  it('pedersenHash', () => {
@@ -6,7 +6,7 @@ describe('poseidon sync', () => {
6
6
  let api: BarretenbergSync;
7
7
 
8
8
  beforeAll(async () => {
9
- api = await BarretenbergSync.new();
9
+ api = await BarretenbergSync.initSingleton();
10
10
  });
11
11
 
12
12
  it('poseidonHash', () => {
@@ -76,6 +76,18 @@ export class BarretenbergApi {
76
76
  return out[0];
77
77
  }
78
78
 
79
+ async poseidon2HashAccumulate(inputsBuffer: Fr[]): Promise<Fr> {
80
+ const inArgs = [inputsBuffer].map(serializeBufferable);
81
+ const outTypes: OutputType[] = [Fr];
82
+ const result = await this.wasm.callWasmExport(
83
+ 'poseidon2_hash_accumulate',
84
+ inArgs,
85
+ outTypes.map(t => t.SIZE_IN_BYTES),
86
+ );
87
+ const out = result.map((r, i) => outTypes[i].fromBuffer(r));
88
+ return out[0];
89
+ }
90
+
79
91
  async poseidon2Hashes(inputsBuffer: Fr[]): Promise<Fr> {
80
92
  const inArgs = [inputsBuffer].map(serializeBufferable);
81
93
  const outTypes: OutputType[] = [Fr];
@@ -1,7 +1,7 @@
1
1
  import createDebug from 'debug';
2
2
  import { randomBytes } from '../../random/index.js';
3
3
 
4
- const debug = createDebug('bb.js:wasm');
4
+ const debug = createDebug('bb.js:bb_wasm_base');
5
5
 
6
6
  /**
7
7
  * Base implementation of BarretenbergWasm.
@@ -51,9 +51,9 @@ export class BarretenbergWasmBase {
51
51
  const m = this.getMemory();
52
52
  const str2 = `${str} (mem: ${(m.length / (1024 * 1024)).toFixed(2)}MiB)`;
53
53
  this.logger(str2);
54
- if (str2.startsWith('WARNING:')) {
55
- this.logger(new Error().stack!);
56
- }
54
+ // if (str2.startsWith('WARNING:')) {
55
+ // this.logger(new Error().stack!);
56
+ // }
57
57
  },
58
58
 
59
59
  get_data: (keyAddr: number, outBufAddr: number) => {
@@ -7,7 +7,7 @@ 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');
10
+ const debug = createDebug('bb.js:bb_wasm');
11
11
 
12
12
  /**
13
13
  * This is the "main thread" implementation of BarretenbergWasm.
@@ -4,9 +4,22 @@ import pako from 'pako';
4
4
 
5
5
  // Annoyingly the wasm declares if it's memory is shared or not. So now we need two wasms if we want to be
6
6
  // able to fallback on "non shared memory" situations.
7
- export async function fetchCode(multithreaded: boolean) {
8
- const res = await fetch(multithreaded ? barretenbergThreadsModule : barretenbergModule);
9
- const compressedData = await res.arrayBuffer();
10
- const decompressedData = pako.ungzip(new Uint8Array(compressedData));
11
- return decompressedData.buffer;
7
+ export async function fetchCode(multithreaded: boolean, wasmPath?: string) {
8
+ let url = multithreaded ? barretenbergThreadsModule : barretenbergModule;
9
+ url = wasmPath ? `${wasmPath}/${/[^/]+(?=\/$|$)/.exec(url)?.[0]}` : url;
10
+ const res = await fetch(url);
11
+ const maybeCompressedData = await res.arrayBuffer();
12
+ const buffer = new Uint8Array(maybeCompressedData);
13
+ const isGzip =
14
+ // Check magic number
15
+ buffer[0] === 0x1f &&
16
+ buffer[1] === 0x8b &&
17
+ // Check compression method:
18
+ buffer[2] === 0x08;
19
+ if (isGzip) {
20
+ const decompressedData = pako.ungzip(buffer);
21
+ return decompressedData.buffer;
22
+ } else {
23
+ return buffer;
24
+ }
12
25
  }
@@ -14,7 +14,7 @@ function getCurrentDir() {
14
14
  }
15
15
 
16
16
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
- export async function fetchCode(multithreaded: boolean) {
17
+ export async function fetchCode(multithreaded: boolean, wasmPath?: string) {
18
18
  const path = getCurrentDir() + '/../../barretenberg-threads.wasm.gz';
19
19
  const compressedData = await readFile(path);
20
20
  const decompressedData = pako.ungzip(new Uint8Array(compressedData));
@@ -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,17 +5,20 @@ 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');
8
+ const fetchDebug = createDebug('bb.js:fetch_mat');
9
9
 
10
- export async function fetchModuleAndThreads(desiredThreads = 32) {
10
+ export async function fetchModuleAndThreads(desiredThreads = 32, wasmPath?: string) {
11
11
  const shared = getSharedMemoryAvailable();
12
12
 
13
13
  const availableThreads = shared ? await getAvailableThreads() : 1;
14
14
  // We limit the number of threads to 32 as we do not benefit from greater numbers.
15
15
  const limitedThreads = Math.min(desiredThreads, availableThreads, 32);
16
16
 
17
- const code = await fetchCode(shared);
17
+ fetchDebug('Fetching wasm...');
18
+ const code = await fetchCode(shared, wasmPath);
19
+ fetchDebug(`Compiling wasm of ${code.byteLength} bytes...`);
18
20
  const module = await WebAssembly.compile(code);
21
+ fetchDebug('Done.');
19
22
  return { module, threads: limitedThreads };
20
23
  }
21
24
 
@@ -27,7 +30,7 @@ async function getAvailableThreads(): Promise<number> {
27
30
  const os = await import('os');
28
31
  return os.cpus().length;
29
32
  } catch (e) {
30
- debug(`Could not detect environment. Falling back to one thread.: {e}`);
33
+ fetchDebug(`Could not detect environment. Falling back to one thread.: {e}`);
31
34
  return 1;
32
35
  }
33
36
  }
@@ -38,11 +41,11 @@ export class BarretenbergWasm extends BarretenbergWasmMain {
38
41
  * Construct and initialize BarretenbergWasm within a Worker. Return both the worker and the wasm proxy.
39
42
  * Used when running in the browser, because we can't block the main thread.
40
43
  */
41
- public static async new(desiredThreads?: number) {
44
+ public static async new(desiredThreads?: number, wasmPath?: string) {
42
45
  const worker = createMainWorker();
43
46
  const wasm = getRemoteBarretenbergWasm<BarretenbergWasmMainWorker>(worker);
44
- const { module, threads } = await fetchModuleAndThreads(desiredThreads);
45
- await wasm.init(module, threads, proxy(debug));
47
+ const { module, threads } = await fetchModuleAndThreads(desiredThreads, wasmPath);
48
+ await wasm.init(module, threads, proxy(createDebug('bb.js:bb_wasm_main')));
46
49
  return { worker, wasm };
47
50
  }
48
51
  }
@@ -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
  }
@@ -45,7 +45,9 @@ export class Crs {
45
45
  * @returns The points data.
46
46
  */
47
47
  getG1Data(): Uint8Array {
48
- const length = this.numPoints * 64;
48
+ // Ensure length > 0, otherwise we might read a huge file.
49
+ // This is a backup.
50
+ const length = Math.max(this.numPoints, 1) * 64;
49
51
  const fd = openSync(this.path + '/bn254_g1.dat', 'r');
50
52
  const buffer = new Uint8Array(length);
51
53
  readSync(fd, buffer, 0, length, 0);
package/src/index.ts CHANGED
@@ -3,11 +3,11 @@ export {
3
3
  BackendOptions,
4
4
  Barretenberg,
5
5
  BarretenbergSync,
6
- BarretenbergLazy,
7
6
  BarretenbergVerifier,
8
7
  UltraPlonkBackend,
9
8
  UltraHonkBackend,
10
9
  AztecClientBackend,
11
10
  } from './barretenberg/index.js';
11
+
12
12
  export { RawBuffer, Fr } from './types/index.js';
13
13
  export { splitHonkProof, reconstructHonkProof, ProofData } from './proof/index.js';
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,10 +62,10 @@ 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) {
@@ -300,7 +300,7 @@ export async function gateCountUltra(bytecodePath: string, recursive: boolean, h
300
300
  const buffer = Buffer.alloc(8);
301
301
  buffer.writeBigInt64LE(BigInt(numberOfGates));
302
302
 
303
- process.stdout.write(buffer);
303
+ process.stdout.write(Uint8Array.from(buffer));
304
304
  } finally {
305
305
  await api.destroy();
306
306
  }
@@ -310,7 +310,7 @@ export async function verify(proofPath: string, vkPath: string, crsPath: string)
310
310
  const { api, acirComposer } = await initLite(crsPath);
311
311
  try {
312
312
  await api.acirLoadVerificationKey(acirComposer, new RawBuffer(readFileSync(vkPath)));
313
- const verified = await api.acirVerifyProof(acirComposer, readFileSync(proofPath));
313
+ const verified = await api.acirVerifyProof(acirComposer, Uint8Array.from(readFileSync(proofPath)));
314
314
  debug(`verified: ${verified}`);
315
315
  return verified;
316
316
  } finally {
@@ -406,7 +406,7 @@ export async function proofAsFields(proofPath: string, vkPath: string, outputPat
406
406
  const numPublicInputs = readFileSync(vkPath).readUint32BE(8);
407
407
  const proofAsFields = await api.acirSerializeProofIntoFields(
408
408
  acirComposer,
409
- readFileSync(proofPath),
409
+ Uint8Array.from(readFileSync(proofPath)),
410
410
  numPublicInputs,
411
411
  );
412
412
  const jsonProofAsFields = JSON.stringify(proofAsFields.map(f => f.toString()));
@@ -521,7 +521,10 @@ export async function verifyUltraHonk(
521
521
  const acirVerifyUltraHonk = options?.keccak
522
522
  ? api.acirVerifyUltraKeccakHonk.bind(api)
523
523
  : api.acirVerifyUltraHonk.bind(api);
524
- const verified = await acirVerifyUltraHonk(readFileSync(proofPath), new RawBuffer(readFileSync(vkPath)));
524
+ const verified = await acirVerifyUltraHonk(
525
+ Uint8Array.from(readFileSync(proofPath)),
526
+ new RawBuffer(readFileSync(vkPath)),
527
+ );
525
528
 
526
529
  debug(`verified: ${verified}`);
527
530
  return verified;
@@ -534,7 +537,7 @@ export async function proofAsFieldsUltraHonk(proofPath: string, outputPath: stri
534
537
  const { api } = await initLite(crsPath);
535
538
  try {
536
539
  debug('outputting proof as vector of fields');
537
- const proofAsFields = await api.acirProofAsFieldsUltraHonk(readFileSync(proofPath));
540
+ const proofAsFields = await api.acirProofAsFieldsUltraHonk(Uint8Array.from(readFileSync(proofPath)));
538
541
  const jsonProofAsFields = JSON.stringify(proofAsFields.map(f => f.toString()));
539
542
 
540
543
  if (outputPath === '-') {
@@ -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
+ }