@aztec/bb.js 3.0.0-nightly.20251114 → 3.0.0-nightly.20251118

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 (149) hide show
  1. package/build/amd64-linux/bb +0 -0
  2. package/build/amd64-linux/nodejs_module.node +0 -0
  3. package/build/amd64-macos/bb +0 -0
  4. package/build/amd64-macos/nodejs_module.node +0 -0
  5. package/build/arm64-linux/bb +0 -0
  6. package/build/arm64-linux/nodejs_module.node +0 -0
  7. package/build/arm64-macos/bb +0 -0
  8. package/build/arm64-macos/nodejs_module.node +0 -0
  9. package/dest/browser/barretenberg/backend.d.ts +9 -23
  10. package/dest/browser/barretenberg/backend.d.ts.map +1 -1
  11. package/dest/browser/barretenberg/backend.js +24 -84
  12. package/dest/browser/barretenberg/index.d.ts +1 -3
  13. package/dest/browser/barretenberg/index.d.ts.map +1 -1
  14. package/dest/browser/barretenberg/index.js +15 -24
  15. package/dest/browser/{bigint-array/index.d.ts → barretenberg/testing/bigint-buffer.d.ts} +1 -1
  16. package/dest/browser/barretenberg/testing/bigint-buffer.d.ts.map +1 -0
  17. package/dest/browser/barretenberg/testing/bigint-buffer.js +37 -0
  18. package/dest/browser/barretenberg/testing/fields.d.ts +16 -0
  19. package/dest/browser/barretenberg/testing/fields.d.ts.map +1 -0
  20. package/dest/browser/barretenberg/testing/fields.js +48 -0
  21. package/dest/browser/barretenberg_wasm/fetch_code/browser/barretenberg-threads.js +1 -1
  22. package/dest/browser/barretenberg_wasm/fetch_code/browser/barretenberg.js +1 -1
  23. package/dest/browser/bb_backends/index.d.ts +8 -5
  24. package/dest/browser/bb_backends/index.d.ts.map +1 -1
  25. package/dest/browser/bb_backends/index.js +5 -5
  26. package/dest/node/barretenberg/backend.d.ts +9 -23
  27. package/dest/node/barretenberg/backend.d.ts.map +1 -1
  28. package/dest/node/barretenberg/backend.js +24 -84
  29. package/dest/node/barretenberg/blake2s.test.js +2 -2
  30. package/dest/node/barretenberg/index.d.ts +1 -3
  31. package/dest/node/barretenberg/index.d.ts.map +1 -1
  32. package/dest/node/barretenberg/index.js +15 -24
  33. package/dest/node/barretenberg/pedersen.test.js +2 -2
  34. package/dest/node/barretenberg/poseidon.bench.test.js +27 -68
  35. package/dest/node/barretenberg/poseidon.test.js +2 -2
  36. package/dest/node/{bigint-array/index.d.ts → barretenberg/testing/bigint-buffer.d.ts} +1 -1
  37. package/dest/node/barretenberg/testing/bigint-buffer.d.ts.map +1 -0
  38. package/dest/node/barretenberg/testing/bigint-buffer.js +37 -0
  39. package/dest/node/barretenberg/testing/fields.d.ts +16 -0
  40. package/dest/node/barretenberg/testing/fields.d.ts.map +1 -0
  41. package/dest/node/barretenberg/testing/fields.js +48 -0
  42. package/dest/node/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  43. package/dest/node/bb_backends/index.d.ts +8 -5
  44. package/dest/node/bb_backends/index.d.ts.map +1 -1
  45. package/dest/node/bb_backends/index.js +5 -5
  46. package/dest/node/bb_backends/node/index.d.ts.map +1 -1
  47. package/dest/node/bb_backends/node/index.js +12 -4
  48. package/dest/node/bb_backends/node/native_shm.d.ts +2 -1
  49. package/dest/node/bb_backends/node/native_shm.d.ts.map +1 -1
  50. package/dest/node/bb_backends/node/native_shm.js +50 -15
  51. package/dest/node/bb_backends/node/native_socket.d.ts +1 -1
  52. package/dest/node/bb_backends/node/native_socket.d.ts.map +1 -1
  53. package/dest/node/bb_backends/node/native_socket.js +28 -19
  54. package/dest/node-cjs/barretenberg/backend.d.ts +9 -23
  55. package/dest/node-cjs/barretenberg/backend.d.ts.map +1 -1
  56. package/dest/node-cjs/barretenberg/backend.js +30 -90
  57. package/dest/node-cjs/barretenberg/blake2s.test.js +6 -6
  58. package/dest/node-cjs/barretenberg/index.d.ts +1 -3
  59. package/dest/node-cjs/barretenberg/index.d.ts.map +1 -1
  60. package/dest/node-cjs/barretenberg/index.js +15 -24
  61. package/dest/node-cjs/barretenberg/pedersen.test.js +9 -9
  62. package/dest/node-cjs/barretenberg/poseidon.bench.test.js +36 -77
  63. package/dest/node-cjs/barretenberg/poseidon.test.js +4 -4
  64. package/dest/node-cjs/{bigint-array/index.d.ts → barretenberg/testing/bigint-buffer.d.ts} +1 -1
  65. package/dest/node-cjs/barretenberg/testing/bigint-buffer.d.ts.map +1 -0
  66. package/dest/node-cjs/barretenberg/testing/bigint-buffer.js +43 -0
  67. package/dest/node-cjs/barretenberg/testing/fields.d.ts +16 -0
  68. package/dest/node-cjs/barretenberg/testing/fields.d.ts.map +1 -0
  69. package/dest/node-cjs/barretenberg/testing/fields.js +52 -0
  70. package/dest/node-cjs/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  71. package/dest/node-cjs/bb_backends/index.d.ts +8 -5
  72. package/dest/node-cjs/bb_backends/index.d.ts.map +1 -1
  73. package/dest/node-cjs/bb_backends/index.js +5 -5
  74. package/dest/node-cjs/bb_backends/node/index.d.ts.map +1 -1
  75. package/dest/node-cjs/bb_backends/node/index.js +12 -4
  76. package/dest/node-cjs/bb_backends/node/native_shm.d.ts +2 -1
  77. package/dest/node-cjs/bb_backends/node/native_shm.d.ts.map +1 -1
  78. package/dest/node-cjs/bb_backends/node/native_shm.js +50 -15
  79. package/dest/node-cjs/bb_backends/node/native_socket.d.ts +1 -1
  80. package/dest/node-cjs/bb_backends/node/native_socket.d.ts.map +1 -1
  81. package/dest/node-cjs/bb_backends/node/native_socket.js +28 -19
  82. package/package.json +1 -1
  83. package/src/barretenberg/backend.ts +19 -97
  84. package/src/barretenberg/blake2s.test.ts +1 -1
  85. package/src/barretenberg/index.ts +14 -24
  86. package/src/barretenberg/pedersen.test.ts +1 -1
  87. package/src/barretenberg/poseidon.bench.test.ts +109 -156
  88. package/src/barretenberg/poseidon.test.ts +1 -1
  89. package/src/{types → barretenberg/testing}/fields.ts +12 -26
  90. package/src/bb_backends/index.ts +8 -5
  91. package/src/bb_backends/node/index.ts +23 -3
  92. package/src/bb_backends/node/native_shm.ts +51 -14
  93. package/src/bb_backends/node/native_socket.ts +31 -17
  94. package/dest/browser/bigint-array/index.d.ts.map +0 -1
  95. package/dest/browser/bigint-array/index.js +0 -37
  96. package/dest/browser/serialize/index.d.ts +0 -2
  97. package/dest/browser/serialize/index.d.ts.map +0 -1
  98. package/dest/browser/serialize/index.js +0 -2
  99. package/dest/browser/serialize/serialize.d.ts +0 -18
  100. package/dest/browser/serialize/serialize.d.ts.map +0 -1
  101. package/dest/browser/serialize/serialize.js +0 -72
  102. package/dest/browser/types/fields.d.ts +0 -23
  103. package/dest/browser/types/fields.d.ts.map +0 -1
  104. package/dest/browser/types/fields.js +0 -61
  105. package/dest/browser/types/index.d.ts +0 -3
  106. package/dest/browser/types/index.d.ts.map +0 -1
  107. package/dest/browser/types/index.js +0 -3
  108. package/dest/browser/types/point.d.ts +0 -18
  109. package/dest/browser/types/point.d.ts.map +0 -1
  110. package/dest/browser/types/point.js +0 -28
  111. package/dest/node/bigint-array/index.d.ts.map +0 -1
  112. package/dest/node/bigint-array/index.js +0 -37
  113. package/dest/node/serialize/index.d.ts +0 -2
  114. package/dest/node/serialize/index.d.ts.map +0 -1
  115. package/dest/node/serialize/index.js +0 -2
  116. package/dest/node/serialize/serialize.d.ts +0 -18
  117. package/dest/node/serialize/serialize.d.ts.map +0 -1
  118. package/dest/node/serialize/serialize.js +0 -72
  119. package/dest/node/types/fields.d.ts +0 -23
  120. package/dest/node/types/fields.d.ts.map +0 -1
  121. package/dest/node/types/fields.js +0 -61
  122. package/dest/node/types/index.d.ts +0 -3
  123. package/dest/node/types/index.d.ts.map +0 -1
  124. package/dest/node/types/index.js +0 -3
  125. package/dest/node/types/point.d.ts +0 -18
  126. package/dest/node/types/point.d.ts.map +0 -1
  127. package/dest/node/types/point.js +0 -28
  128. package/dest/node-cjs/bigint-array/index.d.ts.map +0 -1
  129. package/dest/node-cjs/bigint-array/index.js +0 -43
  130. package/dest/node-cjs/serialize/index.d.ts +0 -2
  131. package/dest/node-cjs/serialize/index.d.ts.map +0 -1
  132. package/dest/node-cjs/serialize/index.js +0 -5
  133. package/dest/node-cjs/serialize/serialize.d.ts +0 -18
  134. package/dest/node-cjs/serialize/serialize.d.ts.map +0 -1
  135. package/dest/node-cjs/serialize/serialize.js +0 -82
  136. package/dest/node-cjs/types/fields.d.ts +0 -23
  137. package/dest/node-cjs/types/fields.d.ts.map +0 -1
  138. package/dest/node-cjs/types/fields.js +0 -65
  139. package/dest/node-cjs/types/index.d.ts +0 -3
  140. package/dest/node-cjs/types/index.d.ts.map +0 -1
  141. package/dest/node-cjs/types/index.js +0 -6
  142. package/dest/node-cjs/types/point.d.ts +0 -18
  143. package/dest/node-cjs/types/point.d.ts.map +0 -1
  144. package/dest/node-cjs/types/point.js +0 -32
  145. package/src/serialize/index.ts +0 -1
  146. package/src/serialize/serialize.ts +0 -75
  147. package/src/types/index.ts +0 -2
  148. package/src/types/point.ts +0 -32
  149. /package/src/{bigint-array/index.ts → barretenberg/testing/bigint-buffer.ts} +0 -0
