@aztec/bb-prover 0.0.1-commit.e558bd1c → 0.0.1-commit.e57c76e

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 (62) hide show
  1. package/dest/avm_proving_tests/avm_proving_tester.d.ts +13 -8
  2. package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
  3. package/dest/avm_proving_tests/avm_proving_tester.js +152 -110
  4. package/dest/bb/bb_js_backend.d.ts +196 -0
  5. package/dest/bb/bb_js_backend.d.ts.map +1 -0
  6. package/dest/bb/bb_js_backend.js +379 -0
  7. package/dest/bb/bb_js_debug.d.ts +52 -0
  8. package/dest/bb/bb_js_debug.d.ts.map +1 -0
  9. package/dest/bb/bb_js_debug.js +176 -0
  10. package/dest/bb/file_names.d.ts +4 -0
  11. package/dest/bb/file_names.d.ts.map +1 -0
  12. package/dest/bb/file_names.js +5 -0
  13. package/dest/config.d.ts +17 -1
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/index.d.ts +3 -2
  16. package/dest/index.d.ts.map +1 -1
  17. package/dest/index.js +2 -1
  18. package/dest/instrumentation.d.ts +1 -1
  19. package/dest/instrumentation.d.ts.map +1 -1
  20. package/dest/instrumentation.js +12 -4
  21. package/dest/prover/client/bb_private_kernel_prover.d.ts +10 -2
  22. package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
  23. package/dest/prover/client/bb_private_kernel_prover.js +39 -5
  24. package/dest/prover/proof_utils.d.ts +11 -1
  25. package/dest/prover/proof_utils.d.ts.map +1 -1
  26. package/dest/prover/proof_utils.js +24 -1
  27. package/dest/prover/server/bb_prover.d.ts +4 -5
  28. package/dest/prover/server/bb_prover.d.ts.map +1 -1
  29. package/dest/prover/server/bb_prover.js +207 -78
  30. package/dest/verification_key/verification_key_data.js +1 -1
  31. package/dest/verifier/batch_chonk_verifier.d.ts +56 -0
  32. package/dest/verifier/batch_chonk_verifier.d.ts.map +1 -0
  33. package/dest/verifier/batch_chonk_verifier.js +384 -0
  34. package/dest/verifier/bb_verifier.d.ts +4 -1
  35. package/dest/verifier/bb_verifier.d.ts.map +1 -1
  36. package/dest/verifier/bb_verifier.js +134 -45
  37. package/dest/verifier/index.d.ts +2 -1
  38. package/dest/verifier/index.d.ts.map +1 -1
  39. package/dest/verifier/index.js +1 -0
  40. package/dest/verifier/queued_chonk_verifier.d.ts +2 -3
  41. package/dest/verifier/queued_chonk_verifier.d.ts.map +1 -1
  42. package/dest/verifier/queued_chonk_verifier.js +6 -5
  43. package/package.json +19 -17
  44. package/src/avm_proving_tests/avm_proving_tester.ts +53 -126
  45. package/src/bb/bb_js_backend.ts +435 -0
  46. package/src/bb/bb_js_debug.ts +227 -0
  47. package/src/bb/file_names.ts +6 -0
  48. package/src/config.ts +16 -0
  49. package/src/index.ts +2 -1
  50. package/src/instrumentation.ts +12 -4
  51. package/src/prover/client/bb_private_kernel_prover.ts +116 -4
  52. package/src/prover/proof_utils.ts +41 -1
  53. package/src/prover/server/bb_prover.ts +132 -137
  54. package/src/verification_key/verification_key_data.ts +1 -1
  55. package/src/verifier/batch_chonk_verifier.ts +415 -0
  56. package/src/verifier/bb_verifier.ts +66 -76
  57. package/src/verifier/index.ts +1 -0
  58. package/src/verifier/queued_chonk_verifier.ts +6 -7
  59. package/dest/bb/execute.d.ts +0 -107
  60. package/dest/bb/execute.d.ts.map +0 -1
  61. package/dest/bb/execute.js +0 -647
  62. package/src/bb/execute.ts +0 -678
