@aztec/bb.js 3.0.0-nightly.20251115 → 3.0.0-nightly.20251119

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 (169) 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/browser/platform.d.ts +4 -0
  24. package/dest/browser/bb_backends/browser/platform.d.ts.map +1 -0
  25. package/dest/browser/bb_backends/browser/platform.js +10 -0
  26. package/dest/browser/bb_backends/index.d.ts +8 -5
  27. package/dest/browser/bb_backends/index.d.ts.map +1 -1
  28. package/dest/browser/bb_backends/index.js +5 -5
  29. package/dest/browser/index.d.ts +1 -0
  30. package/dest/browser/index.d.ts.map +1 -1
  31. package/dest/browser/index.js +2 -1
  32. package/dest/node/barretenberg/backend.d.ts +9 -23
  33. package/dest/node/barretenberg/backend.d.ts.map +1 -1
  34. package/dest/node/barretenberg/backend.js +24 -84
  35. package/dest/node/barretenberg/blake2s.test.js +2 -2
  36. package/dest/node/barretenberg/index.d.ts +1 -3
  37. package/dest/node/barretenberg/index.d.ts.map +1 -1
  38. package/dest/node/barretenberg/index.js +15 -24
  39. package/dest/node/barretenberg/pedersen.test.js +2 -2
  40. package/dest/node/barretenberg/poseidon.bench.test.js +27 -68
  41. package/dest/node/barretenberg/poseidon.test.js +2 -2
  42. package/dest/node/{bigint-array/index.d.ts → barretenberg/testing/bigint-buffer.d.ts} +1 -1
  43. package/dest/node/barretenberg/testing/bigint-buffer.d.ts.map +1 -0
  44. package/dest/node/barretenberg/testing/bigint-buffer.js +37 -0
  45. package/dest/node/barretenberg/testing/fields.d.ts +16 -0
  46. package/dest/node/barretenberg/testing/fields.d.ts.map +1 -0
  47. package/dest/node/barretenberg/testing/fields.js +48 -0
  48. package/dest/node/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  49. package/dest/node/bb_backends/browser/platform.d.ts +4 -0
  50. package/dest/node/bb_backends/browser/platform.d.ts.map +1 -0
  51. package/dest/node/bb_backends/browser/platform.js +10 -0
  52. package/dest/node/bb_backends/index.d.ts +8 -5
  53. package/dest/node/bb_backends/index.d.ts.map +1 -1
  54. package/dest/node/bb_backends/index.js +5 -5
  55. package/dest/node/bb_backends/node/index.d.ts.map +1 -1
  56. package/dest/node/bb_backends/node/index.js +12 -4
  57. package/dest/node/bb_backends/node/native_shm.d.ts +2 -1
  58. package/dest/node/bb_backends/node/native_shm.d.ts.map +1 -1
  59. package/dest/node/bb_backends/node/native_shm.js +50 -15
  60. package/dest/node/bb_backends/node/native_socket.d.ts +1 -1
  61. package/dest/node/bb_backends/node/native_socket.d.ts.map +1 -1
  62. package/dest/node/bb_backends/node/native_socket.js +28 -19
  63. package/dest/node/index.d.ts +1 -0
  64. package/dest/node/index.d.ts.map +1 -1
  65. package/dest/node/index.js +2 -1
  66. package/dest/node-cjs/barretenberg/backend.d.ts +9 -23
  67. package/dest/node-cjs/barretenberg/backend.d.ts.map +1 -1
  68. package/dest/node-cjs/barretenberg/backend.js +30 -90
  69. package/dest/node-cjs/barretenberg/blake2s.test.js +6 -6
  70. package/dest/node-cjs/barretenberg/index.d.ts +1 -3
  71. package/dest/node-cjs/barretenberg/index.d.ts.map +1 -1
  72. package/dest/node-cjs/barretenberg/index.js +15 -24
  73. package/dest/node-cjs/barretenberg/pedersen.test.js +9 -9
  74. package/dest/node-cjs/barretenberg/poseidon.bench.test.js +36 -77
  75. package/dest/node-cjs/barretenberg/poseidon.test.js +4 -4
  76. package/dest/node-cjs/{bigint-array/index.d.ts → barretenberg/testing/bigint-buffer.d.ts} +1 -1
  77. package/dest/node-cjs/barretenberg/testing/bigint-buffer.d.ts.map +1 -0
  78. package/dest/node-cjs/barretenberg/testing/bigint-buffer.js +43 -0
  79. package/dest/node-cjs/barretenberg/testing/fields.d.ts +16 -0
  80. package/dest/node-cjs/barretenberg/testing/fields.d.ts.map +1 -0
  81. package/dest/node-cjs/barretenberg/testing/fields.js +52 -0
  82. package/dest/node-cjs/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  83. package/dest/node-cjs/bb_backends/browser/platform.d.ts +4 -0
  84. package/dest/node-cjs/bb_backends/browser/platform.d.ts.map +1 -0
  85. package/dest/node-cjs/bb_backends/browser/platform.js +15 -0
  86. package/dest/node-cjs/bb_backends/index.d.ts +8 -5
  87. package/dest/node-cjs/bb_backends/index.d.ts.map +1 -1
  88. package/dest/node-cjs/bb_backends/index.js +5 -5
  89. package/dest/node-cjs/bb_backends/node/index.d.ts.map +1 -1
  90. package/dest/node-cjs/bb_backends/node/index.js +12 -4
  91. package/dest/node-cjs/bb_backends/node/native_shm.d.ts +2 -1
  92. package/dest/node-cjs/bb_backends/node/native_shm.d.ts.map +1 -1
  93. package/dest/node-cjs/bb_backends/node/native_shm.js +50 -15
  94. package/dest/node-cjs/bb_backends/node/native_socket.d.ts +1 -1
  95. package/dest/node-cjs/bb_backends/node/native_socket.d.ts.map +1 -1
  96. package/dest/node-cjs/bb_backends/node/native_socket.js +28 -19
  97. package/dest/node-cjs/index.d.ts +1 -0
  98. package/dest/node-cjs/index.d.ts.map +1 -1
  99. package/dest/node-cjs/index.js +4 -2
  100. package/package.json +1 -1
  101. package/src/barretenberg/backend.ts +19 -97
  102. package/src/barretenberg/blake2s.test.ts +1 -1
  103. package/src/barretenberg/index.ts +14 -24
  104. package/src/barretenberg/pedersen.test.ts +1 -1
  105. package/src/barretenberg/poseidon.bench.test.ts +109 -156
  106. package/src/barretenberg/poseidon.test.ts +1 -1
  107. package/src/{types → barretenberg/testing}/fields.ts +12 -26
  108. package/src/bb_backends/browser/platform.ts +11 -0
  109. package/src/bb_backends/index.ts +8 -5
  110. package/src/bb_backends/node/index.ts +23 -3
  111. package/src/bb_backends/node/native_shm.ts +51 -14
  112. package/src/bb_backends/node/native_socket.ts +31 -17
  113. package/src/index.ts +2 -0
  114. package/dest/browser/bigint-array/index.d.ts.map +0 -1
  115. package/dest/browser/bigint-array/index.js +0 -37
  116. package/dest/browser/serialize/index.d.ts +0 -2
  117. package/dest/browser/serialize/index.d.ts.map +0 -1
  118. package/dest/browser/serialize/index.js +0 -2
  119. package/dest/browser/serialize/serialize.d.ts +0 -18
  120. package/dest/browser/serialize/serialize.d.ts.map +0 -1
  121. package/dest/browser/serialize/serialize.js +0 -72
  122. package/dest/browser/types/fields.d.ts +0 -23
  123. package/dest/browser/types/fields.d.ts.map +0 -1
  124. package/dest/browser/types/fields.js +0 -61
  125. package/dest/browser/types/index.d.ts +0 -3
  126. package/dest/browser/types/index.d.ts.map +0 -1
  127. package/dest/browser/types/index.js +0 -3
  128. package/dest/browser/types/point.d.ts +0 -18
  129. package/dest/browser/types/point.d.ts.map +0 -1
  130. package/dest/browser/types/point.js +0 -28
  131. package/dest/node/bigint-array/index.d.ts.map +0 -1
  132. package/dest/node/bigint-array/index.js +0 -37
  133. package/dest/node/serialize/index.d.ts +0 -2
  134. package/dest/node/serialize/index.d.ts.map +0 -1
  135. package/dest/node/serialize/index.js +0 -2
  136. package/dest/node/serialize/serialize.d.ts +0 -18
  137. package/dest/node/serialize/serialize.d.ts.map +0 -1
  138. package/dest/node/serialize/serialize.js +0 -72
  139. package/dest/node/types/fields.d.ts +0 -23
  140. package/dest/node/types/fields.d.ts.map +0 -1
  141. package/dest/node/types/fields.js +0 -61
  142. package/dest/node/types/index.d.ts +0 -3
  143. package/dest/node/types/index.d.ts.map +0 -1
  144. package/dest/node/types/index.js +0 -3
  145. package/dest/node/types/point.d.ts +0 -18
  146. package/dest/node/types/point.d.ts.map +0 -1
  147. package/dest/node/types/point.js +0 -28
  148. package/dest/node-cjs/bigint-array/index.d.ts.map +0 -1
  149. package/dest/node-cjs/bigint-array/index.js +0 -43
  150. package/dest/node-cjs/serialize/index.d.ts +0 -2
  151. package/dest/node-cjs/serialize/index.d.ts.map +0 -1
  152. package/dest/node-cjs/serialize/index.js +0 -5
  153. package/dest/node-cjs/serialize/serialize.d.ts +0 -18
  154. package/dest/node-cjs/serialize/serialize.d.ts.map +0 -1
  155. package/dest/node-cjs/serialize/serialize.js +0 -82
  156. package/dest/node-cjs/types/fields.d.ts +0 -23
  157. package/dest/node-cjs/types/fields.d.ts.map +0 -1
  158. package/dest/node-cjs/types/fields.js +0 -65
  159. package/dest/node-cjs/types/index.d.ts +0 -3
  160. package/dest/node-cjs/types/index.d.ts.map +0 -1
  161. package/dest/node-cjs/types/index.js +0 -6
  162. package/dest/node-cjs/types/point.d.ts +0 -18
  163. package/dest/node-cjs/types/point.d.ts.map +0 -1
  164. package/dest/node-cjs/types/point.js +0 -32
  165. package/src/serialize/index.ts +0 -1
  166. package/src/serialize/serialize.ts +0 -75
  167. package/src/types/index.ts +0 -2
  168. package/src/types/point.ts +0 -32
  169. /package/src/{bigint-array/index.ts → barretenberg/testing/bigint-buffer.ts} +0 -0
