@aztec/bb-prover 0.0.1-commit.2f68f620 → 0.0.1-commit.3100065

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.
@@ -6,21 +6,19 @@ import { Timer } from '@aztec/foundation/timer';
6
6
  import { ProtocolCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
7
7
  import { Unpackr } from 'msgpackr';
8
8
  import { execFile } from 'node:child_process';
9
- import { rmSync } from 'node:fs';
10
- import { mkdtemp, rm } from 'node:fs/promises';
9
+ import { unlinkSync } from 'node:fs';
10
+ import { unlink } from 'node:fs/promises';
11
11
  import * as os from 'node:os';
12
12
  import * as path from 'node:path';
13
13
  import { promisify } from 'node:util';
14
14
  const execFileAsync = promisify(execFile);
15
- const RESULT_TIMEOUT_MS = 5 * 60 * 1000;
16
- const STOP_DRAIN_TIMEOUT_MS = 5_000;
17
15
  /** Maps client protocol artifacts used for chonk verification to VK indices. */ const CHONK_VK_ARTIFACTS = [
18
16
  'HidingKernelToRollup',
19
17
  'HidingKernelToPublic'
20
18
  ];
21
19
  /**
22
20
  * Batch verifier for Chonk IVC proofs. Uses the bb batch verifier service
23
- * which batches IPA verification into a constant number of SRS MSMs for better throughput.
21
+ * which batches IPA verification into a single SRS MSM for better throughput.
24
22
  *
25
23
  * Architecture:
26
24
  * - Spawns a persistent `bb msgpack run` process via Barretenberg (native backend)
@@ -33,7 +31,6 @@ const STOP_DRAIN_TIMEOUT_MS = 5_000;
33
31
  batchSize;
34
32
  label;
35
33
  bb;
36
- fifoDir;
37
34
  fifoPath;
38
35
  nextRequestId;
39
36
  pendingRequests;
@@ -42,22 +39,17 @@ const STOP_DRAIN_TIMEOUT_MS = 5_000;
42
39
  logger;
43
40
  /** Maps artifact name to VK index in the batch verifier. */ vkIndexMap;
44
41
  /** Bound cleanup handler for process exit signals. */ exitCleanup;
45
- stopped;
46
- fatalError;
47
- pendingDrainedResolvers;
48
42
  constructor(config, vkBuffers, batchSize, label){
49
43
  this.config = config;
50
44
  this.vkBuffers = vkBuffers;
51
45
  this.batchSize = batchSize;
52
46
  this.label = label;
53
- this.fifoPath = '';
54
47
  this.nextRequestId = 0;
55
48
  this.pendingRequests = new Map();
56
49
  this.logger = createLogger('bb-prover:batch_chonk_verifier');
57
50
  this.vkIndexMap = new Map();
58
51
  this.exitCleanup = null;
59
- this.stopped = false;
60
- this.pendingDrainedResolvers = new Set();
52
+ this.fifoPath = path.join(os.tmpdir(), `bb-batch-${label}-${process.pid}-${Date.now()}.fifo`);
61
53
  this.fifoReader = new FifoFrameReader();
62
54
  this.sendQueue = new SerialQueue();
63
55
  this.sendQueue.start(1);
@@ -88,91 +80,47 @@ const STOP_DRAIN_TIMEOUT_MS = 5_000;
88
80
  }
89
81
  async start() {
90
82
  this.logger.info('Starting BatchChonkVerifier');
91
- try {
92
- this.bb = await Barretenberg.new({
93
- bbPath: this.config.bbBinaryPath,
94
- backend: BackendType.NativeUnixSocket
95
- });
96
- await this.bb.initSRSChonk();
97
- // Keep the FIFO in a private directory so cleanup has a single owner.
98
- this.fifoDir = await mkdtemp(path.join(os.tmpdir(), `bb-batch-${this.label}-${process.pid}-`));
99
- this.fifoPath = path.join(this.fifoDir, 'results.fifo');
100
- await execFileAsync('mkfifo', [
101
- this.fifoPath
102
- ]);
103
- this.registerExitCleanup();
104
- this.startFifoReader();
105
- await this.bb.chonkBatchVerifierStart({
106
- vks: this.vkBuffers,
107
- numCores: this.config.bbChonkVerifyConcurrency || 0,
108
- batchSize: this.batchSize,
109
- fifoPath: this.fifoPath
110
- });
111
- } catch (err) {
112
- this.fifoReader.stop();
113
- this.deregisterExitCleanup();
114
- await this.cleanupFifo();
115
- await this.bb?.destroy().catch(()=>{});
116
- throw err;
117
- }
83
+ this.bb = await Barretenberg.new({
84
+ bbPath: this.config.bbBinaryPath,
85
+ backend: BackendType.NativeUnixSocket
86
+ });
87
+ await this.bb.initSRSChonk();
88
+ await execFileAsync('mkfifo', [
89
+ this.fifoPath
90
+ ]);
91
+ this.registerExitCleanup();
92
+ await this.bb.chonkBatchVerifierStart({
93
+ vks: this.vkBuffers,
94
+ numCores: this.config.bbChonkVerifyConcurrency || 0,
95
+ batchSize: this.batchSize,
96
+ fifoPath: this.fifoPath
97
+ });
98
+ this.startFifoReader();
118
99
  this.logger.info('BatchChonkVerifier started', {
119
100
  fifoPath: this.fifoPath
120
101
  });
121
102
  }
122
103
  verifyProof(tx) {
123
- const totalTimer = new Timer();
124
- return (async ()=>{
125
- const circuit = tx.data.forPublic ? 'HidingKernelToPublic' : 'HidingKernelToRollup';
126
- const vkIndex = this.vkIndexMap.get(circuit);
127
- if (vkIndex === undefined) {
128
- throw new Error(`No VK index for circuit ${circuit}`);
129
- }
130
- const proofWithPubInputs = tx.chonkProof.attachPublicInputs(tx.data.publicInputs().toFields());
131
- const proofFields = proofWithPubInputs.fieldsWithPublicInputs.map((f)=>f.toBuffer());
132
- return await this.enqueueProof(vkIndex, proofFields);
133
- })().catch((err)=>{
134
- this.logger.warn(`Failed to verify Chonk proof for tx ${tx.getTxHash().toString()}: ${String(err)}`);
135
- return {
136
- valid: false,
137
- durationMs: 0,
138
- totalDurationMs: totalTimer.ms()
139
- };
140
- });
104
+ const circuit = tx.data.forPublic ? 'HidingKernelToPublic' : 'HidingKernelToRollup';
105
+ const vkIndex = this.vkIndexMap.get(circuit);
106
+ if (vkIndex === undefined) {
107
+ throw new Error(`No VK index for circuit ${circuit}`);
108
+ }
109
+ const proofWithPubInputs = tx.chonkProof.attachPublicInputs(tx.data.publicInputs().toFields());
110
+ const proofFields = proofWithPubInputs.fieldsWithPublicInputs.map((f)=>f.toBuffer());
111
+ return this.enqueueProof(vkIndex, proofFields);
141
112
  }
142
113
  /** Enqueue raw proof fields for verification. Used directly by tests with custom VKs. */ enqueueProof(vkIndex, proofFields) {
143
- if (this.stopped) {
144
- return Promise.reject(new Error('BatchChonkVerifier stopped'));
145
- }
146
- if (this.fatalError) {
147
- return Promise.reject(this.fatalError);
148
- }
149
114
  const totalTimer = new Timer();
150
115
  const requestId = this.nextRequestId++;
151
116
  const resultPromise = new Promise((resolve, reject)=>{
152
- const timeout = setTimeout(()=>{
153
- const pending = this.pendingRequests.get(requestId);
154
- if (!pending) {
155
- return;
156
- }
157
- this.pendingRequests.delete(requestId);
158
- pending.reject(new Error(`BatchChonkVerifier result timed out for request_id=${requestId}`));
159
- this.notifyPendingDrained();
160
- }, RESULT_TIMEOUT_MS);
161
- // A pending result timer must never keep the host process alive on its own (e.g. an
162
- // orphaned request at process exit); the FIFO reader keeps the loop alive while results
163
- // are genuinely awaited.
164
- timeout.unref();
165
117
  this.pendingRequests.set(requestId, {
166
118
  resolve,
167
119
  reject,
168
- totalTimer,
169
- timeout
120
+ totalTimer
170
121
  });
171
122
  });
172
123
  void this.sendQueue.put(async ()=>{
173
- if (this.fatalError) {
174
- throw this.fatalError;
175
- }
176
124
  await this.bb.chonkBatchVerifierQueue({
177
125
  requestId,
178
126
  vkIndex,
@@ -182,62 +130,35 @@ const STOP_DRAIN_TIMEOUT_MS = 5_000;
182
130
  const pending = this.pendingRequests.get(requestId);
183
131
  if (pending) {
184
132
  this.pendingRequests.delete(requestId);
185
- clearTimeout(pending.timeout);
186
133
  pending.reject(err instanceof Error ? err : new Error(String(err)));
187
- this.notifyPendingDrained();
188
134
  }
189
135
  });
190
136
  return resultPromise;
191
137
  }
192
138
  async stop() {
193
139
  this.logger.info('Stopping BatchChonkVerifier');
194
- this.stopped = true;
140
+ // Stop accepting new proofs
141
+ await this.sendQueue.end();
142
+ // Stop the bb service (flushes remaining proofs)
195
143
  try {
196
- // Stop accepting new proofs and flush the send queue. Bound it so an unresponsive
197
- // native process can't block teardown of our own event-loop handles indefinitely.
198
- await this.withTimeout(this.sendQueue.end(), STOP_DRAIN_TIMEOUT_MS, 'send queue flush');
199
- // Stop the bb service (flushes remaining proofs).
200
- await this.withTimeout(this.bb.chonkBatchVerifierStop({}), STOP_DRAIN_TIMEOUT_MS, 'chonkBatchVerifierStop');
201
- // Native stop flushes callbacks; keep the FIFO open until those frames are observed.
202
- const drained = await this.waitForPendingRequestsToDrain(STOP_DRAIN_TIMEOUT_MS);
203
- if (!drained) {
204
- this.rejectPendingRequests(new Error('Timed out waiting for BatchChonkVerifier results during stop'));
205
- }
144
+ await this.bb.chonkBatchVerifierStop({});
206
145
  } catch (err) {
207
- this.logger.warn(`Error during BatchChonkVerifier graceful stop: ${err}`);
208
- this.rejectPendingRequests(err instanceof Error ? err : new Error(String(err)));
209
- } finally{
210
- // Always release our own event-loop handles — the FIFO read stream (a blocking
211
- // threadpool read that can't be unref'd), the unix socket, the native process, and the
212
- // exit handler — so the host process exits cleanly even if the native backend is wedged.
213
- this.fifoReader.stop();
214
- this.deregisterExitCleanup();
215
- await this.cleanupFifo();
216
- await this.bb.destroy().catch((err)=>this.logger.warn(`Error destroying bb backend during stop: ${err}`));
146
+ this.logger.warn(`Error stopping batch verifier service: ${err}`);
147
+ }
148
+ // Stop FIFO reader
149
+ this.fifoReader.stop();
150
+ // Clean up FIFO file and deregister exit handler
151
+ await unlink(this.fifoPath).catch(()=>{});
152
+ this.deregisterExitCleanup();
153
+ // Reject any remaining pending requests
154
+ for (const [id, pending] of this.pendingRequests){
155
+ pending.reject(new Error('BatchChonkVerifier stopped'));
156
+ this.pendingRequests.delete(id);
217
157
  }
158
+ // Destroy bb process
159
+ await this.bb.destroy();
218
160
  this.logger.info('BatchChonkVerifier stopped');
219
161
  }
220
- /**
221
- * Races a promise against a timeout so a wedged native backend can't block teardown. The
222
- * timer is unref'd so it never keeps the process alive; the underlying promise stays handled
223
- * by the race even if the timeout wins, so it cannot surface as an unhandled rejection.
224
- */ async withTimeout(promise, timeoutMs, label) {
225
- let timer;
226
- const timeout = new Promise((_, reject)=>{
227
- timer = setTimeout(()=>reject(new Error(`BatchChonkVerifier ${label} timed out after ${timeoutMs}ms`)), timeoutMs);
228
- timer.unref();
229
- });
230
- try {
231
- return await Promise.race([
232
- promise,
233
- timeout
234
- ]);
235
- } finally{
236
- if (timer) {
237
- clearTimeout(timer);
238
- }
239
- }
240
- }
241
162
  startFifoReader() {
242
163
  const unpackr = new Unpackr({
243
164
  useRecords: false
@@ -248,18 +169,16 @@ const STOP_DRAIN_TIMEOUT_MS = 5_000;
248
169
  this.handleResult(result);
249
170
  } catch (err) {
250
171
  this.logger.error(`FIFO: failed to decode msgpack result: ${err}`);
251
- // A corrupt result stream cannot safely be matched to outstanding requests.
252
- this.failVerifier(err instanceof Error ? err : new Error(String(err)));
253
172
  }
254
173
  });
255
174
  this.fifoReader.on('error', (err)=>{
256
175
  this.logger.error(`FIFO reader error: ${err}`);
257
- this.failVerifier(err);
258
176
  });
259
177
  this.fifoReader.on('end', ()=>{
260
178
  this.logger.debug('FIFO reader: stream ended');
261
- if (!this.stopped) {
262
- this.failVerifier(new Error('FIFO stream ended unexpectedly'));
179
+ for (const [id, pending] of this.pendingRequests){
180
+ pending.reject(new Error('FIFO stream ended unexpectedly'));
181
+ this.pendingRequests.delete(id);
263
182
  }
264
183
  });
265
184
  this.fifoReader.start(this.fifoPath);
@@ -271,7 +190,6 @@ const STOP_DRAIN_TIMEOUT_MS = 5_000;
271
190
  return;
272
191
  }
273
192
  this.pendingRequests.delete(result.request_id);
274
- clearTimeout(pending.timeout);
275
193
  const valid = result.status === 0; // VerifyStatus::OK
276
194
  const durationMs = result.time_in_verify_ms;
277
195
  const totalDurationMs = pending.totalTimer.ms();
@@ -290,95 +208,25 @@ const STOP_DRAIN_TIMEOUT_MS = 5_000;
290
208
  });
291
209
  }
