@aztec/bb.js 0.0.1-commit.d3ec352c → 0.0.1-commit.f295ac2

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 (186) 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 +48 -17
  10. package/dest/browser/barretenberg/backend.d.ts.map +1 -1
  11. package/dest/browser/barretenberg/backend.js +95 -6
  12. package/dest/browser/barretenberg/index.d.ts +2 -2
  13. package/dest/browser/barretenberg/index.d.ts.map +1 -1
  14. package/dest/browser/barretenberg/index.js +2 -2
  15. package/dest/browser/barretenberg_wasm/barretenberg_wasm_main/index.js +1 -1
  16. package/dest/browser/barretenberg_wasm/fetch_code/browser/barretenberg-threads.js +1 -1
  17. package/dest/browser/barretenberg_wasm/fetch_code/browser/barretenberg.js +1 -1
  18. package/dest/browser/bb_backends/index.d.ts +3 -1
  19. package/dest/browser/bb_backends/index.d.ts.map +1 -1
  20. package/dest/browser/cbind/generate.d.ts +5 -2
  21. package/dest/browser/cbind/generate.d.ts.map +1 -1
  22. package/dest/browser/cbind/generate.js +47 -25
  23. package/dest/browser/cbind/generated/api_types.d.ts +787 -1660
  24. package/dest/browser/cbind/generated/api_types.d.ts.map +1 -1
  25. package/dest/browser/cbind/generated/api_types.js +1535 -1535
  26. package/dest/browser/cbind/generated/async.d.ts +1 -1
  27. package/dest/browser/cbind/generated/async.d.ts.map +1 -1
  28. package/dest/browser/cbind/generated/async.js +6 -2
  29. package/dest/browser/cbind/generated/sync.d.ts +1 -1
  30. package/dest/browser/cbind/generated/sync.d.ts.map +1 -1
  31. package/dest/browser/cbind/generated/sync.js +6 -2
  32. package/dest/browser/cbind/naming.d.ts +16 -0
  33. package/dest/browser/cbind/naming.d.ts.map +1 -0
  34. package/dest/browser/cbind/naming.js +24 -0
  35. package/dest/browser/cbind/rust_codegen.d.ts +25 -0
  36. package/dest/browser/cbind/rust_codegen.d.ts.map +1 -0
  37. package/dest/browser/cbind/rust_codegen.js +416 -0
  38. package/dest/browser/cbind/schema_visitor.d.ts +47 -0
  39. package/dest/browser/cbind/schema_visitor.d.ts.map +1 -0
  40. package/dest/browser/cbind/schema_visitor.js +158 -0
  41. package/dest/browser/cbind/typescript_codegen.d.ts +30 -0
  42. package/dest/browser/cbind/typescript_codegen.d.ts.map +1 -0
  43. package/dest/browser/cbind/typescript_codegen.js +365 -0
  44. package/dest/browser/index.d.ts +2 -2
  45. package/dest/browser/index.d.ts.map +1 -1
  46. package/dest/browser/index.js +2 -2
  47. package/dest/node/barretenberg/backend.d.ts +48 -17
  48. package/dest/node/barretenberg/backend.d.ts.map +1 -1
  49. package/dest/node/barretenberg/backend.js +95 -6
  50. package/dest/node/barretenberg/backend.test.d.ts +2 -0
  51. package/dest/node/barretenberg/backend.test.d.ts.map +1 -0
  52. package/dest/node/barretenberg/backend.test.js +103 -0
  53. package/dest/node/barretenberg/index.d.ts +2 -2
  54. package/dest/node/barretenberg/index.d.ts.map +1 -1
  55. package/dest/node/barretenberg/index.js +2 -2
  56. package/dest/node/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  57. package/dest/node/barretenberg_wasm/barretenberg_wasm_main/index.js +1 -1
  58. package/dest/node/bb_backends/index.d.ts +3 -1
  59. package/dest/node/bb_backends/index.d.ts.map +1 -1
  60. package/dest/node/bb_backends/node/index.d.ts +1 -1
  61. package/dest/node/bb_backends/node/index.d.ts.map +1 -1
  62. package/dest/node/bb_backends/node/index.js +5 -5
  63. package/dest/node/bb_backends/node/native_shm.d.ts +3 -2
  64. package/dest/node/bb_backends/node/native_shm.d.ts.map +1 -1
  65. package/dest/node/bb_backends/node/native_shm.js +38 -20
  66. package/dest/node/bb_backends/node/native_shm_async.d.ts +2 -2
  67. package/dest/node/bb_backends/node/native_shm_async.d.ts.map +1 -1
  68. package/dest/node/bb_backends/node/native_shm_async.js +15 -20
  69. package/dest/node/bb_backends/node/native_socket.d.ts +1 -1
  70. package/dest/node/bb_backends/node/native_socket.d.ts.map +1 -1
  71. package/dest/node/bb_backends/node/native_socket.js +4 -4
  72. package/dest/node/bb_backends/node/platform.d.ts +1 -1
  73. package/dest/node/bb_backends/node/platform.d.ts.map +1 -1
  74. package/dest/node/bb_backends/node/platform.js +7 -2
  75. package/dest/node/cbind/generate.d.ts +5 -2
  76. package/dest/node/cbind/generate.d.ts.map +1 -1
  77. package/dest/node/cbind/generate.js +47 -25
  78. package/dest/node/cbind/generated/api_types.d.ts +787 -1660
  79. package/dest/node/cbind/generated/api_types.d.ts.map +1 -1
  80. package/dest/node/cbind/generated/api_types.js +1535 -1535
  81. package/dest/node/cbind/generated/async.d.ts +1 -1
  82. package/dest/node/cbind/generated/async.d.ts.map +1 -1
  83. package/dest/node/cbind/generated/async.js +6 -2
  84. package/dest/node/cbind/generated/sync.d.ts +1 -1
  85. package/dest/node/cbind/generated/sync.d.ts.map +1 -1
  86. package/dest/node/cbind/generated/sync.js +6 -2
  87. package/dest/node/cbind/naming.d.ts +16 -0
  88. package/dest/node/cbind/naming.d.ts.map +1 -0
  89. package/dest/node/cbind/naming.js +24 -0
  90. package/dest/node/cbind/rust_codegen.d.ts +25 -0
  91. package/dest/node/cbind/rust_codegen.d.ts.map +1 -0
  92. package/dest/node/cbind/rust_codegen.js +416 -0
  93. package/dest/node/cbind/schema_visitor.d.ts +47 -0
  94. package/dest/node/cbind/schema_visitor.d.ts.map +1 -0
  95. package/dest/node/cbind/schema_visitor.js +158 -0
  96. package/dest/node/cbind/typescript_codegen.d.ts +30 -0
  97. package/dest/node/cbind/typescript_codegen.d.ts.map +1 -0
  98. package/dest/node/cbind/typescript_codegen.js +365 -0
  99. package/dest/node/index.d.ts +2 -2
  100. package/dest/node/index.d.ts.map +1 -1
  101. package/dest/node/index.js +2 -2
  102. package/dest/node-cjs/barretenberg/backend.d.ts +48 -17
  103. package/dest/node-cjs/barretenberg/backend.d.ts.map +1 -1
  104. package/dest/node-cjs/barretenberg/backend.js +97 -6
  105. package/dest/node-cjs/barretenberg/backend.test.d.ts +2 -0
  106. package/dest/node-cjs/barretenberg/backend.test.d.ts.map +1 -0
  107. package/dest/node-cjs/barretenberg/backend.test.js +105 -0
  108. package/dest/node-cjs/barretenberg/index.d.ts +2 -2
  109. package/dest/node-cjs/barretenberg/index.d.ts.map +1 -1
  110. package/dest/node-cjs/barretenberg/index.js +4 -2
  111. package/dest/node-cjs/barretenberg_wasm/barretenberg-threads.wasm.gz +0 -0
  112. package/dest/node-cjs/barretenberg_wasm/barretenberg_wasm_main/index.js +1 -1
  113. package/dest/node-cjs/bb_backends/index.d.ts +3 -1
  114. package/dest/node-cjs/bb_backends/index.d.ts.map +1 -1
  115. package/dest/node-cjs/bb_backends/node/index.d.ts +1 -1
  116. package/dest/node-cjs/bb_backends/node/index.d.ts.map +1 -1
  117. package/dest/node-cjs/bb_backends/node/index.js +5 -5
  118. package/dest/node-cjs/bb_backends/node/native_shm.d.ts +3 -2
  119. package/dest/node-cjs/bb_backends/node/native_shm.d.ts.map +1 -1
  120. package/dest/node-cjs/bb_backends/node/native_shm.js +37 -19
  121. package/dest/node-cjs/bb_backends/node/native_shm_async.d.ts +2 -2
  122. package/dest/node-cjs/bb_backends/node/native_shm_async.d.ts.map +1 -1
  123. package/dest/node-cjs/bb_backends/node/native_shm_async.js +15 -20
  124. package/dest/node-cjs/bb_backends/node/native_socket.d.ts +1 -1
  125. package/dest/node-cjs/bb_backends/node/native_socket.d.ts.map +1 -1
  126. package/dest/node-cjs/bb_backends/node/native_socket.js +4 -4
  127. package/dest/node-cjs/bb_backends/node/platform.d.ts +1 -1
  128. package/dest/node-cjs/bb_backends/node/platform.d.ts.map +1 -1
  129. package/dest/node-cjs/bb_backends/node/platform.js +7 -2
  130. package/dest/node-cjs/cbind/generate.d.ts +5 -2
  131. package/dest/node-cjs/cbind/generate.d.ts.map +1 -1
  132. package/dest/node-cjs/cbind/generate.js +47 -25
  133. package/dest/node-cjs/cbind/generated/api_types.d.ts +787 -1660
  134. package/dest/node-cjs/cbind/generated/api_types.d.ts.map +1 -1
  135. package/dest/node-cjs/cbind/generated/api_types.js +1744 -1744
  136. package/dest/node-cjs/cbind/generated/async.d.ts +1 -1
  137. package/dest/node-cjs/cbind/generated/async.d.ts.map +1 -1
  138. package/dest/node-cjs/cbind/generated/async.js +6 -2
  139. package/dest/node-cjs/cbind/generated/sync.d.ts +1 -1
  140. package/dest/node-cjs/cbind/generated/sync.d.ts.map +1 -1
  141. package/dest/node-cjs/cbind/generated/sync.js +6 -2
  142. package/dest/node-cjs/cbind/naming.d.ts +16 -0
  143. package/dest/node-cjs/cbind/naming.d.ts.map +1 -0
  144. package/dest/node-cjs/cbind/naming.js +28 -0
  145. package/dest/node-cjs/cbind/rust_codegen.d.ts +25 -0
  146. package/dest/node-cjs/cbind/rust_codegen.d.ts.map +1 -0
  147. package/dest/node-cjs/cbind/rust_codegen.js +420 -0
  148. package/dest/node-cjs/cbind/schema_visitor.d.ts +47 -0
  149. package/dest/node-cjs/cbind/schema_visitor.d.ts.map +1 -0
  150. package/dest/node-cjs/cbind/schema_visitor.js +162 -0
  151. package/dest/node-cjs/cbind/typescript_codegen.d.ts +30 -0
  152. package/dest/node-cjs/cbind/typescript_codegen.d.ts.map +1 -0
  153. package/dest/node-cjs/cbind/typescript_codegen.js +369 -0
  154. package/dest/node-cjs/index.d.ts +2 -2
  155. package/dest/node-cjs/index.d.ts.map +1 -1
  156. package/dest/node-cjs/index.js +4 -2
  157. package/package.json +1 -1
  158. package/src/barretenberg/backend.test.ts +122 -0
  159. package/src/barretenberg/backend.ts +133 -19
  160. package/src/barretenberg/index.ts +9 -1
  161. package/src/barretenberg_wasm/barretenberg_wasm_main/index.ts +1 -1
  162. package/src/bb_backends/index.ts +3 -0
  163. package/src/bb_backends/node/index.ts +9 -4
  164. package/src/bb_backends/node/native_shm.ts +36 -18
  165. package/src/bb_backends/node/native_shm_async.ts +13 -18
  166. package/src/bb_backends/node/native_socket.ts +3 -4
  167. package/src/bb_backends/node/platform.ts +6 -1
  168. package/src/cbind/generate.ts +51 -32
  169. package/src/cbind/generated/api_types.ts +1655 -2756
  170. package/src/cbind/generated/async.ts +7 -2
  171. package/src/cbind/generated/sync.ts +7 -2
  172. package/src/cbind/naming.ts +27 -0
  173. package/src/cbind/rust_codegen.ts +459 -0
  174. package/src/cbind/schema_visitor.ts +219 -0
  175. package/src/cbind/typescript_codegen.ts +419 -0
  176. package/src/index.ts +4 -0
  177. package/dest/browser/cbind/schema_compiler.d.ts +0 -68
  178. package/dest/browser/cbind/schema_compiler.d.ts.map +0 -1
  179. package/dest/browser/cbind/schema_compiler.js +0 -600
  180. package/dest/node/cbind/schema_compiler.d.ts +0 -68
  181. package/dest/node/cbind/schema_compiler.d.ts.map +0 -1
  182. package/dest/node/cbind/schema_compiler.js +0 -600
  183. package/dest/node-cjs/cbind/schema_compiler.d.ts +0 -68
  184. package/dest/node-cjs/cbind/schema_compiler.d.ts.map +0 -1
  185. package/dest/node-cjs/cbind/schema_compiler.js +0 -607
  186. package/src/cbind/schema_compiler.ts +0 -745