@@ -31,7 +31,7 @@ export class Barretenberg extends AsyncApi {
31
31
  *
32
32
  * If options.backend is set: uses that specific backend (throws if unavailable)
33
33
  * If options.backend is unset: tries backends in order with fallback:
34
- * 1. NativeSharedMemory (if bb binary available)
34
+ * 1. NativeUnixSocket (if bb binary available)
35
35
  * 2. WasmWorker (in browser) or Wasm (in Node.js)
36
36
  */
37
37
  static async new(options: BackendOptions = {}) {
@@ -39,35 +39,30 @@ export class Barretenberg extends AsyncApi {
39
39
 
40
40
  if (options.backend) {
41
41
  // Explicit backend required - no fallback
42
- return await createAsyncBackend(options.backend, options, logger);
42
+ const backend = await createAsyncBackend(options.backend, options, logger);
43
+ if (options.backend === BackendType.Wasm || options.backend === BackendType.WasmWorker) {
44
+ await backend.initSRSChonk();
45
+ }
46
+ return backend;
43
47
  }
44
48
 
45
49
  if (typeof window === 'undefined') {
46
50
  try {
47
- return await createAsyncBackend(BackendType.NativeSharedMemory, options, logger);
51
+ return await createAsyncBackend(BackendType.NativeUnixSocket, options, logger);
48
52
  } catch (err: any) {
49
- logger(`Shared memory unavailable (${err.message}), falling back to other backends`);
50
- try {
51
- return await createAsyncBackend(BackendType.NativeUnixSocket, options, logger);
52
- } catch (err: any) {
53
- logger(`Unix socket unavailable (${err.message}), falling back to WASM`);
54
- return await createAsyncBackend(BackendType.Wasm, options, logger);
55
- }
53
+ logger(`Unix socket unavailable (${err.message}), falling back to WASM`);
54
+ const backend = await createAsyncBackend(BackendType.Wasm, options, logger);
55
+ await backend.initSRSChonk();
56
+ return backend;
56
57
  }
57
58
  } else {
58
59
  logger(`In browser, using WASM over worker backend.`);
59
- return await createAsyncBackend(BackendType.WasmWorker, options, logger);
60
+ const backend = await createAsyncBackend(BackendType.WasmWorker, options, logger);
61
+ await backend.initSRSChonk();
62
+ return backend;
60
63
  }
61
64
  }
62
65
 
63
- async initSRSForCircuitSize(circuitSize: number): Promise<void> {
64
- const minSRSSize = 2 ** 9; // 2**9 is the dyadic size for the SmallSubgroupIPA MSM.
65
- const crs = await Crs.new(Math.max(circuitSize, minSRSSize) + 1, this.options.crsPath, this.options.logger);
66
- // TODO(https://github.com/AztecProtocol/barretenberg/issues/1129): Do slab allocator initialization?
67
- // await this.commonInitSlabAllocator(circuitSize);
68
- await this.srsInitSrs({ pointsBuf: crs.getG1Data(), numPoints: crs.numPoints, g2Point: crs.getG2Data() });
69
- }
70
-
71
66
  async initSRSChonk(srsSize = this.getDefaultSrsSize()): Promise<void> {
72
67
  // crsPath can be undefined
73
68
  const crs = await Crs.new(srsSize + 1, this.options.crsPath, this.options.logger);
@@ -106,11 +101,6 @@ export class Barretenberg extends AsyncApi {
106
101
  return [response.numGates, response.numGatesDyadic];
107
102
  }
108
103
 
109
- async acirInitSRS(bytecode: Uint8Array, recursive: boolean, honkRecursion: boolean): Promise<void> {
110
- const [_, subgroupSize] = await this.acirGetCircuitSizes(bytecode, recursive, honkRecursion);
111
- return this.initSRSForCircuitSize(subgroupSize);
112
- }
113
-
114
104
  async destroy() {
115
105
  return super.destroy();
116
106
  }
@@ -1,6 +1,6 @@
1
1
  import { BarretenbergSync } from './index.js';
2
2
  import { Timer } from '../benchmark/timer.js';
3
- import { Fr } from '../types/index.js';
3
+ import { Fr } from './testing/fields.js';
4
4
 
5
5
  describe('pedersen sync', () => {
6
6
  let api: BarretenbergSync;
@@ -1,9 +1,8 @@
1
1
  import { Barretenberg, BarretenbergSync } from '../index.js';
2
- import { Fr } from '../types/fields.js';
3
- import { serializeBufferable } from '../serialize/index.js';
4
2
  import { BarretenbergWasmMain } from '../barretenberg_wasm/barretenberg_wasm_main/index.js';
5
3
  import { fetchModuleAndThreads } from '../barretenberg_wasm/index.js';
6
4
  import { BackendType } from './index.js';
5
+ import { Fr } from './testing/fields.js';
7
6
 
8
7
  /**
9
8
  * Async API benchmark test: WASM vs Native backends with proper non-blocking I/O
@@ -67,170 +66,129 @@ describe('poseidon2Hash benchmark (Async API): WASM vs Native', () => {
67
66
  }
68
67
  }, 20000);
69
68
 
70
- afterAll(async () => {
71
- await wasm.destroy();
72
- if (wasmApi) {
73
- await wasmApi.destroy();
74
- }
75
- if (nativeSocketApi) {
76
- await nativeSocketApi.destroy();
77
- }
78
- if (nativeShmApi) {
79
- await nativeShmApi.destroy();
80
- }
81
- if (nativeShmSyncApi) {
82
- nativeShmSyncApi.destroy();
83
- }
84
- });
85
-
86
- async function directPoseidon2Hash(inputsBuffer: Fr[]): Promise<Fr> {
87
- const inArgs = [inputsBuffer].map(serializeBufferable);
88
- const outTypes = [Fr];
89
- const result = wasm.callWasmExport(
90
- 'poseidon2_hash',
91
- inArgs,
92
- outTypes.map(t => t.SIZE_IN_BYTES),
93
- );
94
- const out = result.map((r, i) => outTypes[i].fromBuffer(r));
95
- return Promise.resolve(out[0]);
96
- }
97
-
98
- it.each(SIZES)('benchmark with %p field elements', async size => {
99
- // Generate random inputs
100
- const inputs = Array(size)
101
- .fill(0)
102
- .map(() => Fr.random());
103
-
104
- // Benchmark 1: Direct WASM (baseline - always available)
105
- const directStart = performance.now();
106
- for (let i = 0; i < ITERATIONS; i++) {
107
- await directPoseidon2Hash(inputs);
108
- }
109
- const directTime = performance.now() - directStart;
69
+ it.each(SIZES)(
70
+ 'benchmark with %p field elements',
71
+ async size => {
72
+ // Generate random inputs
73
+ const inputs = Array(size)
74
+ .fill(0)
75
+ .map(() => Fr.random().toBuffer());
110
76
 
111
- // Benchmark 2: WASM (async)
112
- let wasmTime = 0;
113
- if (wasmApi) {
114
- const wasmStart = performance.now();
115
- for (let i = 0; i < ITERATIONS; i++) {
116
- await wasmApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
77
+ // Benchmark 1: WASM (async)
78
+ let wasmTime = 0;
79
+ if (wasmApi) {
80
+ const wasmStart = performance.now();
81
+ for (let i = 0; i < ITERATIONS; i++) {
82
+ await wasmApi.poseidon2Hash({ inputs });
83
+ }
84
+ wasmTime = performance.now() - wasmStart;
117
85
  }
118
- wasmTime = performance.now() - wasmStart;
119
- }
120
86
 
121
- // Benchmark 3: Native Socket (async with non-blocking I/O)
122
- let nativeSocketTime = 0;
123
- if (nativeSocketApi) {
124
- const nativeSocketStart = performance.now();
125
- for (let i = 0; i < ITERATIONS; i++) {
126
- await nativeSocketApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
87
+ // Benchmark 2: Native Socket (async with non-blocking I/O)
88
+ let nativeSocketTime = 0;
89
+ if (nativeSocketApi) {
90
+ const nativeSocketStart = performance.now();
91
+ for (let i = 0; i < ITERATIONS; i++) {
92
+ await nativeSocketApi.poseidon2Hash({ inputs });
93
+ }
94
+ nativeSocketTime = performance.now() - nativeSocketStart;
127
95
  }
128
- nativeSocketTime = performance.now() - nativeSocketStart;
129
- }
130
96
 
131
- // Benchmark 4: Native Shared Memory (async)
132
- let nativeShmTime = 0;
133
- if (nativeShmApi) {
134
- const nativeShmStart = performance.now();
135
- for (let i = 0; i < ITERATIONS; i++) {
136
- await nativeShmApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
97
+ // Benchmark 3: Native Shared Memory (async)
98
+ let nativeShmTime = 0;
99
+ if (nativeShmApi) {
100
+ const nativeShmStart = performance.now();
101
+ for (let i = 0; i < ITERATIONS; i++) {
102
+ await nativeShmApi.poseidon2Hash({ inputs });
103
+ }
104
+ nativeShmTime = performance.now() - nativeShmStart;
137
105
  }
138
- nativeShmTime = performance.now() - nativeShmStart;
139
- }
140
106
 
141
- // Benchmark 5: Native Shared Memory (sync)
142
- let nativeShmSyncTime = 0;
143
- if (nativeShmSyncApi) {
144
- const nativeShmSyncStart = performance.now();
145
- for (let i = 0; i < ITERATIONS; i++) {
146
- nativeShmSyncApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
107
+ // Benchmark 4: Native Shared Memory (sync)
108
+ let nativeShmSyncTime = 0;
109
+ if (nativeShmSyncApi) {
110
+ const nativeShmSyncStart = performance.now();
111
+ for (let i = 0; i < ITERATIONS; i++) {
112
+ nativeShmSyncApi.poseidon2Hash({ inputs });
113
+ }
114
+ nativeShmSyncTime = performance.now() - nativeShmSyncStart;
147
115
  }
148
- nativeShmSyncTime = performance.now() - nativeShmSyncStart;
149
- }
150
-
151
- // Calculate metrics (all relative to WASM baseline)
152
- const directOverhead = ((directTime - wasmTime) / wasmTime) * 100;
153
- const nativeSocketOverhead = ((nativeSocketTime - wasmTime) / wasmTime) * 100;
154
- const nativeShmOverhead = ((nativeShmTime - wasmTime) / wasmTime) * 100;
155
- const nativeShmSyncOverhead = ((nativeShmSyncTime - wasmTime) / wasmTime) * 100;
156
116
 
157
- const avgDirectTimeUs = (directTime / ITERATIONS) * 1000; // microseconds
158
- const avgWasmTimeUs = (wasmTime / ITERATIONS) * 1000;
159
- const avgNativeSocketTimeUs = (nativeSocketTime / ITERATIONS) * 1000;
160
- const avgNativeShmTimeUs = (nativeShmTime / ITERATIONS) * 1000;
161
- const avgNativeShmSyncTimeUs = (nativeShmSyncTime / ITERATIONS) * 1000;
117
+ // Calculate metrics (all relative to WASM baseline)
118
+ const nativeSocketOverhead = ((nativeSocketTime - wasmTime) / wasmTime) * 100;
119
+ const nativeShmOverhead = ((nativeShmTime - wasmTime) / wasmTime) * 100;
120
+ const nativeShmSyncOverhead = ((nativeShmSyncTime - wasmTime) / wasmTime) * 100;
162
121
 
163
- process.stdout.write(`┌─ Size ${size.toString().padStart(3)} field elements ──────────────────────────────────┐\n`);
164
- const formatOverhead = (overhead: number): string => {
165
- const sign = overhead >= 0 ? '+' : '-';
166
- const value = Math.abs(overhead).toFixed(1).padStart(6);
167
- return `${sign}${value}%`;
168
- };
122
+ const avgWasmTimeUs = (wasmTime / ITERATIONS) * 1000;
123
+ const avgNativeSocketTimeUs = (nativeSocketTime / ITERATIONS) * 1000;
124
+ const avgNativeShmTimeUs = (nativeShmTime / ITERATIONS) * 1000;
125
+ const avgNativeShmSyncTimeUs = (nativeShmSyncTime / ITERATIONS) * 1000;
169
126
 
170
- if (wasmApi) {
171
127
  process.stdout.write(
172
- `│ WASM: ${wasmTime.toFixed(2).padStart(8)}ms (${avgWasmTimeUs.toFixed(2).padStart(7)}µs/call) [baseline] │\n`,
128
+ `┌─ Size ${size.toString().padStart(3)} field elements ──────────────────────────────────┐\n`,
173
129
  );
174
- } else {
175
- process.stdout.write(`│ WASM: unavailable │\n`);
176
- }
130
+ const formatOverhead = (overhead: number): string => {
131
+ const sign = overhead >= 0 ? '+' : '-';
132
+ const value = Math.abs(overhead).toFixed(1).padStart(6);
133
+ return `${sign}${value}%`;
134
+ };
177
135
 
178
- process.stdout.write(
179
- `│ Direct WASM: ${directTime.toFixed(2).padStart(8)}ms (${avgDirectTimeUs.toFixed(2).padStart(7)}µs/call) ${formatOverhead(directOverhead)} │\n`,
180
- );
181
-
182
- if (nativeSocketApi) {
183
- process.stdout.write(
184
- `│ Native Socket: ${nativeSocketTime.toFixed(2).padStart(8)}ms (${avgNativeSocketTimeUs.toFixed(2).padStart(7)}µs/call) ${formatOverhead(nativeSocketOverhead)} │\n`,
185
- );
186
- } else {
187
- process.stdout.write(`│ Native Socket: unavailable │\n`);
188
- }
136
+ if (wasmApi) {
137
+ process.stdout.write(
138
+ `│ WASM: ${wasmTime.toFixed(2).padStart(8)}ms (${avgWasmTimeUs.toFixed(2).padStart(7)}µs/call) [baseline] │\n`,
139
+ );
140
+ } else {
141
+ process.stdout.write(`│ WASM: unavailable │\n`);
142
+ }
189
143
 
190
- if (nativeShmApi) {
191
- process.stdout.write(
192
- `│ Native Shared: ${nativeShmTime.toFixed(2).padStart(8)}ms (${avgNativeShmTimeUs.toFixed(2).padStart(7)}µs/call) ${formatOverhead(nativeShmOverhead)} │\n`,
193
- );
194
- } else {
195
- process.stdout.write(`│ Native Shared: unavailable │\n`);
196
- }
144
+ if (nativeSocketApi) {
145
+ process.stdout.write(
146
+ `│ Native Socket: ${nativeSocketTime.toFixed(2).padStart(8)}ms (${avgNativeSocketTimeUs.toFixed(2).padStart(7)}µs/call) ${formatOverhead(nativeSocketOverhead)} │\n`,
147
+ );
148
+ } else {
149
+ process.stdout.write(`│ Native Socket: unavailable │\n`);
150
+ }
197
151
 
198
- if (nativeShmSyncApi) {
199
- process.stdout.write(
200
- `│ Native Shared Sync: ${nativeShmSyncTime.toFixed(2).padStart(8)}ms (${avgNativeShmSyncTimeUs.toFixed(2).padStart(7)}µs/call) ${formatOverhead(nativeShmSyncOverhead)} │\n`,
201
- );
202
- } else {
203
- process.stdout.write(`│ Native Shared Sync: unavailable │\n`);
204
- }
152
+ if (nativeShmApi) {
153
+ process.stdout.write(
154
+ `│ Native Shared: ${nativeShmTime.toFixed(2).padStart(8)}ms (${avgNativeShmTimeUs.toFixed(2).padStart(7)}µs/call) ${formatOverhead(nativeShmOverhead)} │\n`,
155
+ );
156
+ } else {
157
+ process.stdout.write(`│ Native Shared: unavailable │\n`);
158
+ }
205
159
 
206
- process.stdout.write(`└────────────────────────────────────────────────────────────┘\n`);
160
+ if (nativeShmSyncApi) {
161
+ process.stdout.write(
162
+ `│ Native Shared Sync: ${nativeShmSyncTime.toFixed(2).padStart(8)}ms (${avgNativeShmSyncTimeUs.toFixed(2).padStart(7)}µs/call) ${formatOverhead(nativeShmSyncOverhead)} │\n`,
163
+ );
164
+ } else {
165
+ process.stdout.write(`│ Native Shared Sync: unavailable │\n`);
166
+ }
207
167
 
208
- // Sanity check: verify all backends produce same result as direct WASM
209
- const directResult = await directPoseidon2Hash(inputs);
168
+ process.stdout.write(`└────────────────────────────────────────────────────────────┘\n`);
210
169
 
211
- if (wasmApi) {
212
- const wasmResult = await wasmApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
213
- expect(Buffer.from(wasmResult.hash)).toEqual(directResult.toBuffer());
214
- }
170
+ const wasmResult = await wasmApi!.poseidon2Hash({ inputs });
215
171
 
216
- if (nativeSocketApi) {
217
- const nativeSocketResult = await nativeSocketApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
218
- expect(Buffer.from(nativeSocketResult.hash)).toEqual(directResult.toBuffer());
219
- }
172
+ if (nativeSocketApi) {
173
+ const nativeSocketResult = await nativeSocketApi.poseidon2Hash({ inputs });
174
+ expect(Buffer.from(nativeSocketResult.hash)).toEqual(wasmResult.hash);
175
+ }
220
176
 
221
- if (nativeShmApi) {
222
- const nativeShmResult = await nativeShmApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
223
- expect(Buffer.from(nativeShmResult.hash)).toEqual(directResult.toBuffer());
224
- }
177
+ if (nativeShmApi) {
178
+ const nativeShmResult = await nativeShmApi.poseidon2Hash({ inputs });
179
+ expect(Buffer.from(nativeShmResult.hash)).toEqual(wasmResult.hash);
180
+ }
225
181
 
226
- if (nativeShmSyncApi) {
227
- const nativeShmSyncResult = nativeShmSyncApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
228
- expect(Buffer.from(nativeShmSyncResult.hash)).toEqual(directResult.toBuffer());
229
- }
182
+ if (nativeShmSyncApi) {
183
+ const nativeShmSyncResult = nativeShmSyncApi.poseidon2Hash({ inputs });
184
+ expect(Buffer.from(nativeShmSyncResult.hash)).toEqual(wasmResult.hash);
185
+ }
230
186
 
231
- // Test always passes, this is just for measuring performance
232
- expect(true).toBe(true);
233
- });
187
+ // Test always passes, this is just for measuring performance
188
+ expect(true).toBe(true);
189
+ },
190
+ 10000,
191
+ );
234
192
 
235
193
  const TEST_VECTORS = [1, 2, 3, 5, 10, 50, 100];
236
194
  const NUM_RANDOM_TESTS = 10;
@@ -240,28 +198,23 @@ describe('poseidon2Hash benchmark (Async API): WASM vs Native', () => {
240
198
  for (let test = 0; test < NUM_RANDOM_TESTS; test++) {
241
199
  const inputs = Array(size)
242
200
  .fill(0)
243
- .map(() => Fr.random());
201
+ .map(() => Fr.random().toBuffer());
244
202
 
245
- const directResult = await directPoseidon2Hash(inputs);
246
-
247
- if (wasmApi) {
248
- const wasmResult = await wasmApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
249
- expect(Buffer.from(wasmResult.hash)).toEqual(directResult.toBuffer());
250
- }
203
+ const wasmResult = await wasmApi!.poseidon2Hash({ inputs });
251
204
 
252
205
  if (nativeSocketApi) {
253
- const nativeSocketResult = await nativeSocketApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
254
- expect(Buffer.from(nativeSocketResult.hash)).toEqual(directResult.toBuffer());
206
+ const nativeSocketResult = await nativeSocketApi.poseidon2Hash({ inputs });
207
+ expect(Buffer.from(nativeSocketResult.hash)).toEqual(wasmResult.hash);
255
208
  }
256
209
 
257
210
  if (nativeShmApi) {
258
- const nativeShmResult = await nativeShmApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
259
- expect(Buffer.from(nativeShmResult.hash)).toEqual(directResult.toBuffer());
211
+ const nativeShmResult = await nativeShmApi.poseidon2Hash({ inputs });
212
+ expect(Buffer.from(nativeShmResult.hash)).toEqual(wasmResult.hash);
260
213
  }
261
214
 
262
215
  if (nativeShmSyncApi) {
263
- const nativeShmSyncResult = nativeShmSyncApi.poseidon2Hash({ inputs: inputs.map(fr => fr.toBuffer()) });
264
- expect(Buffer.from(nativeShmSyncResult.hash)).toEqual(directResult.toBuffer());
216
+ const nativeShmSyncResult = nativeShmSyncApi.poseidon2Hash({ inputs });
217
+ expect(Buffer.from(nativeShmSyncResult.hash)).toEqual(wasmResult.hash);
265
218
  }
266
219
  }
267
220
  });
@@ -1,6 +1,6 @@
1
1
  import { BarretenbergSync } from './index.js';
2
2
  import { Timer } from '../benchmark/timer.js';
3
- import { Fr } from '../types/index.js';
3
+ import { Fr } from './testing/fields.js';
4
4
 
5
5
  describe('poseidon sync', () => {
6
6
  let api: BarretenbergSync;
@@ -1,17 +1,11 @@
1
- import { randomBytes } from '../random/index.js';
1
+ import { randomBytes } from '../../random/index.js';
2
2
  import {
3
3
  buffer32BytesToBigIntBE,
4
4
  uint8ArrayToBigIntBE,
5
5
  bigIntToBufferBE,
6
6
  bigIntToUint8ArrayBE,
7
- } from '../bigint-array/index.js';
7
+ } from './bigint-buffer.js';
8
8
 
9
- /**
10
- * Internal Fr field class for tests.
11
- * @dev This minimal implementation is provided for testing barretenberg directly.
12
- * Projects using bb.js should create their own field abstraction using the curve constants
13
- * exported from the barretenberg binary (see CurveConstants generation).
14
- */
15
9
  export class Fr {
16
10
  static ZERO = new Fr(0n);
17
11
  static MODULUS = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n;
@@ -41,24 +35,6 @@ export class Fr {
41
35
  return new this(r);
42
36
  }
43
37
 
44
- static fromBuffer(buffer: Uint8Array | Buffer) {
45
- if (buffer.length !== this.SIZE_IN_BYTES) {
46
- throw new Error(`Expected ${this.SIZE_IN_BYTES} bytes, got ${buffer.length}`);
47
- }
48
- return new this(buffer);
49
- }
50
-
51
- static fromBufferReduce(buffer: Uint8Array | Buffer) {
52
- if (buffer.length !== this.SIZE_IN_BYTES) {
53
- throw new Error(`Expected ${this.SIZE_IN_BYTES} bytes, got ${buffer.length}`);
54
- }
55
- return new this(uint8ArrayToBigIntBE(buffer instanceof Buffer ? new Uint8Array(buffer) : buffer) % Fr.MODULUS);
56
- }
57
-
58
- static fromString(str: string) {
59
- return this.fromBuffer(Buffer.from(str.replace(/^0x/i, ''), 'hex'));
60
- }
61
-
62
38
  toBuffer() {
63
39
  return this.value;
64
40
  }
@@ -74,4 +50,14 @@ export class Fr {
74
50
  isZero() {
75
51
  return this.value.every(v => v === 0);
76
52
  }
53
+
54
+ static fromBuffer(value: Uint8Array): Fr {
55
+ return Fr.fromBufferReduce(value);
56
+ }
57
+
58
+ static fromBufferReduce(value: Uint8Array): Fr {
59
+ const valueBigInt = uint8ArrayToBigIntBE(value);
60
+ const reducedValue = valueBigInt % Fr.MODULUS;
61
+ return new Fr(reducedValue);
62
+ }
77
63
  }
@@ -3,13 +3,13 @@
3
3
  */
4
4
  export enum BackendType {
5
5
  /** WASM direct execution (no worker) */
6
- Wasm = 'wasm',
6
+ Wasm = 'Wasm',
7
7
  /** WASM with worker threads */
8
- WasmWorker = 'wasm-worker',
8
+ WasmWorker = 'WasmWorker',
9
9
  /** Native via Unix domain socket (async only) */
10
- NativeUnixSocket = 'native-unix-socket',
10
+ NativeUnixSocket = 'NativeUnixSocket',
11
11
  /** Native via shared memory (sync only currently) */
12
- NativeSharedMemory = 'native-shared-mem',
12
+ NativeSharedMemory = 'NativeSharedMemory',
13
13
  }
14
14
 
15
15
  export type BackendOptions = {
@@ -28,7 +28,10 @@ export type BackendOptions = {
28
28
  /** @description Custom path to bb binary for native backend (overrides automatic detection) */
29
29
  bbPath?: string;
30
30
 
31
- /** @description Logging function */
31
+ /**
32
+ * @description Logging function
33
+ * Warning: Attaching a logger can prevent nodejs from exiting without explicitly destroying the backend.
34
+ */
32
35
  logger?: (msg: string) => void;
33
36
 
34
37
  /**
@@ -14,6 +14,11 @@ export async function createAsyncBackend(
14
14
  options: BackendOptions,
15
15
  logger: (msg: string) => void,
16
16
  ): Promise<Barretenberg> {
17
+ options = {
18
+ ...options,
19
+ wasmPath: options.wasmPath ?? process.env.BB_WASM_PATH,
20
+ };
21
+
17
22
  switch (type) {
18
23
  case BackendType.NativeUnixSocket: {
19
24
  const bbPath = findBbBinary(options.bbPath);
@@ -21,7 +26,7 @@ export async function createAsyncBackend(
21
26
  throw new Error('Native backend requires bb binary.');
22
27
  }
23
28
  logger(`Using native Unix socket backend: ${bbPath}`);
24
- const socket = new BarretenbergNativeSocketAsyncBackend(bbPath, options.threads);
29
+ const socket = new BarretenbergNativeSocketAsyncBackend(bbPath, options.threads, options.logger);
25
30
  return new Barretenberg(socket, options);
26
31
  }
27
32
 
@@ -36,7 +41,12 @@ export async function createAsyncBackend(
36
41
  }
37
42
  logger(`Using native shared memory backend (via sync adapter): ${bbPath}`);
38
43
  // Use sync backend with adapter to provide async interface
39
- const syncBackend = await BarretenbergNativeShmSyncBackend.new(bbPath, options.threads, options.maxClients);
44
+ const syncBackend = await BarretenbergNativeShmSyncBackend.new(
45
+ bbPath,
46
+ options.threads,
47
+ options.maxClients,
48
+ options.logger,
49
+ );
40
50
  const asyncBackend = new SyncToAsyncAdapter(syncBackend);
41
51
  return new Barretenberg(asyncBackend, options);
42
52
  }
@@ -68,6 +78,11 @@ export async function createSyncBackend(
68
78
  options: BackendOptions,
69
79
  logger: (msg: string) => void,
70
80
  ): Promise<BarretenbergSync> {
81
+ options = {
82
+ ...options,
83
+ wasmPath: options.wasmPath ?? process.env.BB_WASM_PATH,
84
+ };
85
+
71
86
  switch (type) {
72
87
  case BackendType.NativeSharedMemory: {
73
88
  const bbPath = findBbBinary(options.bbPath);
@@ -79,7 +94,12 @@ export async function createSyncBackend(
79
94
  throw new Error('Native sync backend requires napi client stub.');
80
95
  }
81
96
  logger(`Using native shared memory backend: ${bbPath}`);
82
- const shm = await BarretenbergNativeShmSyncBackend.new(bbPath, options.threads, options.maxClients);
97
+ const shm = await BarretenbergNativeShmSyncBackend.new(
98
+ bbPath,
99
+ options.threads,
100
+ options.maxClients,
101
+ options.logger,
102
+ );
83
103
  return new BarretenbergSync(shm);
84
104
  }
85
105