292
210
  pending.resolve(ivcResult);
293
- this.notifyPendingDrained();
294
211
  }
295
212
  registerExitCleanup() {
213
+ // Signal handlers must be synchronous — unlinkSync is intentional here
296
214
  this.exitCleanup = ()=>{
297
- this.cleanupFifoSync();
215
+ try {
216
+ unlinkSync(this.fifoPath);
217
+ } catch {
218
+ /* ignore */ }
298
219
  };
299
220
  process.on('exit', this.exitCleanup);
221
+ process.on('SIGINT', this.exitCleanup);
222
+ process.on('SIGTERM', this.exitCleanup);
300
223
  }
301
224
  deregisterExitCleanup() {
302
225
  if (this.exitCleanup) {
303
226
  process.removeListener('exit', this.exitCleanup);
227
+ process.removeListener('SIGINT', this.exitCleanup);
228
+ process.removeListener('SIGTERM', this.exitCleanup);
304
229
  this.exitCleanup = null;
305
230
  }
306
231
  }
307
- rejectPendingRequests(error) {
308
- for (const [id, pending] of Array.from(this.pendingRequests)){
309
- pending.reject(error);
310
- clearTimeout(pending.timeout);
311
- this.pendingRequests.delete(id);
312
- }
313
- this.notifyPendingDrained();
314
- }
315
- failVerifier(error) {
316
- if (!this.fatalError) {
317
- this.fatalError = error;
318
- }
319
- this.rejectPendingRequests(error);
320
- }
321
- waitForPendingRequestsToDrain(timeoutMs) {
322
- if (this.pendingRequests.size === 0) {
323
- return Promise.resolve(true);
324
- }
325
- let timeout;
326
- let onDrain;
327
- const drained = new Promise((resolve)=>{
328
- onDrain = ()=>resolve(true);
329
- this.pendingDrainedResolvers.add(onDrain);
330
- });
331
- const timedOut = new Promise((resolve)=>{
332
- timeout = setTimeout(()=>resolve(false), timeoutMs);
333
- timeout.unref();
334
- });
335
- return Promise.race([
336
- drained,
337
- timedOut
338
- ]).finally(()=>{
339
- if (timeout) {
340
- clearTimeout(timeout);
341
- }
342
- if (onDrain) {
343
- this.pendingDrainedResolvers.delete(onDrain);
344
- }
345
- });
346
- }
347
- notifyPendingDrained() {
348
- if (this.pendingRequests.size > 0) {
349
- return;
350
- }
351
- for (const resolve of Array.from(this.pendingDrainedResolvers)){
352
- resolve();
353
- }
354
- }
355
- async cleanupFifo() {
356
- if (this.fifoDir) {
357
- await rm(this.fifoDir, {
358
- recursive: true,
359
- force: true
360
- }).catch(()=>{});
361
- } else if (this.fifoPath) {
362
- await rm(this.fifoPath, {
363
- force: true
364
- }).catch(()=>{});
365
- }
366
- this.fifoDir = undefined;
367
- this.fifoPath = '';
368
- }
369
- cleanupFifoSync() {
370
- try {
371
- if (this.fifoDir) {
372
- rmSync(this.fifoDir, {
373
- recursive: true,
374
- force: true
375
- });
376
- } else if (this.fifoPath) {
377
- rmSync(this.fifoPath, {
378
- force: true
379
- });
380
- }
381
- } catch {
382
- /* ignore */ }
383
- }
384
232
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/bb-prover",
3
- "version": "0.0.1-commit.2f68f620",
3
+ "version": "0.0.1-commit.3100065",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -70,16 +70,16 @@
70
70
  ]