@@ -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
  }
@@ -0,0 +1,11 @@
1
+ export function findPackageRoot(): string | null {
2
+ throw new Error('Not implemented in browser environment.');
3
+ }
4
+
5
+ export function findBbBinary(customPath?: string): string | null {
6
+ throw new Error('Not implemented in browser environment.');
7
+ }
8
+
9
+ export function findNapiBinary(customPath?: string): string | null {
10
+ throw new Error('Not implemented in browser environment.');
11
+ }
@@ -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
 
@@ -1,7 +1,9 @@
1
1
  import { createRequire } from 'module';
2
2
  import { spawn, ChildProcess } from 'child_process';
3
+ import { openSync, closeSync } from 'fs';
3
4
  import { IMsgpackBackendSync } from '../interface.js';
4
5
  import { findNapiBinary, findPackageRoot } from './platform.js';
6
+ import readline from 'readline';
5
7
 
6
8
  // Import the NAPI module
7
9
  // The addon is built to the nodejs_module directory
@@ -32,10 +34,12 @@ try {
32
34
  export class BarretenbergNativeShmSyncBackend implements IMsgpackBackendSync {
33
35
  private process: ChildProcess;
34
36
  private client: any; // NAPI MsgpackClient instance
37
+ private logFd?: number; // File descriptor for logs
35
38
 
36
- private constructor(process: ChildProcess, client: any) {
39
+ private constructor(process: ChildProcess, client: any, logFd?: number) {
37
40
  this.process = process;
38
41
  this.client = client;
42
+ this.logFd = logFd;
39
43
  }
40
44
 
41
45
  /**
@@ -48,6 +52,7 @@ export class BarretenbergNativeShmSyncBackend implements IMsgpackBackendSync {
48
52
  bbBinaryPath: string,
49
53
  threads?: number,
50
54
  maxClients?: number,
55
+ logger?: (msg: string) => void,
51
56
  ): Promise<BarretenbergNativeShmSyncBackend> {
52
57
  if (!addon || !addon.MsgpackClient) {
53
58
  throw new Error('Shared memory NAPI not available.');
@@ -59,22 +64,40 @@ export class BarretenbergNativeShmSyncBackend implements IMsgpackBackendSync {
59
64
  // Default maxClients to 1 if not specified
60
65
  const clientCount = maxClients ?? 1;
61
66
 
62
- // Set HARDWARE_CONCURRENCY if threads specified
63
- const env = threads !== undefined ? { ...process.env, HARDWARE_CONCURRENCY: threads.toString() } : process.env;
67
+ // If threads not set use 1 thread. We're not expected to do long lived work on sync backends.
68
+ const hwc = threads ? threads.toString() : '1';
69
+ const env = { ...process.env, HARDWARE_CONCURRENCY: '1' };
70
+
71
+ // Set up file logging if logger is provided.
72
+ // Direct file redirection bypasses Node event loop - logs are written even if process hangs.
73
+ let logFd: number | undefined;
74
+ let logPath: string | undefined;
75
+ if (logger) {
76
+ logPath = `/tmp/${shmName}.log`;
77
+ logFd = openSync(logPath, 'w');
78
+ logger(`BB process logs redirected to: ${logPath}`);
79
+ }
64
80
 
65
81
  // Spawn bb process with shared memory mode
66
- const args = [bbBinaryPath, 'msgpack', 'run', '--input', `${shmName}.shm`, '--max-clients', clientCount.toString()];
67
- const bbProcess = spawn(findPackageRoot() + '/scripts/kill_wrapper.sh', args, {
68
- stdio: ['ignore', 'ignore', 'ignore'],
82
+ const args = [
83
+ 'msgpack',
84
+ 'run',
85
+ '--input',
86
+ `${shmName}.shm`,
87
+ '--max-clients',
88
+ clientCount.toString(),
89
+ '--request-ring-size',
90
+ `${1024 * 1024 * 2}`,
91
+ ];
92
+ const bbProcess = spawn(bbBinaryPath, args, {
93
+ stdio: ['ignore', logFd ?? 'ignore', logFd ?? 'ignore'],
69
94
  env,
70
95
  });
71
- // Disconnect from event loop so process can exit. The kill wrapper will reap bb once parent (node) dies.
72
- bbProcess.unref();
73
96
 
74
- // Capture stderr for error diagnostics
75
- // bbProcess.stderr?.on('data', (data: Buffer) => {
76
- // stderrOutput += data.toString();
77
- // });
97
+ // Disconnect from event loop so process can exit without waiting for bb
98
+ // The bb process has parent death monitoring (prctl on Linux, kqueue on macOS)
99
+ // so it will automatically exit when Node.js exits
100
+ bbProcess.unref();
78
101
 
79
102
  // Track if process has exited
80
103
  let processExited = false;
@@ -133,12 +156,19 @@ export class BarretenbergNativeShmSyncBackend implements IMsgpackBackendSync {
133
156
  throw new Error('Failed to create client connection');
134
157
  }
135
158
 
136
- return new BarretenbergNativeShmSyncBackend(bbProcess, client);
159
+ return new BarretenbergNativeShmSyncBackend(bbProcess, client, logFd);
137
160
  } finally {
138
- // If we failed to connect, ensure the process is killed
161
+ // If we failed to connect, ensure the process is killed and log file closed
139
162
  // kill() returns false if process already exited, but doesn't throw
140
163
  if (!client) {
141
164
  bbProcess.kill('SIGKILL');
165
+ if (logFd !== undefined) {
166
+ try {
167
+ closeSync(logFd);
168
+ } catch (e) {
169
+ // Ignore errors during cleanup
170
+ }
171
+ }
142
172
  }
143
173
  }
144
174
  }
@@ -160,6 +190,13 @@ export class BarretenbergNativeShmSyncBackend implements IMsgpackBackendSync {
160
190
  // Ignore errors during cleanup
161
191
  }
162
192
  }
193
+ if (this.logFd !== undefined) {
194
+ try {
195
+ closeSync(this.logFd);
196
+ } catch (e) {
197
+ // Ignore errors during cleanup
198
+ }
199
+ }
163
200
  }
164
201
 
165
202
  destroy(): void {