@@ -10,29 +10,46 @@ export class AztecClientBackendError extends Error {
10
10
  }
11
11
  }
12
12
 
13
+ /**
14
+ * Target verification environment for proof generation.
15
+ * This determines the hash function used and whether zero-knowledge is enabled.
16
+ */
17
+ export type VerifierTarget =
18
+ | 'evm' // Ethereum/Solidity verification (keccak, ZK enabled)
19
+ | 'evm-no-zk' // Ethereum/Solidity without zero-knowledge
20
+ | 'noir-recursive' // Recursive verification in Noir circuits (poseidon2, ZK enabled)
21
+ | 'noir-recursive-no-zk' // Recursive verification without ZK
22
+ | 'noir-rollup' // Rollup circuits with IPA accumulation (poseidon2, ZK enabled)
23
+ | 'noir-rollup-no-zk' // Rollup circuits without ZK
24
+ | 'starknet' // Starknet verification via Garaga (ZK enabled)
25
+ | 'starknet-no-zk'; // Starknet without zero-knowledge
26
+
13
27
  /**
14
28
  * Options for the UltraHonkBackend.
15
29
  */
16
30
  export type UltraHonkBackendOptions = {
17
- /** Selecting this option will use the keccak hash function instead of poseidon
18
- * when generating challenges in the proof.
19
- * Use this when you want to verify the created proof on an EVM chain.
31
+ /**
32
+ * Target verification environment. Determines hash function and ZK settings.
33
+ * This is the recommended way to configure proof generation.
34
+ *
35
+ * @example
36
+ * // For EVM/Solidity verification
37
+ * backend.generateProof(witness, { verifierTarget: 'evm' });
38
+ *
39
+ * // For recursive verification in Noir
40
+ * backend.generateProof(witness, { verifierTarget: 'noir-recursive' });
20
41
  */
42
+ verifierTarget?: VerifierTarget;
43
+
44
+ // Legacy options - prefer using verifierTarget instead
45
+
46
+ /** @deprecated Use verifierTarget: 'evm-no-zk' instead */
21
47
  keccak?: boolean;
22
- /** Selecting this option will use the keccak hash function instead of poseidon
23
- * when generating challenges in the proof.
24
- * Use this when you want to verify the created proof on an EVM chain.
25
- */
48
+ /** @deprecated Use verifierTarget: 'evm' instead */
26
49
  keccakZK?: boolean;
27
- /** Selecting this option will use the poseidon/stark252 hash function instead of poseidon
28
- * when generating challenges in the proof.
29
- * Use this when you want to verify the created proof on an Starknet chain with Garaga.
30
- */
50
+ /** @deprecated Use verifierTarget: 'starknet-no-zk' instead */
31
51
  starknet?: boolean;
32
- /** Selecting this option will use the poseidon/stark252 hash function instead of poseidon
33
- * when generating challenges in the proof.
34
- * Use this when you want to verify the created proof on an Starknet chain with Garaga.
35
- */
52
+ /** @deprecated Use verifierTarget: 'starknet' instead */
36
53
  starknetZK?: boolean;
37
54
  };