71
71
  },
72
72
  "dependencies": {
73
- "@aztec/bb.js": "0.0.1-commit.2f68f620",
74
- "@aztec/constants": "0.0.1-commit.2f68f620",
75
- "@aztec/foundation": "0.0.1-commit.2f68f620",
76
- "@aztec/noir-noirc_abi": "0.0.1-commit.2f68f620",
77
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.2f68f620",
78
- "@aztec/noir-types": "0.0.1-commit.2f68f620",
79
- "@aztec/simulator": "0.0.1-commit.2f68f620",
80
- "@aztec/stdlib": "0.0.1-commit.2f68f620",
81
- "@aztec/telemetry-client": "0.0.1-commit.2f68f620",
82
- "@aztec/world-state": "0.0.1-commit.2f68f620",
73
+ "@aztec/bb.js": "0.0.1-commit.3100065",
74
+ "@aztec/constants": "0.0.1-commit.3100065",
75
+ "@aztec/foundation": "0.0.1-commit.3100065",
76
+ "@aztec/noir-noirc_abi": "0.0.1-commit.3100065",
77
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.3100065",
78
+ "@aztec/noir-types": "0.0.1-commit.3100065",
79
+ "@aztec/simulator": "0.0.1-commit.3100065",
80
+ "@aztec/stdlib": "0.0.1-commit.3100065",
81
+ "@aztec/telemetry-client": "0.0.1-commit.3100065",
82
+ "@aztec/world-state": "0.0.1-commit.3100065",
83
83
  "commander": "^12.1.0",
84
84
  "msgpackr": "^1.11.2",
85
85
  "pako": "^2.1.0",
@@ -87,11 +87,11 @@
87
87
  "tslib": "^2.4.0"
88
88
  },