@@ -0,0 +1,379 @@
1
+ import { BackendType, Barretenberg } from '@aztec/bb.js';
2
+ import { FifoMemoryQueue } from '@aztec/foundation/queue';
3
+ import { Timer } from '@aztec/foundation/timer';
4
+ /**
5
+ * Maps UltraHonkFlavor to the bb.js ProofSystemSettings.
6
+ * All server-side proofs use disableZk: true.
7
+ */ function getProofSettings(flavor) {
8
+ const base = {
9
+ disableZk: true,
10
+ optimizedSolidityVerifier: false
11
+ };
12
+ switch(flavor){
13
+ case 'ultra_honk':
14
+ return {
15
+ ...base,
16
+ oracleHashType: 'poseidon2',
17
+ ipaAccumulation: false
18
+ };
19
+ case 'ultra_keccak_honk':
20
+ return {
21
+ ...base,
22
+ oracleHashType: 'keccak',
23
+ ipaAccumulation: false
24
+ };
25
+ case 'ultra_starknet_honk':
26
+ return {
27
+ ...base,
28
+ oracleHashType: 'starknet',
29
+ ipaAccumulation: false
30
+ };
31
+ case 'ultra_rollup_honk':
32
+ return {
33
+ ...base,
34
+ oracleHashType: 'poseidon2',
35
+ ipaAccumulation: true
36
+ };
37
+ }
38
+ }
39
+ /**
40
+ * Thin wrapper around a single Barretenberg instance.
41
+ * Each instance spawns its own bb process via the NativeUnixSocket backend.
42
+ */ export class BBJsInstance {
43
+ api;
44
+ constructor(api){
45
+ this.api = api;
46
+ }
47
+ /** Creates a new Barretenberg instance connected to a fresh bb process. */ static async create(bbPath, logger, threads) {
48
+ const options = {
49
+ bbPath,
50
+ backend: BackendType.NativeUnixSocket,
51
+ logger
52
+ };
53
+ if (threads !== undefined) {
54
+ options.threads = threads;
55
+ }
56
+ const api = await Barretenberg.new(options);
57
+ return new BBJsInstance(api);
58
+ }
59
+ /**
60
+ * Generate an UltraHonk proof for a circuit.
61
+ * @param circuitName - Identifier for the circuit (used by bb internally).
62
+ * @param bytecode - Uncompressed ACIR bytecode.
63
+ * @param verificationKey - The circuit's verification key bytes.
64
+ * @param witness - Uncompressed witness bytes.
65
+ * @param flavor - The UltraHonk flavor to use.
66
+ */ async generateProof(circuitName, bytecode, verificationKey, witness, flavor) {
67
+ const timer = new Timer();
68
+ const result = await this.api.circuitProve({
69
+ circuit: {
70
+ name: circuitName,
71
+ bytecode,
72
+ verificationKey
73
+ },
74
+ witness,
75
+ settings: getProofSettings(flavor)
76
+ });
77
+ return {
78
+ proofFields: result.proof,
79
+ publicInputFields: result.publicInputs,
80
+ durationMs: timer.ms()
81
+ };
82
+ }
83
+ /**
84
+ * Verify an UltraHonk proof.
85
+ * @param proofFields - Proof fields as 32-byte Uint8Arrays.
86
+ * @param verificationKey - The VK bytes.
87
+ * @param publicInputFields - Public input fields as 32-byte Uint8Arrays.
88
+ * @param flavor - The UltraHonk flavor.
89
+ * @returns Whether the proof is valid.
90
+ */ async verifyProof(proofFields, verificationKey, publicInputFields, flavor) {
91
+ const timer = new Timer();
92
+ const result = await this.api.circuitVerify({
93
+ verificationKey,
94
+ publicInputs: publicInputFields,
95
+ proof: proofFields,
96
+ settings: getProofSettings(flavor)
97
+ });
98
+ return {
99
+ verified: result.verified,
100
+ durationMs: timer.ms()
101
+ };
102
+ }
103
+ /**
104
+ * Compute circuit gate count / circuit size.
105
+ * @param circuitName - Identifier for the circuit.
106
+ * @param bytecode - Uncompressed ACIR bytecode.
107
+ * @param flavor - 'mega_honk' for chonk circuits, or an UltraHonk flavor.
108
+ * @returns The dyadic circuit size (next power of 2 of gate count).
109
+ */ async computeGateCount(circuitName, bytecode, flavor) {
110
+ const timer = new Timer();
111
+ if (flavor === 'mega_honk') {
112
+ const result = await this.api.chonkStats({
113
+ circuit: {
114
+ name: circuitName,
115
+ bytecode
116
+ },
117
+ includeGatesPerOpcode: false
118
+ });
119
+ return {
120
+ circuitSize: result.circuitSize,
121
+ durationMs: timer.ms()
122
+ };
123
+ }
124
+ const result = await this.api.circuitStats({
125
+ circuit: {
126
+ name: circuitName,
127
+ bytecode,
128
+ verificationKey: new Uint8Array(0)
129
+ },
130
+ includeGatesPerOpcode: false,
131
+ settings: getProofSettings(flavor)
132
+ });
133
+ return {
134
+ circuitSize: result.numGatesDyadic,
135
+ durationMs: timer.ms()
136
+ };
137
+ }
138
+ /**
139
+ * Generate a Solidity verifier contract from a verification key.
140
+ * @param verificationKey - The VK bytes.
141
+ * @returns The Solidity source code.
142
+ */ async generateContract(verificationKey) {
143
+ const timer = new Timer();
144
+ const result = await this.api.circuitWriteSolidityVerifier({
145
+ verificationKey,
146
+ settings: {
147
+ ipaAccumulation: false,
148
+ oracleHashType: 'poseidon2',
149
+ disableZk: true,
150
+ optimizedSolidityVerifier: false
151
+ }
152
+ });
153
+ return {
154
+ solidityCode: result.solidityCode,
155
+ durationMs: timer.ms()
156
+ };
157
+ }
158
+ /**
159
+ * Verify a Chonk (IVC) proof passed as flat field elements (with public inputs prepended).
160
+ * The split into structured sub-proofs happens server-side in `ChonkProof::from_field_elements`,
161
+ * so this layer doesn't need to know per-component sub-proof sizes.
162
+ * @param fieldsWithPublicInputs - Flat proof fields as 32-byte Uint8Arrays (public inputs prepended).
163
+ * @param verificationKey - The VK bytes.
164
+ */ async verifyChonkProof(fieldsWithPublicInputs, verificationKey) {
165
+ const timer = new Timer();
166
+ const result = await this.api.chonkVerifyFromFields({
167
+ proof: fieldsWithPublicInputs,
168
+ vk: verificationKey
169
+ });
170
+ return {
171
+ verified: result.valid,
172
+ durationMs: timer.ms()
173
+ };
174
+ }
175
+ /** Generate an AVM proof from serialized inputs. */ async generateAvmProof(inputs) {
176
+ const timer = new Timer();
177
+ const result = await this.api.avmProve({
178
+ inputs
179
+ });
180
+ return {
181
+ proof: result.proof,
182
+ stats: result.stats,
183
+ durationMs: timer.ms()
184
+ };
185
+ }
186
+ /** Verify an AVM proof against serialized public inputs. */ async verifyAvmProof(proof, publicInputs) {
187
+ const timer = new Timer();
188
+ const result = await this.api.avmVerify({
189
+ proof,
190
+ publicInputs
191
+ });
192
+ return {
193
+ verified: result.verified,
194
+ durationMs: timer.ms()
195
+ };
196
+ }
197
+ /** Check the AVM circuit from serialized inputs. */ async checkAvmCircuit(inputs) {
198
+ const timer = new Timer();
199
+ const result = await this.api.avmCheckCircuit({
200
+ inputs
201
+ });
202
+ return {
203
+ passed: result.passed,
204
+ stats: result.stats,
205
+ durationMs: timer.ms()
206
+ };
207
+ }
208
+ /** Destroy this instance and kill the underlying bb process. */ async destroy() {
209
+ await this.api.destroy();
210
+ }
211
+ }
212
+ /**
213
+ * Manages bb.js instance lifecycle. By default every `getInstance()` call spawns a fresh
214
+ * bb process that is destroyed when the borrow is disposed. Pass `poolSize` to keep a fixed
215
+ * set of long-lived bb processes that are reused across calls — useful when the per-call
216
+ * bb startup cost dominates the workload (e.g. high-rate IVC verification).
217
+ *
218
+ * Idiomatic usage:
219
+ * ```
220
+ * await using inst = await factory.getInstance();
221
+ * await inst.someMethod(...);
222
+ * // disposed automatically when `inst` goes out of scope
223
+ * ```
224
+ */ export class BBJsFactory {
225
+ bbPath;
226
+ poolSize;
227
+ logger;
228
+ threads;
229
+ debugDir;
230
+ /** Available pooled instances when poolSize is set; otherwise undefined. */ pool;
231
+ /** Lazily-resolved on first `getInstance()` call to prevent racing pool initialization. */ initPromise;
232
+ destroyed;
233
+ constructor(bbPath, options = {}){
234
+ this.bbPath = bbPath;
235
+ this.destroyed = false;
236
+ this.poolSize = options.poolSize;
237
+ this.logger = options.logger;
238
+ this.threads = options.threads;
239
+ this.debugDir = options.debugDir;
240
+ if (this.poolSize !== undefined && this.poolSize < 1) {
241
+ throw new Error(`BBJsFactory poolSize must be >= 1, got ${this.poolSize}`);
242
+ }
243
+ }
244
+ /**
245
+ * Acquire a bb instance. The returned object implements `BBJsApi` and `AsyncDisposable`.
246
+ * With no pool: spawns a fresh bb that is destroyed on dispose. With a pool: borrows from
247
+ * the pool and returns to it on dispose.
248
+ */ async getInstance() {
249
+ if (this.destroyed) {
250
+ throw new Error('BBJsFactory has been destroyed');
251
+ }
252
+ if (this.poolSize === undefined) {
253
+ // No pool: fresh-per-call, dispose destroys.
254
+ const instance = await this.createInstance();
255
+ return this.makeOwned(instance);
256
+ }
257
+ if (!this.initPromise) {
258
+ this.initPromise = this.initPool();
259
+ }
260
+ await this.initPromise;
261
+ const pool = this.pool;
262
+ if (!pool) {
263
+ throw new Error('BBJsFactory has been destroyed');
264
+ }
265
+ const instance = await pool.get();
266
+ if (!instance) {
267
+ throw new Error('BBJsFactory was destroyed while waiting for an instance');
268
+ }
269
+ return this.makeBorrowed(instance);
270
+ }
271
+ /**
272
+ * Tear down all pooled instances. Idempotent. No-op when no pool is configured (fresh-per-call
273
+ * instances are destroyed by their own dispose callbacks). Instances currently held by an
274
+ * in-flight pooled borrow are destroyed by their dispose callback when released.
275
+ */ async destroy() {
276
+ if (this.destroyed) {
277
+ return;
278
+ }
279
+ this.destroyed = true;
280
+ const pool = this.pool;
281
+ this.pool = undefined;
282
+ if (!pool) {
283
+ return;
284
+ }
285
+ const idle = [];
286
+ while(pool.length() > 0){
287
+ const item = pool.getImmediate();
288
+ if (item) {
289
+ idle.push(item);
290
+ }
291
+ }
292
+ pool.cancel();
293
+ // Aggregate teardown failures so a single bb child that fails to shut down doesn't mask others.
294
+ const results = await Promise.allSettled(idle.map((item)=>item.destroy()));
295
+ const errors = results.filter((r)=>r.status === 'rejected').map((r)=>r.reason);
296
+ if (errors.length > 0) {
297
+ throw new AggregateError(errors, `BBJsFactory.destroy: ${errors.length} bb instance(s) failed to shut down`);
298
+ }
299
+ }
300
+ async initPool() {
301
+ // Use allSettled so that if any createInstance() rejects we can destroy the rest instead of
302
+ // leaking bb child processes whose creation succeeded.
303
+ const results = await Promise.allSettled(Array.from({
304
+ length: this.poolSize
305
+ }, ()=>this.createInstance()));
306
+ const items = [];
307
+ const errors = [];
308
+ for (const result of results){
309
+ if (result.status === 'fulfilled') {
310
+ items.push(result.value);
311
+ } else {
312
+ errors.push(result.reason);
313
+ }
314
+ }
315
+ if (errors.length > 0 || this.destroyed) {
316
+ // Either creation failed or destroy() raced ahead — clean up everything we successfully spawned.
317
+ await Promise.all(items.map((item)=>item.destroy()));
318
+ if (errors.length > 0) {
319
+ throw errors[0];
320
+ }
321
+ return;
322
+ }
323
+ const pool = new FifoMemoryQueue();
324
+ for (const item of items){
325
+ pool.put(item);
326
+ }
327
+ this.pool = pool;
328
+ }
329
+ async createInstance() {
330
+ const logFn = this.logger ? (msg)=>this.logger.verbose(`bb.js - ${msg}`) : undefined;
331
+ const raw = await BBJsInstance.create(this.bbPath, logFn, this.threads);
332
+ return this.maybeWrapDebug(raw);
333
+ }
334
+ /** Wrap the instance in a debug wrapper if debugDir is configured. */ async maybeWrapDebug(instance) {
335
+ if (this.debugDir && this.logger) {
336
+ const { DebugBBJsInstance } = await import('./bb_js_debug.js');
337
+ return new DebugBBJsInstance(instance, this.debugDir, this.bbPath, this.logger);
338
+ }
339
+ return instance;
340
+ }
341
+ /**
342
+ * Wrap a fresh instance with an `AsyncDisposable` that destroys it on dispose. Used when no
343
+ * pool is configured. Destroy errors are propagated so that a teardown failure (e.g. a bb child
344
+ * that didn't shut down cleanly) surfaces instead of being silently swallowed.
345
+ */ makeOwned(instance) {
346
+ return this.makeDisposable(instance, ()=>instance.destroy());
347
+ }
348
+ /**
349
+ * Wrap a pooled instance with an `AsyncDisposable` that returns it to the pool (or destroys it
350
+ * if the factory was destroyed in the meantime). Destroy errors are propagated.
351
+ */ makeBorrowed(instance) {
352
+ return this.makeDisposable(instance, async ()=>{
353
+ const pool = this.pool;
354
+ if (pool && !this.destroyed) {
355
+ pool.put(instance);
356
+ } else {
357
+ await instance.destroy();
358
+ }
359
+ });
360
+ }
361
+ makeDisposable(instance, onDispose) {
362
+ let disposed = false;
363
+ const dispose = async ()=>{
364
+ if (disposed) {
365
+ return;
366
+ }
367
+ disposed = true;
368
+ await onDispose();
369
+ };
370
+ return new Proxy(instance, {
371
+ get (target, prop, receiver) {
372
+ if (prop === Symbol.asyncDispose) {
373
+ return dispose;
374
+ }
375
+ return Reflect.get(target, prop, receiver);
376
+ }
377
+ });
378
+ }
379
+ }
@@ -0,0 +1,52 @@
1
+ import type { AvmStat } from '@aztec/bb.js';
2
+ import type { Logger } from '@aztec/foundation/log';
3
+ import type { UltraHonkFlavor } from '../honk.js';
4
+ import type { BBJsApi, BBJsProofResult } from './bb_js_backend.js';
5
+ /**
6
+ * Wraps a BBJsApi instance to write debug files and log equivalent CLI commands.
7
+ * Activated when BB_DEBUG_OUTPUT_DIR is set. Each operation writes its inputs
8
+ * and outputs to a numbered subdirectory, enabling offline reproduction.
9
+ */
10
+ export declare class DebugBBJsInstance implements BBJsApi {
11
+ private inner;
12
+ private debugDir;
13
+ private bbPath;
14
+ private logger;
15
+ private counter;
16
+ constructor(inner: BBJsApi, debugDir: string, bbPath: string, logger: Logger);
17
+ private nextDir;
18
+ private logCommand;
19
+ generateProof(circuitName: string, bytecode: Uint8Array, verificationKey: Uint8Array, witness: Uint8Array, flavor: UltraHonkFlavor): Promise<BBJsProofResult>;
20
+ verifyProof(proofFields: Uint8Array[], verificationKey: Uint8Array, publicInputFields: Uint8Array[], flavor: UltraHonkFlavor): Promise<{
21
+ verified: boolean;
22
+ durationMs: number;
23
+ }>;
24
+ verifyChonkProof(fieldsWithPublicInputs: Uint8Array[], verificationKey: Uint8Array): Promise<{
25
+ verified: boolean;
26
+ durationMs: number;
27
+ }>;
28
+ computeGateCount(circuitName: string, bytecode: Uint8Array, flavor: UltraHonkFlavor | 'mega_honk'): Promise<{
29
+ circuitSize: number;
30
+ durationMs: number;
31
+ }>;
32
+ generateAvmProof(inputs: Uint8Array): Promise<{
33
+ proof: Uint8Array[];
34
+ stats: AvmStat[];
35
+ durationMs: number;
36
+ }>;
37
+ verifyAvmProof(proof: Uint8Array[], publicInputs: Uint8Array): Promise<{
38
+ verified: boolean;
39
+ durationMs: number;
40
+ }>;
41
+ checkAvmCircuit(inputs: Uint8Array): Promise<{
42
+ passed: boolean;
43
+ stats: AvmStat[];
44
+ durationMs: number;
45
+ }>;
46
+ generateContract(verificationKey: Uint8Array): Promise<{
47
+ solidityCode: string;
48
+ durationMs: number;
49
+ }>;
50
+ destroy(): Promise<void>;
51
+ }
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmJfanNfZGVidWcuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iYi9iYl9qc19kZWJ1Zy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDNUMsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFNcEQsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ2xELE9BQU8sS0FBSyxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQWlDbkU7Ozs7R0FJRztBQUNILHFCQUFhLGlCQUFrQixZQUFXLE9BQU87SUFJN0MsT0FBTyxDQUFDLEtBQUs7SUFDYixPQUFPLENBQUMsUUFBUTtJQUNoQixPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxNQUFNO0lBTmhCLE9BQU8sQ0FBQyxPQUFPLENBQUs7SUFFcEIsWUFDVSxLQUFLLEVBQUUsT0FBTyxFQUNkLFFBQVEsRUFBRSxNQUFNLEVBQ2hCLE1BQU0sRUFBRSxNQUFNLEVBQ2QsTUFBTSxFQUFFLE1BQU0sRUFDcEI7SUFFSixPQUFPLENBQUMsT0FBTztZQU9ELFVBQVU7SUFLbEIsYUFBYSxDQUNqQixXQUFXLEVBQUUsTUFBTSxFQUNuQixRQUFRLEVBQUUsVUFBVSxFQUNwQixlQUFlLEVBQUUsVUFBVSxFQUMzQixPQUFPLEVBQUUsVUFBVSxFQUNuQixNQUFNLEVBQUUsZUFBZSxHQUN0QixPQUFPLENBQUMsZUFBZSxDQUFDLENBOEIxQjtJQUVLLFdBQVcsQ0FDZixXQUFXLEVBQUUsVUFBVSxFQUFFLEVBQ3pCLGVBQWUsRUFBRSxVQUFVLEVBQzNCLGlCQUFpQixFQUFFLFVBQVUsRUFBRSxFQUMvQixNQUFNLEVBQUUsZUFBZSxHQUN0QixPQUFPLENBQUM7UUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDO1FBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBQUMsQ0FvQnBEO0lBRUssZ0JBQWdCLENBQ3BCLHNCQUFzQixFQUFFLFVBQVUsRUFBRSxFQUNwQyxlQUFlLEVBQUUsVUFBVSxHQUMxQixPQUFPLENBQUM7UUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDO1FBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBQUMsQ0FhcEQ7SUFFSyxnQkFBZ0IsQ0FDcEIsV0FBVyxFQUFFLE1BQU0sRUFDbkIsUUFBUSxFQUFFLFVBQVUsRUFDcEIsTUFBTSxFQUFFLGVBQWUsR0FBRyxXQUFXLEdBQ3BDLE9BQU8sQ0FBQztRQUFFLFdBQVcsRUFBRSxNQUFNLENBQUM7UUFBQyxVQUFVLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FBQyxDQWV0RDtJQUVLLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDO1FBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxDQUFDO1FBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBQUMsQ0Flakg7SUFFSyxjQUFjLENBQ2xCLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFDbkIsWUFBWSxFQUFFLFVBQVUsR0FDdkIsT0FBTyxDQUFDO1FBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQztRQUFDLFVBQVUsRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDLENBYXBEO0lBRUssZUFBZSxDQUFDLE1BQU0sRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDO1FBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQztRQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQztRQUFDLFVBQVUsRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDLENBVTVHO0lBRUQsZ0JBQWdCLENBQUMsZUFBZSxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUM7UUFBRSxZQUFZLEVBQUUsTUFBTSxDQUFDO1FBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBQUMsQ0FFbkc7SUFFRCxPQUFPLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUV2QjtDQUNGIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bb_js_debug.d.ts","sourceRoot":"","sources":["../../src/bb/bb_js_debug.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAMpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAiCnE;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IAI7C,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,OAAO,CAAK;IAEpB,YACU,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACpB;IAEJ,OAAO,CAAC,OAAO;YAOD,UAAU;IAKlB,aAAa,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,UAAU,EACpB,eAAe,EAAE,UAAU,EAC3B,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,eAAe,CAAC,CA8B1B;IAEK,WAAW,CACf,WAAW,EAAE,UAAU,EAAE,EACzB,eAAe,EAAE,UAAU,EAC3B,iBAAiB,EAAE,UAAU,EAAE,EAC/B,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAoBpD;IAEK,gBAAgB,CACpB,sBAAsB,EAAE,UAAU,EAAE,EACpC,eAAe,EAAE,UAAU,GAC1B,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAapD;IAEK,gBAAgB,CACpB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,eAAe,GAAG,WAAW,GACpC,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAetD;IAEK,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,OAAO,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAejH;IAEK,cAAc,CAClB,KAAK,EAAE,UAAU,EAAE,EACnB,YAAY,EAAE,UAAU,GACvB,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAapD;IAEK,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAU5G;IAED,gBAAgB,CAAC,eAAe,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAEnG;IAED,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAEvB;CACF"}
@@ -0,0 +1,176 @@
1
+ import { promises as fs } from 'fs';
2
+ import * as path from 'path';
3
+ import { gzipSync } from 'zlib';
4
+ /**
5
+ * Maps UltraHonk flavors to the CLI flags used by the bb binary.
6
+ * The CLI always uses `--scheme ultra_honk`; flavors are expressed via
7
+ * `--oracle_hash` and `--ipa_accumulation`.
8
+ */ function getCliFlags(flavor) {
9
+ const base = '--scheme ultra_honk --disable_zk';
10
+ switch(flavor){
11
+ case 'ultra_honk':
12
+ return `${base} --oracle_hash poseidon2`;
13
+ case 'ultra_keccak_honk':
14
+ return `${base} --oracle_hash keccak`;
15
+ case 'ultra_starknet_honk':
16
+ return `${base} --oracle_hash starknet`;
17
+ case 'ultra_rollup_honk':
18
+ return `${base} --oracle_hash poseidon2 --ipa_accumulation`;
19
+ }
20
+ }
21
+ /** Concatenate an array of 32-byte field elements into a single buffer. */ function concatFields(fields) {
22
+ const totalLen = fields.reduce((sum, f)=>sum + f.length, 0);
23
+ const buf = Buffer.alloc(totalLen);
24
+ let offset = 0;
25
+ for (const f of fields){
26
+ buf.set(f, offset);
27
+ offset += f.length;
28
+ }
29
+ return buf;
30
+ }
31
+ /**
32
+ * Wraps a BBJsApi instance to write debug files and log equivalent CLI commands.
33
+ * Activated when BB_DEBUG_OUTPUT_DIR is set. Each operation writes its inputs
34
+ * and outputs to a numbered subdirectory, enabling offline reproduction.
35
+ */ export class DebugBBJsInstance {
36
+ inner;
37
+ debugDir;
38
+ bbPath;
39
+ logger;
40
+ counter;
41
+ constructor(inner, debugDir, bbPath, logger){
42
+ this.inner = inner;
43
+ this.debugDir = debugDir;
44
+ this.bbPath = bbPath;
45
+ this.logger = logger;
46
+ this.counter = 0;
47
+ }
48
+ nextDir(prefix) {
49
+ this.counter++;
50
+ const padded = String(this.counter).padStart(3, '0');
51
+ return path.join(this.debugDir, `${prefix}-${padded}`);
52
+ }
53
+ /** Write a command string to both the logger and a command.sh file in the given directory. */ async logCommand(dir, command) {
54
+ this.logger.info(`Executing BB with: ${command}`);
55
+ await fs.writeFile(path.join(dir, 'command.sh'), `#!/bin/bash\n${command}\n`, {
56
+ mode: 0o755
57
+ });
58
+ }
59
+ async generateProof(circuitName, bytecode, verificationKey, witness, flavor) {
60
+ const dir = this.nextDir(circuitName);
61
+ await fs.mkdir(dir, {
62
+ recursive: true
63
+ });
64
+ const bytecodePath = path.join(dir, `${circuitName}-bytecode.gz`);
65
+ const vkPath = path.join(dir, `${circuitName}-vk`);
66
+ const witnessPath = path.join(dir, 'partial-witness.gz');
67
+ await Promise.all([
68
+ fs.writeFile(bytecodePath, gzipSync(bytecode)),
69
+ fs.writeFile(vkPath, verificationKey),
70
+ fs.writeFile(witnessPath, gzipSync(witness))
71
+ ]);
72
+ const flags = getCliFlags(flavor);
73
+ await this.logCommand(dir, `${this.bbPath} prove ${flags} -o ${dir} -b ${bytecodePath} -k ${vkPath} -w ${witnessPath}`);
74
+ const result = await this.inner.generateProof(circuitName, bytecode, verificationKey, witness, flavor);
75
+ const proofBuf = concatFields(result.proofFields);
76
+ const publicInputsBuf = concatFields(result.publicInputFields);
77
+ await Promise.all([
78
+ fs.writeFile(path.join(dir, 'proof'), proofBuf),
79
+ fs.writeFile(path.join(dir, 'public_inputs'), publicInputsBuf)
80
+ ]);
81
+ return result;
82
+ }
83
+ async verifyProof(proofFields, verificationKey, publicInputFields, flavor) {
84
+ const dir = this.nextDir(`verify-${flavor}`);
85
+ await fs.mkdir(dir, {
86
+ recursive: true
87
+ });
88
+ const proofPath = path.join(dir, 'proof');
89
+ const vkPath = path.join(dir, 'vk');
90
+ const publicInputsPath = path.join(dir, 'public_inputs');
91
+ const proofBuf = concatFields(proofFields);
92
+ const publicInputsBuf = concatFields(publicInputFields);
93
+ await Promise.all([
94
+ fs.writeFile(proofPath, proofBuf),
95
+ fs.writeFile(vkPath, verificationKey),
96
+ fs.writeFile(publicInputsPath, publicInputsBuf)
97
+ ]);
98
+ const flags = getCliFlags(flavor);
99
+ await this.logCommand(dir, `${this.bbPath} verify ${flags} -p ${proofPath} -k ${vkPath} -i ${publicInputsPath}`);
100
+ return this.inner.verifyProof(proofFields, verificationKey, publicInputFields, flavor);
101
+ }
102
+ async verifyChonkProof(fieldsWithPublicInputs, verificationKey) {
103
+ const dir = this.nextDir('verify-chonk');
104
+ await fs.mkdir(dir, {
105
+ recursive: true
106
+ });
107
+ const proofPath = path.join(dir, 'proof');
108
+ const vkPath = path.join(dir, 'vk');
109
+ const proofBuf = concatFields(fieldsWithPublicInputs);
110
+ await Promise.all([
111
+ fs.writeFile(proofPath, proofBuf),
112
+ fs.writeFile(vkPath, verificationKey)
113
+ ]);
114
+ await this.logCommand(dir, `${this.bbPath} verify --scheme chonk -p ${proofPath} -k ${vkPath} -v`);
115
+ return this.inner.verifyChonkProof(fieldsWithPublicInputs, verificationKey);
116
+ }
117
+ async computeGateCount(circuitName, bytecode, flavor) {
118
+ const dir = this.nextDir(`gates-${circuitName}`);
119
+ await fs.mkdir(dir, {
120
+ recursive: true
121
+ });
122
+ const bytecodePath = path.join(dir, `${circuitName}-bytecode.gz`);
123
+ await fs.writeFile(bytecodePath, gzipSync(bytecode));
124
+ if (flavor === 'mega_honk') {
125
+ await this.logCommand(dir, `${this.bbPath} gates --scheme chonk -b ${bytecodePath}`);
126
+ } else {
127
+ const flags = getCliFlags(flavor);
128
+ await this.logCommand(dir, `${this.bbPath} gates ${flags} -b ${bytecodePath}`);
129
+ }
130
+ return this.inner.computeGateCount(circuitName, bytecode, flavor);
131
+ }
132
+ async generateAvmProof(inputs) {
133
+ const dir = this.nextDir('avm-prove');
134
+ await fs.mkdir(dir, {
135
+ recursive: true
136
+ });
137
+ const inputsPath = path.join(dir, 'avm_inputs.bin');
138
+ await fs.writeFile(inputsPath, inputs);
139
+ await this.logCommand(dir, `${this.bbPath} avm_prove --avm-inputs ${inputsPath} -o ${dir}`);
140
+ const result = await this.inner.generateAvmProof(inputs);
141
+ const proofBuf = concatFields(result.proof);
142
+ await fs.writeFile(path.join(dir, 'proof'), proofBuf);
143
+ return result;
144
+ }
145
+ async verifyAvmProof(proof, publicInputs) {
146
+ const dir = this.nextDir('avm-verify');
147
+ await fs.mkdir(dir, {
148
+ recursive: true
149
+ });
150
+ const proofPath = path.join(dir, 'proof');
151
+ const publicInputsPath = path.join(dir, 'avm_public_inputs.bin');
152
+ const proofBuf = concatFields(proof);
153
+ await Promise.all([
154
+ fs.writeFile(proofPath, proofBuf),
155
+ fs.writeFile(publicInputsPath, publicInputs)
156
+ ]);
157
+ await this.logCommand(dir, `${this.bbPath} avm_verify -p ${proofPath} --avm-public-inputs ${publicInputsPath}`);
158
+ return this.inner.verifyAvmProof(proof, publicInputs);
159
+ }
160
+ async checkAvmCircuit(inputs) {
161
+ const dir = this.nextDir('avm-check-circuit');
162
+ await fs.mkdir(dir, {
163
+ recursive: true
164
+ });
165
+ const inputsPath = path.join(dir, 'avm_inputs.bin');
166
+ await fs.writeFile(inputsPath, inputs);
167
+ await this.logCommand(dir, `${this.bbPath} avm_check_circuit --avm-inputs ${inputsPath}`);
168
+ return this.inner.checkAvmCircuit(inputs);
169
+ }
170
+ generateContract(verificationKey) {
171
+ return this.inner.generateContract(verificationKey);
172
+ }
173
+ destroy() {
174
+ return this.inner.destroy();
175
+ }
176
+ }
@@ -0,0 +1,4 @@
1
+ export declare const VK_FILENAME = "vk";
2
+ export declare const PROOF_FILENAME = "proof";
3
+ export declare const PUBLIC_INPUTS_FILENAME = "public_inputs";
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZV9uYW1lcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2JiL2ZpbGVfbmFtZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0EsZUFBTyxNQUFNLFdBQVcsT0FBTyxDQUFDO0FBQ2hDLGVBQU8sTUFBTSxjQUFjLFVBQVUsQ0FBQztBQUN0QyxlQUFPLE1BQU0sc0JBQXNCLGtCQUFrQixDQUFDIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file_names.d.ts","sourceRoot":"","sources":["../../src/bb/file_names.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,OAAO,CAAC;AAChC,eAAO,MAAM,cAAc,UAAU,CAAC;AACtC,eAAO,MAAM,sBAAsB,kBAAkB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // File-naming conventions used by `bb` CLI output directories. Retained for consumers that still
2
+ // read/write proofs to disk alongside bb-prover's in-memory bb.js flows.
3
+ export const VK_FILENAME = 'vk';
4
+ export const PROOF_FILENAME = 'proof';
5
+ export const PUBLIC_INPUTS_FILENAME = 'public_inputs';
package/dest/config.d.ts CHANGED
@@ -3,8 +3,24 @@ export interface BBConfig {
3
3
  bbWorkingDirectory: string;
4
4
  /** Whether to skip tmp dir cleanup for debugging purposes */
5
5
  bbSkipCleanup: boolean;
6
+ /**
7
+ * Number of long-lived bb processes pooled by the RPC verifier (BBCircuitVerifier).
8
+ * Also caps concurrent verifications via the wrapping QueuedIVCVerifier.
9
+ */
6
10
  numConcurrentIVCVerifiers: number;
11
+ /** Thread count for the RPC IVC verifier. */
7
12
  bbIVCConcurrency: number;
13
+ /**
14
+ * Upper bound on proofs per batch for the peer chonk batch verifier.
15
+ * Proofs are verified immediately as they arrive — this only caps how many
16
+ * can accumulate while a batch is already being processed.
17
+ * Default 16: at 4 cores, a full batch of 16 verifies in ~245ms wall time.
18
+ */
19
+ bbChonkVerifyMaxBatch: number;
20
+ /** Thread count for the peer batch verifier parallel reduce. Default 6 to leave cores for the rest of the node. */
21
+ bbChonkVerifyConcurrency: number;
22
+ /** When set, bb.js operations write input/output files and log equivalent CLI commands to this directory. */
23
+ bbDebugOutputDir?: string;
8
24
  }