38
55
 
@@ -42,6 +59,67 @@ function getProofSettingsFromOptions(options?: UltraHonkBackendOptions): {
42
59
  disableZk: boolean;
43
60
  optimizedSolidityVerifier: boolean;
44
61
  } {
62
+ // Check for conflicting options - verifierTarget should not be combined with legacy options
63
+ if (options?.verifierTarget) {
64
+ const legacyOptions = [options.keccak, options.keccakZK, options.starknet, options.starknetZK].filter(Boolean);
65
+ if (legacyOptions.length > 0) {
66
+ throw new Error(
67
+ 'Cannot use verifierTarget with legacy options (keccak, keccakZK, starknet, starknetZK). ' +
68
+ 'Use verifierTarget alone.',
69
+ );
70
+ }
71
+
72
+ switch (options.verifierTarget) {
73
+ case 'evm':
74
+ return { ipaAccumulation: false, oracleHashType: 'keccak', disableZk: false, optimizedSolidityVerifier: false };
75
+ case 'evm-no-zk':
76
+ return { ipaAccumulation: false, oracleHashType: 'keccak', disableZk: true, optimizedSolidityVerifier: false };
77
+ case 'noir-recursive':
78
+ return {
79
+ ipaAccumulation: false,
80
+ oracleHashType: 'poseidon2',
81
+ disableZk: false,
82
+ optimizedSolidityVerifier: false,
83
+ };
84
+ case 'noir-recursive-no-zk':
85
+ return {
86
+ ipaAccumulation: false,
87
+ oracleHashType: 'poseidon2',
88
+ disableZk: true,
89
+ optimizedSolidityVerifier: false,
90
+ };
91
+ case 'noir-rollup':
92
+ return {
93
+ ipaAccumulation: true,
94
+ oracleHashType: 'poseidon2',
95
+ disableZk: false,
96
+ optimizedSolidityVerifier: false,
97
+ };
98
+ case 'noir-rollup-no-zk':
99
+ return {
100
+ ipaAccumulation: true,
101
+ oracleHashType: 'poseidon2',
102
+ disableZk: true,
103
+ optimizedSolidityVerifier: false,
104
+ };
105
+ case 'starknet':
106
+ return {
107
+ ipaAccumulation: false,
108
+ oracleHashType: 'starknet',
109
+ disableZk: false,
110
+ optimizedSolidityVerifier: false,
111
+ };
112
+ case 'starknet-no-zk':
113
+ return {
114
+ ipaAccumulation: false,
115
+ oracleHashType: 'starknet',
116
+ disableZk: true,
117
+ optimizedSolidityVerifier: false,
118
+ };
119
+ }
120
+ }
121
+
122
+ // Legacy options support (deprecated)
45
123
  return {
46
124
  ipaAccumulation: false,
47
125
  oracleHashType:
@@ -50,7 +128,6 @@ function getProofSettingsFromOptions(options?: UltraHonkBackendOptions): {
50
128
  : options?.starknet || options?.starknetZK
51
129
  ? 'starknet'
52
130
  : 'poseidon2',
53
- // TODO no current way to target non-zk poseidon2 hash
54
131
  disableZk: options?.keccak || options?.starknet ? true : false,
55
132
  optimizedSolidityVerifier: false,
56
133
  };
@@ -162,6 +239,7 @@ export class UltraHonkBackend {
162
239
  _proof: Uint8Array,
163
240
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
164
241
  _numOfPublicInputs: number,
242
+ options?: UltraHonkBackendOptions,
165
243
  ): Promise<{ proofAsFields: string[]; vkAsFields: string[]; vkHash: string }> {
166
244
  // TODO(https://github.com/noir-lang/noir/issues/5661): This needs to be updated to handle recursive aggregation.
167
245
  // There is still a proofAsFields method but we could consider getting rid of it as the proof itself
@@ -171,14 +249,12 @@ export class UltraHonkBackend {
171
249
  // const proof = reconstructProofWithPublicInputs(proofData);
172
250
  // const proofAsFields = (await this.api.acirProofAsFieldsUltraHonk(proof)).slice(numOfPublicInputs);
173
251
 
174
- // TODO: perhaps we should put this in the init function. Need to benchmark
175
- // TODO how long it takes.
176
252
  const vkResult = await this.api.circuitComputeVk({
177
253
  circuit: {
178
254
  name: 'circuit',
179
255
  bytecode: this.acirUncompressedBytecode,
180
256
  },
181
- settings: getProofSettingsFromOptions({}),
257
+ settings: getProofSettingsFromOptions(options),
182
258
  });
183
259
 
184
260
  // Convert VK bytes to field elements (32-byte chunks)
@@ -310,3 +386,41 @@ function base64Decode(input: string): Uint8Array {
310
386
  throw new Error('atob is not available. Node.js 18+ or browser required.');
311
387
  }
312
388
  }
389
+
390
+ /**
391
+ * Convert a field element (32-byte Uint8Array) to a string.
392
+ *
393
+ * @param field - A 32-byte field element
394
+ * @param radix - The radix for string conversion (2-36), defaults to 10 (decimal)
395
+ * @returns The field value as a string in the specified radix
396
+ *
397
+ * @example
398
+ * const decimal = fieldToString(field); // "12345678"
399
+ * const hex = fieldToString(field, 16); // "bc614e"
400
+ */
401
+ export function fieldToString(field: Uint8Array, radix: number = 10): string {
402
+ let result = 0n;
403
+ for (const byte of field) {
404
+ result <<= 8n;
405
+ result += BigInt(byte);
406
+ }
407
+ return result.toString(radix);
408
+ }
409
+
410
+ /**
411
+ * Convert an array of field elements to an array of strings.
412
+ * Useful for passing VK fields to Noir circuits.
413
+ *
414
+ * @param fields - Array of 32-byte field elements
415
+ * @param radix - The radix for string conversion (2-36), defaults to 10 (decimal)
416
+ * @returns Array of strings in the specified radix
417
+ *
418
+ * @example
419
+ * const vkAsFields = await barretenbergAPI.vkAsFields({ verificationKey: vk });
420
+ * const vkDecimalStrings = fieldsToStrings(vkAsFields.fields); // ["12345678", "87654321", ...]
421
+ * const vkHexStrings = fieldsToStrings(vkAsFields.fields, 16); // ["bc614e", "5397fb1", ...]
422
+ */
423
+ export function fieldsToStrings(fields: Uint8Array[], radix: number = 10): string[] {
424
+ return fields.map(field => fieldToString(field, radix));
425
+ }
426
+
@@ -5,7 +5,15 @@ import { IMsgpackBackendSync, IMsgpackBackendAsync } from '../bb_backends/interf
5
5
  import { BackendOptions, BackendType } from '../bb_backends/index.js';
6
6
  import { createAsyncBackend, createSyncBackend } from '../bb_backends/node/index.js';
7
7
 
8
- export { UltraHonkBackend, UltraHonkVerifierBackend, AztecClientBackend } from './backend.js';
8
+ export {
9
+ UltraHonkBackend,
10
+ UltraHonkVerifierBackend,
11
+ AztecClientBackend,
12
+ fieldToString,
13
+ fieldsToStrings,
14
+ type UltraHonkBackendOptions,
15
+ type VerifierTarget,
16
+ } from './backend.js';
9
17
  export * from '../bb_backends/index.js';
10
18
 
11
19
  export type CircuitOptions = {
@@ -35,7 +35,7 @@ export class BarretenbergWasmMain extends BarretenbergWasmBase {
35
35
  module: WebAssembly.Module,
36
36
  threads = Math.min(getNumCpu(), BarretenbergWasmMain.MAX_THREADS),
37
37
  logger?: (msg: string) => void,
38
- initial = 33,
38
+ initial = 35,
39
39
  maximum = this.getDefaultMaximumMemoryPages(),
40
40
  ) {
41
41
  // Track whether a custom logger was provided so workers know whether to postMessage logs
@@ -28,6 +28,9 @@ 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 Custom path to bb NAPI module for native backend (overrides automatic detection) */
32
+ napiPath?: string;
33
+
31
34
  /**
32
35
  * @description Logging function
33
36
  * Warning: Attaching a logger can prevent nodejs from exiting without explicitly destroying the backend.
@@ -35,12 +35,17 @@ export async function createAsyncBackend(
35
35
  if (!bbPath) {
36
36
  throw new Error('Native backend requires bb binary.');
37
37
  }
38
- const napiPath = findNapiBinary();
38
+ const napiPath = findNapiBinary(options.napiPath);
39
39
  if (!napiPath) {
40
40
  throw new Error('Native async backend requires napi client stub.');
41
41
  }
42
42
  logger(`Using native shared memory async backend: ${bbPath}`);
43
- const asyncBackend = await BarretenbergNativeShmAsyncBackend.new(bbPath, options.threads, options.logger);
43
+ const asyncBackend = await BarretenbergNativeShmAsyncBackend.new(
44
+ bbPath,
45
+ napiPath,
46
+ options.threads,
47
+ options.logger,
48
+ );
44
49
  return new Barretenberg(asyncBackend, options);
45
50
  }
46
51
 
@@ -82,12 +87,12 @@ export async function createSyncBackend(
82
87
  if (!bbPath) {
83
88
  throw new Error('Native backend requires bb binary.');
84
89
  }
85
- const napiPath = findNapiBinary();
90
+ const napiPath = findNapiBinary(options.napiPath);
86
91
  if (!napiPath) {
87
92
  throw new Error('Native sync backend requires napi client stub.');
88
93
  }
89
94
  logger(`Using native shared memory backend: ${bbPath}`);
90
- const shm = await BarretenbergNativeShmSyncBackend.new(bbPath, options.threads, options.logger);
95
+ const shm = await BarretenbergNativeShmSyncBackend.new(bbPath, napiPath, options.threads, options.logger);
91
96
  return new BarretenbergSync(shm);
92
97
  }
93
98
 
@@ -1,24 +1,9 @@
1
1
  import { createRequire } from 'module';
2
2
  import { spawn, ChildProcess } from 'child_process';
3
- import { openSync, closeSync } from 'fs';
3
+ import { openSync, closeSync, unlinkSync } from 'fs';
4
4
  import { IMsgpackBackendSync } from '../interface.js';
5
5
  import { findNapiBinary, findPackageRoot } from './platform.js';
6
6
 
7
- // Import the NAPI module
8
- // The addon is built to the nodejs_module directory
9
- const addonPath = findNapiBinary();
10
- // Try loading, but don't throw if it doesn't exist (will be caught in constructor)
11
- let addon: any = null;
12
- try {
13
- if (addonPath) {
14
- const require = createRequire(findPackageRoot()!);
15
- addon = require(addonPath);
16
- }
17
- } catch (err) {
18
- // Addon not built yet or not available
19
- addon = null;
20
- }
21
-
22
7
  let instanceCounter = 0;
23
8
 
24
9
  /**
@@ -46,15 +31,26 @@ export class BarretenbergNativeShmSyncBackend implements IMsgpackBackendSync {
46
31
  /**
47
32
  * Create and initialize a shared memory backend.
48
33
  * @param bbBinaryPath Path to bb binary
34
+ * @param napiPath Path to NAPI binary
49
35
  * @param threads Optional number of threads
50
36
  */
51
37
  static async new(
52
38
  bbBinaryPath: string,
39
+ napiPath: string,
53
40
  threads?: number,
54
41
  logger?: (msg: string) => void,
55
42
  ): Promise<BarretenbergNativeShmSyncBackend> {
56
- if (!addon || !addon.MsgpackClient) {
57
- throw new Error('Shared memory NAPI not available.');
43
+ // Import the NAPI module
44
+ // The addon is built to the nodejs_module directory
45
+ const addonPath = findNapiBinary(napiPath);
46
+ // Try loading
47
+ let addon: any = null;
48
+ try {
49
+ const require = createRequire(findPackageRoot()!);
50
+ addon = require(addonPath!);
51
+ } catch (err) {
52
+ // Addon not built yet or not available
53
+ throw new Error('Shared memory sync NAPI not available.');
58
54
  }
59
55
 
60
56
  // Create a unique shared memory name
@@ -74,6 +70,28 @@ export class BarretenbergNativeShmSyncBackend implements IMsgpackBackendSync {
74
70
  logger(`BB process logs redirected to: ${logPath}`);
75
71
  }
76
72
 
73
+ // Clean up any stale shared memory files from previous runs
74
+ // This handles the case where a previous process crashed without cleanup
75
+ const shmRequestPath = `/dev/shm/${shmName}_request`;
76
+ const shmResponsePath = `/dev/shm/${shmName}_response`;
77
+ try {
78
+ unlinkSync(shmRequestPath);
79
+ } catch (err) {
80
+ const isNotFound = err && typeof err === 'object' && 'code' in err && err.code === 'ENOENT';
81
+ if (!isNotFound) {
82
+ throw new Error(`Failed to clean up stale shared memory file ${shmRequestPath}: ${err}`);
83
+ }
84
+ }
85
+
86
+ try {
87
+ unlinkSync(shmResponsePath);
88
+ } catch (err) {
89
+ const isNotFound = err && typeof err === 'object' && 'code' in err && err.code === 'ENOENT';
90
+ if (!isNotFound) {
91
+ throw new Error(`Failed to clean up stale shared memory file ${shmResponsePath}: ${err}`);
92
+ }
93
+ }
94
+
77
95
  // Spawn bb process with shared memory mode (SPSC-only, no max-clients needed)
78
96
  const args = ['msgpack', 'run', '--input', `${shmName}.shm`, '--request-ring-size', `${1024 * 1024 * 4}`];
79
97
  const bbProcess = spawn(bbBinaryPath, args, {
@@ -4,21 +4,6 @@ import { openSync, closeSync } from 'fs';
4
4
  import { IMsgpackBackendAsync } from '../interface.js';
5
5
  import { findNapiBinary, findPackageRoot } from './platform.js';
6
6
 
7
- // Import the NAPI module
8
- // The addon is built to the nodejs_module directory
9
- const addonPath = findNapiBinary();
10
- // Try loading, but don't throw if it doesn't exist (will be caught in constructor)
11
- let addon: any = null;
12
- try {
13
- if (addonPath) {
14
- const require = createRequire(findPackageRoot()!);
15
- addon = require(addonPath);
16
- }
17
- } catch (err) {
18
- // Addon not built yet or not available
19
- addon = null;
20
- }
21
-
22
7
  let instanceCounter = 0;
23
8
 
24
9
  /**
@@ -86,18 +71,28 @@ export class BarretenbergNativeShmAsyncBackend implements IMsgpackBackendAsync {
86
71
  */
87
72
  static async new(
88
73
  bbBinaryPath: string,
74
+ napiPath: string,
89
75
  threads?: number,
90
76
  logger?: (msg: string) => void,
91
77
  ): Promise<BarretenbergNativeShmAsyncBackend> {
92
- if (!addon || !addon.MsgpackClientAsync) {
78
+ // Import the NAPI module
79
+ // The addon is built to the nodejs_module directory
80
+ const addonPath = findNapiBinary(napiPath);
81
+ // Try loading
82
+ let addon: any = null;
83
+ try {
84
+ const require = createRequire(findPackageRoot()!);
85
+ addon = require(addonPath!);
86
+ } catch (err) {
87
+ // Addon not built yet or not available
93
88
  throw new Error('Shared memory async NAPI not available.');
94
89
  }
95
90
 
96
91
  // Create a unique shared memory name
97
92
  const shmName = `bb-async-${process.pid}-${instanceCounter++}`;
98
93
 
99
- // If threads not set use num cpu cores, max 32 (same as socket backend)
100
- const hwc = threads ? threads.toString() : '1';
94
+ // If threads not set use num cpu cores, max 16 (same as socket backend)
95
+ const hwc = threads ? threads.toString() : '16';
101
96
  const env = { ...process.env, HARDWARE_CONCURRENCY: hwc };
102
97
 
103
98
  // Set up file logging if logger is provided
@@ -4,7 +4,6 @@ import * as fs from 'fs';
4
4
  import * as os from 'os';
5
5
  import * as path from 'path';
6
6
  import { IMsgpackBackendAsync } from '../interface.js';
7
- import { findPackageRoot } from './platform.js';
8
7
  import readline from 'readline';
9
8
 
10
9
  /**
@@ -58,9 +57,9 @@ export class BarretenbergNativeSocketAsyncBackend implements IMsgpackBackendAsyn
58
57
  connectionReject = reject;
59
58
  });
60
59
 
61
- // If threads not set use num cpu cores, max 32.
62
- const hwc = threads ? threads.toString() : Math.min(32, os.cpus.length).toString();
63
- const env = { ...process.env, HARDWARE_CONCURRENCY: '1' };
60
+ // If threads not set use num cpu cores, max 16.
61
+ const hwc = threads ? threads.toString() : Math.min(16, os.cpus().length).toString();
62
+ const env = { ...process.env, HARDWARE_CONCURRENCY: hwc };
64
63
 
65
64
  // Spawn bb process - it will create the socket server
66
65
  const args = ['msgpack', 'run', '--input', this.socketPath];
@@ -24,7 +24,12 @@ export function findPackageRoot(): string | null {
24
24
  while (currentDir !== root) {
25
25
  const packageJsonPath = path.join(currentDir, 'package.json');
26
26
  if (fs.existsSync(packageJsonPath)) {
27
- return currentDir;
27
+ // Check if this is the actual package root by verifying it has a 'build' directory
28
+ // This ensures we skip intermediate package.json files (e.g., in dest/node-cjs/)
29
+ const buildDir = path.join(currentDir, 'build');
30
+ if (fs.existsSync(buildDir)) {
31
+ return currentDir;
32
+ }
28
33
  }
29
34
  currentDir = path.dirname(currentDir);
30
35
  }
@@ -1,5 +1,8 @@
1
1
  /**
2
- * Generate TypeScript bindings from msgpack schema
2
+ * Multi-language code generation from BB msgpack schema
3
+ *
4
+ * Architecture:
5
+ * Raw Schema → SchemaVisitor → CompiledSchema IR → Language Codegens → Files
3
6
  */
4
7
 
5
8
  import { writeFileSync, mkdirSync } from 'fs';
@@ -8,36 +11,42 @@ import { exec } from 'child_process';
8
11
  import { promisify } from 'util';
9
12
  import { fileURLToPath } from 'url';
10
13
  import { unpack } from 'msgpackr';
11
- import {
12
- createSharedTypesCompiler,
13
- createSyncApiCompiler,
14
- createAsyncApiCompiler,
15
- type SchemaCompiler,
16
- } from './schema_compiler.js';
14
+ import { SchemaVisitor, type CompiledSchema } from './schema_visitor.js';
15
+ import { TypeScriptCodegen } from './typescript_codegen.js';
16
+ import { RustCodegen } from './rust_codegen.js';
17
17
 
18
18
  const execAsync = promisify(exec);
19
19
 
20
- interface GeneratorConfig {
20
+ // Language generators - all use the same CompiledSchema IR
21
+ interface LanguageGenerator {
21
22
  name: string;
22
- outputFile: string;
23
- createCompiler: () => SchemaCompiler;
23
+ enabled: boolean;
24
+ generate: (compiled: CompiledSchema) => Array<{ path: string; content: string }>;
24
25
  }
25
26
 
26
- const GENERATORS: GeneratorConfig[] = [
27
+ const LANGUAGE_GENERATORS: LanguageGenerator[] = [
27
28
  {
28
- name: 'Shared types',
29
- outputFile: 'generated/api_types.ts',
30
- createCompiler: createSharedTypesCompiler,
29
+ name: 'TypeScript',
30
+ enabled: true,
31
+ generate: (compiled) => {
32
+ const tsGen = new TypeScriptCodegen();
33
+ return [
34
+ { path: 'generated/api_types.ts', content: tsGen.generateTypes(compiled) },
35
+ { path: 'generated/sync.ts', content: tsGen.generateSyncApi(compiled) },
36
+ { path: 'generated/async.ts', content: tsGen.generateAsyncApi(compiled) },
37
+ ];
38
+ },
31
39
  },
32
40
  {
33
- name: 'Sync API',
34
- outputFile: 'generated/sync.ts',
35
- createCompiler: createSyncApiCompiler,
36
- },
37
- {
38
- name: 'Async API',
39
- outputFile: 'generated/async.ts',
40
- createCompiler: createAsyncApiCompiler,
41
+ name: 'Rust',
42
+ enabled: true,
43
+ generate: (compiled) => {
44
+ const rustGen = new RustCodegen();
45
+ return [
46
+ { path: '../../../rust/barretenberg-rs/src/generated_types.rs', content: rustGen.generateTypes(compiled) },
47
+ { path: '../../../rust/barretenberg-rs/src/api.rs', content: rustGen.generateApi(compiled) },
48
+ ];
49
+ },
41
50
  },
42
51
  ];
43
52
 
@@ -56,29 +65,39 @@ async function generate() {
56
65
  throw new Error('Invalid schema: missing commands or responses');
57
66
  }
58
67
 
59
- console.log('Generating TypeScript bindings...\n');
68
+ // Compile schema once using visitor pattern
69
+ console.log('Compiling schema...');
70
+ const visitor = new SchemaVisitor();
71
+ const compiled = visitor.visit(schema.commands, schema.responses);
72
+
73
+ console.log(`Found ${compiled.commands.length} commands, ${compiled.structs.size} structs\n`);
60
74
 
61
75
  // Ensure output directory exists
62
76
  const outputDir = join(__dirname, 'generated');
63
77
  mkdirSync(outputDir, { recursive: true });
64
78
 
65
- // Generate each output file
66
- for (const config of GENERATORS) {
67
- const compiler = config.createCompiler();
68
- compiler.processApiSchema(schema.commands, schema.responses);
79
+ // Generate all language bindings from compiled IR
80
+ for (const generator of LANGUAGE_GENERATORS) {
81
+ if (!generator.enabled) {
82
+ console.log(`⊘ ${generator.name}: disabled`);
83
+ continue;
84
+ }
69
85
 
70
- const outputPath = join(__dirname, config.outputFile);
71
- const content = compiler.compile();
72
- writeFileSync(outputPath, content);
86
+ const files = generator.generate(compiled);
73
87
 
74
- console.log(`✓ ${config.name}: ${outputPath}`);
88
+ for (const file of files) {
89
+ const outputPath = join(__dirname, file.path);
90
+ mkdirSync(dirname(outputPath), { recursive: true });
91
+ writeFileSync(outputPath, file.content);
92
+ console.log(`✓ ${generator.name}: ${outputPath}`);
93
+ }
75
94
  }
76
95
 
77
96
  // Generate curve constants
78
97
  console.log('\nGenerating curve constants...');
79
98
  await generateCurveConstants(bbBuildPath, outputDir);
80
99
 
81
- console.log('\nGeneration complete!');
100
+ console.log('\n✨ Generation complete! Clean, maintainable, multi-language architecture.');
82
101
  }
83
102
 
84
103
  async function generateCurveConstants(bbBuildPath: string, outputDir: string) {