89
89
  "devDependencies": {
90
- "@aztec/ethereum": "0.0.1-commit.2f68f620",
91
- "@aztec/kv-store": "0.0.1-commit.2f68f620",
92
- "@aztec/noir-contracts.js": "0.0.1-commit.2f68f620",
93
- "@aztec/noir-test-contracts.js": "0.0.1-commit.2f68f620",
94
- "@aztec/protocol-contracts": "0.0.1-commit.2f68f620",
90
+ "@aztec/ethereum": "0.0.1-commit.3100065",
91
+ "@aztec/kv-store": "0.0.1-commit.3100065",
92
+ "@aztec/noir-contracts.js": "0.0.1-commit.3100065",
93
+ "@aztec/noir-test-contracts.js": "0.0.1-commit.3100065",
94
+ "@aztec/protocol-contracts": "0.0.1-commit.3100065",
95
95
  "@jest/globals": "^30.0.0",
96
96
  "@types/jest": "^30.0.0",
97
97
  "@types/node": "^22.15.17",
@@ -192,7 +192,7 @@ export class AvmProvingTester extends PublicTxSimulationTester {
192
192
  gasLimits?: Gas,
193
193
  ) {
194
194
  await this.simProveVerify(
195
- /*sender=*/ AztecAddress.fromNumber(42),
195
+ /*sender=*/ AztecAddress.fromNumberUnsafe(42),
196
196
  /*setupCalls=*/ [],
197
197
  [appCall],
198
198
  undefined,
@@ -19,12 +19,13 @@ import {
19
19
  convertPrivateKernelInnerOutputsFromWitnessMapWithAbi,
20
20
  convertPrivateKernelResetInputsToWitnessMapWithAbi,
21
21
  convertPrivateKernelResetOutputsFromWitnessMapWithAbi,
22
+ convertPrivateKernelResetTailInputsToWitnessMapWithAbi,
23
+ convertPrivateKernelResetTailToPublicInputsToWitnessMapWithAbi,
22
24
  convertPrivateKernelTailForPublicOutputsFromWitnessMapWithAbi,
23
- convertPrivateKernelTailInputsToWitnessMapWithAbi,
24
25
  convertPrivateKernelTailOutputsFromWitnessMapWithAbi,
25
- convertPrivateKernelTailToPublicInputsToWitnessMapWithAbi,
26
26
  foreignCallHandler,
27
27
  getPrivateKernelResetArtifactName,
28
+ getPrivateKernelResetTailArtifactName,
28
29
  updateResetCircuitSampleInputs,
29
30
  } from '@aztec/noir-protocol-circuits-types/client';
30
31
  import {
@@ -47,8 +48,8 @@ import type {
47
48
  PrivateKernelInner3CircuitPrivateInputs,
48
49
  PrivateKernelInnerCircuitPrivateInputs,
49
50
  PrivateKernelResetCircuitPrivateInputs,
51
+ PrivateKernelResetTailCircuitPrivateInputs,
50
52
  PrivateKernelSimulateOutput,
51
- PrivateKernelTailCircuitPrivateInputs,
52
53
  PrivateKernelTailCircuitPublicInputs,
53
54
  } from '@aztec/stdlib/kernel';
54
55
  import type { NoirCompiledCircuitWithName } from '@aztec/stdlib/noir';
@@ -228,40 +229,42 @@ export abstract class BBPrivateKernelProver implements PrivateKernelProver {
228
229
  );
229
230
  }
230
231
 
231
- public async generateTailOutput(
232
- inputs: PrivateKernelTailCircuitPrivateInputs,
232
+ public async generateResetTailOutput(
233
+ inputs: PrivateKernelResetTailCircuitPrivateInputs,
233
234
  ): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
235
+ const artifactName = getPrivateKernelResetTailArtifactName(inputs.dimensions, inputs.isForPublic());
234
236
  if (!inputs.isForPublic()) {
235
237
  return await this.generateCircuitOutput(
236
238
  inputs,
237
- 'PrivateKernelTailArtifact',
238
- convertPrivateKernelTailInputsToWitnessMapWithAbi,
239
+ artifactName,
240
+ convertPrivateKernelResetTailInputsToWitnessMapWithAbi,
239
241
  convertPrivateKernelTailOutputsFromWitnessMapWithAbi,
240
242
  );
241
243
  }
242
244
  return await this.generateCircuitOutput(
243
245
  inputs,
244
- 'PrivateKernelTailToPublicArtifact',
245
- convertPrivateKernelTailToPublicInputsToWitnessMapWithAbi,
246
+ artifactName,
247
+ convertPrivateKernelResetTailToPublicInputsToWitnessMapWithAbi,
246
248
  convertPrivateKernelTailForPublicOutputsFromWitnessMapWithAbi,
247
249
  );
248
250
  }
249
251
 
250
- public async simulateTail(
251
- inputs: PrivateKernelTailCircuitPrivateInputs,
252
+ public async simulateResetTail(
253
+ inputs: PrivateKernelResetTailCircuitPrivateInputs,
252
254
  ): Promise<PrivateKernelSimulateOutput<PrivateKernelTailCircuitPublicInputs>> {
255
+ const artifactName = getPrivateKernelResetTailArtifactName(inputs.dimensions, inputs.isForPublic());
253
256
  if (!inputs.isForPublic()) {
254
257
  return await this.simulateCircuitOutput(
255
258
  inputs,
256
- 'PrivateKernelTailArtifact',
257
- convertPrivateKernelTailInputsToWitnessMapWithAbi,
259
+ artifactName,
260
+ convertPrivateKernelResetTailInputsToWitnessMapWithAbi,
258
261
  convertPrivateKernelTailOutputsFromWitnessMapWithAbi,
259
262
  );
260
263
  }
261
264
  return await this.simulateCircuitOutput(
262
265
  inputs,
263
- 'PrivateKernelTailToPublicArtifact',
264
- convertPrivateKernelTailToPublicInputsToWitnessMapWithAbi,
266
+ artifactName,
267
+ convertPrivateKernelResetTailToPublicInputsToWitnessMapWithAbi,
265
268
  convertPrivateKernelTailForPublicOutputsFromWitnessMapWithAbi,
266
269
  );
267
270
  }
@@ -1,5 +1,5 @@
1
1
  import {
2
- AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
2
+ AVM_V2_PROOF_LENGTH_IN_FIELDS,
3
3
  NESTED_RECURSIVE_PROOF_LENGTH,
4
4
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
5
5
  PAIRING_POINTS_SIZE,
@@ -177,9 +177,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
177
177
  @trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({
178
178
  [Attributes.APP_CIRCUIT_NAME]: inputs.hints.tx.hash,
179
179
  }))
180
- public async getAvmProof(
181
- inputs: AvmCircuitInputs,
182
- ): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
180
+ public async getAvmProof(inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
183
181
  const proof = await this.createAvmProof(inputs);
184
182
  await this.verifyAvmProof(proof.binaryProof, inputs.publicInputs);
185
183
  return proof;
@@ -508,9 +506,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
508
506
  };
509
507
  }
510
508
 
511
- private async createAvmProof(
512
- input: AvmCircuitInputs,
513
- ): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
509
+ private async createAvmProof(input: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
514
510
  logger.info(`Proving avm-circuit for TX ${input.hints.tx.hash}...`);
515
511
 
516
512
  const inputsBuffer = input.serializeWithMessagePack();
@@ -520,20 +516,14 @@ export class BBNativeRollupProver implements ServerCircuitProver {
520
516
  // Convert Uint8Array[] (32-byte field elements) to Fr[]
521
517
  const proofFields = proofFieldArrays.map(f => Fr.fromBuffer(Buffer.from(f)));
522
518
 
523
- // Pad to fixed size (during development the proof length may vary)
524
- if (proofFields.length > AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
525
- throw new Error(
526
- `Proof has ${proofFields.length} fields, expected no more than ${AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED}.`,
527
- );
519
+ if (proofFields.length !== AVM_V2_PROOF_LENGTH_IN_FIELDS) {
520
+ throw new Error(`Proof has ${proofFields.length} fields, expected exactly ${AVM_V2_PROOF_LENGTH_IN_FIELDS}.`);
528
521
  }
529
- const proofFieldsPadded = proofFields.concat(
530
- Array(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED - proofFields.length).fill(new Fr(0)),
531
- );
532
522
 
533
523
  // Build the binary proof from the raw field data
534
524
  const rawProofBuffer = Buffer.concat(proofFieldArrays.map(f => Buffer.from(f)));
535
525
  const binaryProof = new Proof(rawProofBuffer, /*numPublicInputs=*/ 0);
536
- const avmProof = new RecursiveProof(proofFieldsPadded, binaryProof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED);
526
+ const avmProof = new RecursiveProof(proofFields, binaryProof, true, AVM_V2_PROOF_LENGTH_IN_FIELDS);
537
527
 
538
528
  const circuitType = 'avm-circuit' as const;
539
529
  const appCircuitName = 'unknown' as const;
@@ -1,5 +1,5 @@
1
1
  import {
2
- AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
2
+ AVM_V2_PROOF_LENGTH_IN_FIELDS,
3
3
  NESTED_RECURSIVE_PROOF_LENGTH,
4
4
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
5
5
  RECURSIVE_PROOF_LENGTH,
@@ -402,13 +402,11 @@ export class TestCircuitProver implements ServerCircuitProver {
402
402
  );
403
403
  }
404
404
 
405
- public getAvmProof(_inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>> {
405
+ public getAvmProof(_inputs: AvmCircuitInputs): Promise<RecursiveProof<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS>> {
406
406
  // We can't simulate the AVM because we don't have enough context to do so (e.g., DBs).
407
407
  // We just return an empty proof.
408
408
  this.logger.debug('Skipping AVM simulation in TestCircuitProver.');
409
- return this.applyDelay(ProvingRequestType.PUBLIC_VM, () =>
410
- makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED),
411
- );
409
+ return this.applyDelay(ProvingRequestType.PUBLIC_VM, () => makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS));
412
410
  }
413
411
 
414
412
  private async applyDelay<F extends () => any>(type: ProvingRequestType, fn: F): Promise<Awaited<ReturnType<F>>> {