9
25
  export interface ACVMConfig {
10
26
  /** The path to the ACVM binary */
@@ -12,4 +28,4 @@ export interface ACVMConfig {
12
28
  /** The working directory to use for simulation/proving */
13
29
  acvmWorkingDirectory: string;
14
30
  }
15
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sV0FBVyxRQUFRO0lBQ3ZCLFlBQVksRUFBRSxNQUFNLENBQUM7SUFDckIsa0JBQWtCLEVBQUUsTUFBTSxDQUFDO0lBQzNCLDZEQUE2RDtJQUM3RCxhQUFhLEVBQUUsT0FBTyxDQUFDO0lBQ3ZCLHlCQUF5QixFQUFFLE1BQU0sQ0FBQztJQUNsQyxnQkFBZ0IsRUFBRSxNQUFNLENBQUM7Q0FDMUI7QUFFRCxNQUFNLFdBQVcsVUFBVTtJQUN6QixrQ0FBa0M7SUFDbEMsY0FBYyxFQUFFLE1BQU0sQ0FBQztJQUN2QiwwREFBMEQ7SUFDMUQsb0JBQW9CLEVBQUUsTUFBTSxDQUFDO0NBQzlCIn0=
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sV0FBVyxRQUFRO0lBQ3ZCLFlBQVksRUFBRSxNQUFNLENBQUM7SUFDckIsa0JBQWtCLEVBQUUsTUFBTSxDQUFDO0lBQzNCLDZEQUE2RDtJQUM3RCxhQUFhLEVBQUUsT0FBTyxDQUFDO0lBQ3ZCOzs7T0FHRztJQUNILHlCQUF5QixFQUFFLE1BQU0sQ0FBQztJQUNsQyw2Q0FBNkM7SUFDN0MsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDO0lBQ3pCOzs7OztPQUtHO0lBQ0gscUJBQXFCLEVBQUUsTUFBTSxDQUFDO0lBQzlCLG1IQUFtSDtJQUNuSCx3QkFBd0IsRUFBRSxNQUFNLENBQUM7SUFDakMsNkdBQTZHO0lBQzdHLGdCQUFnQixDQUFDLEVBQUUsTUFBTSxDQUFDO0NBQzNCO0FBRUQsTUFBTSxXQUFXLFVBQVU7SUFDekIsa0NBQWtDO0lBQ2xDLGNBQWMsRUFBRSxNQUFNLENBQUM7SUFDdkIsMERBQTBEO0lBQzFELG9CQUFvQixFQUFFLE1BQU0sQ0FBQztDQUM5QiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,aAAa,EAAE,OAAO,CAAC;IACvB,yBAAyB,EAAE,MAAM,CAAC;IAClC,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,oBAAoB,EAAE,MAAM,CAAC;CAC9B"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,aAAa,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,yBAAyB,EAAE,MAAM,CAAC;IAClC,6CAA6C;IAC7C,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,mHAAmH;IACnH,wBAAwB,EAAE,MAAM,CAAC;IACjC,6GAA6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,oBAAoB,EAAE,MAAM,CAAC;CAC9B"}