@aztec/bb-prover 0.0.1-commit.9ef841308 → 0.0.1-commit.a5db02d

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 (50) hide show
  1. package/dest/avm_proving_tests/avm_proving_tester.d.ts +9 -5
  2. package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
  3. package/dest/avm_proving_tests/avm_proving_tester.js +147 -105
  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 +385 -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 +7 -2
  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/prover/client/bb_private_kernel_prover.d.ts +12 -4
  19. package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
  20. package/dest/prover/client/bb_private_kernel_prover.js +33 -7
  21. package/dest/prover/proof_utils.d.ts +11 -1
  22. package/dest/prover/proof_utils.d.ts.map +1 -1
  23. package/dest/prover/proof_utils.js +24 -1
  24. package/dest/prover/server/bb_prover.d.ts +6 -7
  25. package/dest/prover/server/bb_prover.d.ts.map +1 -1
  26. package/dest/prover/server/bb_prover.js +210 -79
  27. package/dest/test/test_circuit_prover.d.ts +3 -3
  28. package/dest/test/test_circuit_prover.d.ts.map +1 -1
  29. package/dest/test/test_circuit_prover.js +2 -2
  30. package/dest/verification_key/verification_key_data.js +1 -1
  31. package/dest/verifier/bb_verifier.d.ts +4 -1
  32. package/dest/verifier/bb_verifier.d.ts.map +1 -1
  33. package/dest/verifier/bb_verifier.js +134 -45
  34. package/package.json +18 -17
  35. package/src/avm_proving_tests/avm_proving_tester.ts +46 -127
  36. package/src/bb/bb_js_backend.ts +441 -0
  37. package/src/bb/bb_js_debug.ts +227 -0
  38. package/src/bb/file_names.ts +6 -0
  39. package/src/config.ts +6 -1
  40. package/src/index.ts +2 -1
  41. package/src/prover/client/bb_private_kernel_prover.ts +118 -15
  42. package/src/prover/proof_utils.ts +41 -1
  43. package/src/prover/server/bb_prover.ts +130 -141
  44. package/src/test/test_circuit_prover.ts +3 -5
  45. package/src/verification_key/verification_key_data.ts +1 -1
  46. package/src/verifier/bb_verifier.ts +66 -76
  47. package/dest/bb/execute.d.ts +0 -108
  48. package/dest/bb/execute.d.ts.map +0 -1
  49. package/dest/bb/execute.js +0 -652
  50. package/src/bb/execute.ts +0 -687
@@ -1,22 +1,92 @@
1
- import { runInDirectory } from '@aztec/foundation/fs';
1
+ function _ts_add_disposable_resource(env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() {
16
+ try {
17
+ inner.call(this);
18
+ } catch (e) {
19
+ return Promise.reject(e);
20
+ }
21
+ };
22
+ env.stack.push({
23
+ value: value,
24
+ dispose: dispose,
25
+ async: async
26
+ });
27
+ } else if (async) {
28
+ env.stack.push({
29
+ async: true
30
+ });
31
+ }
32
+ return value;
33
+ }
34
+ function _ts_dispose_resources(env) {
35
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
36
+ var e = new Error(message);
37
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
38
+ };
39
+ return (_ts_dispose_resources = function _ts_dispose_resources(env) {
40
+ function fail(e) {
41
+ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
42
+ env.hasError = true;
43
+ }
44
+ var r, s = 0;
45
+ function next() {
46
+ while(r = env.stack.pop()){
47
+ try {
48
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
49
+ if (r.dispose) {
50
+ var result = r.dispose.call(r.value);
51
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
52
+ fail(e);
53
+ return next();
54
+ });
55
+ } else s |= 1;
56
+ } catch (e) {
57
+ fail(e);
58
+ }
59
+ }
60
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
61
+ if (env.hasError) throw env.error;
62
+ }
63
+ return next();
64
+ })(env);
65
+ }
2
66
  import { createLogger } from '@aztec/foundation/log';
3
67
  import { Timer } from '@aztec/foundation/timer';
4
68
  import { ProtocolCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
5
69
  import { mapProtocolArtifactNameToCircuitName } from '@aztec/noir-protocol-circuits-types/types';
6
70
  import { promises as fs } from 'fs';
7
- import * as path from 'path';
8
- import { BB_RESULT, PROOF_FILENAME, PUBLIC_INPUTS_FILENAME, VK_FILENAME, verifyChonkProof, verifyProof } from '../bb/execute.js';
71
+ import { BBJsFactory } from '../bb/bb_js_backend.js';
9
72
  import { getUltraHonkFlavorForCircuit } from '../honk.js';
10
- import { writeChonkProofToPath } from '../prover/proof_utils.js';
11
73
  export class BBCircuitVerifier {
12
74
  config;
13
75
  logger;
76
+ bbJsFactory;
14
77
  constructor(config, logger){
15
78
  this.config = config;
16
79
  this.logger = logger;
80
+ // BB_NUM_IVC_VERIFIERS bounds the number of long-lived bb processes the pool keeps alive.
81
+ // If 0, fall back to spawning a fresh bb per verification.
82
+ this.bbJsFactory = new BBJsFactory(config.bbBinaryPath, {
83
+ poolSize: config.numConcurrentIVCVerifiers > 0 ? config.numConcurrentIVCVerifiers : undefined,
84
+ logger,
85
+ debugDir: config.bbDebugOutputDir
86
+ });
17
87
  }
18
88
  stop() {
19
- return Promise.resolve();
89
+ return this.bbJsFactory.destroy();
20
90
  }
21
91
  static async new(config, logger = createLogger('bb-prover:verifier')) {
22
92
  if (!config.bbWorkingDirectory) {
@@ -34,64 +104,76 @@ export class BBCircuitVerifier {
34
104
  }
35
105
  return vk;
36
106
  }
37
- async verifyProofForCircuit(circuit, proof) {
38
- const operation = async (bbWorkingDirectory)=>{
39
- const publicInputsFileName = path.join(bbWorkingDirectory, PUBLIC_INPUTS_FILENAME);
40
- const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME);
41
- const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
107
+ /** Verify an UltraHonk proof via bb.js API (no temp files). */ async verifyProofForCircuit(circuit, proof) {
108
+ const env = {
109
+ stack: [],
110
+ error: void 0,
111
+ hasError: false
112
+ };
113
+ try {
42
114
  const verificationKey = this.getVerificationKeyData(circuit);
115
+ const flavor = getUltraHonkFlavorForCircuit(circuit);
43
116
  this.logger.debug(`${circuit} Verifying with key: ${verificationKey.keyAsFields.hash.toString()}`);
44
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/13189): Put this proof parsing logic in the proof class.
45
- await fs.writeFile(publicInputsFileName, proof.buffer.slice(0, proof.numPublicInputs * 32));
46
- await fs.writeFile(proofFileName, proof.buffer.slice(proof.numPublicInputs * 32));
47
- await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
48
- const result = await verifyProof(this.config.bbBinaryPath, proofFileName, verificationKeyPath, getUltraHonkFlavorForCircuit(circuit), this.logger);
49
- if (result.status === BB_RESULT.FAILURE) {
50
- const errorMessage = `Failed to verify ${circuit} proof!`;
51
- throw new Error(errorMessage);
117
+ // Split proof buffer into public input fields and proof fields (32-byte each)
118
+ const publicInputFields = splitBufferToFieldArrays(proof.buffer.subarray(0, proof.numPublicInputs * 32));
119
+ const proofFields = splitBufferToFieldArrays(proof.buffer.subarray(proof.numPublicInputs * 32));
120
+ const instance = _ts_add_disposable_resource(env, await this.bbJsFactory.getInstance(), true);
121
+ const { verified, durationMs } = await instance.verifyProof(proofFields, verificationKey.keyAsBytes, publicInputFields, flavor);
122
+ if (!verified) {
123
+ throw new Error(`Failed to verify ${circuit} proof!`);
52
124
  }
53
125
  this.logger.debug(`${circuit} verification successful`, {
54
126
  circuitName: mapProtocolArtifactNameToCircuitName(circuit),
55
- duration: result.durationMs,
127
+ duration: durationMs,
56
128
  eventName: 'circuit-verification',
57
129
  proofType: 'ultra-honk'
58
130
  });
59
- };
60
- await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup, this.logger);
131
+ } catch (e) {
132
+ env.error = e;
133
+ env.hasError = true;
134
+ } finally{
135
+ const result = _ts_dispose_resources(env);
136
+ if (result) await result;
137
+ }
61
138
  }
62
- async verifyProof(tx) {
139
+ /** Verify a Chonk (IVC) proof from a transaction via bb.js API. */ async verifyProof(tx) {
63
140
  const proofType = 'Chonk';
64
141
  try {
65
- const totalTimer = new Timer();
66
- let verificationDuration = 0;
67
- const circuit = tx.data.forPublic ? 'HidingKernelToPublic' : 'HidingKernelToRollup';
68
- // Block below is almost copy-pasted from verifyProofForCircuit
69
- const operation = async (bbWorkingDirectory)=>{
70
- const proofPath = path.join(bbWorkingDirectory, PROOF_FILENAME);
71
- await writeChonkProofToPath(tx.chonkProof.attachPublicInputs(tx.data.publicInputs().toFields()), proofPath);
72
- const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME);
142
+ const env = {
143
+ stack: [],
144
+ error: void 0,
145
+ hasError: false
146
+ };
147
+ try {
148
+ const totalTimer = new Timer();
149
+ const circuit = tx.data.forPublic ? 'HidingKernelToPublic' : 'HidingKernelToRollup';
73
150
  const verificationKey = this.getVerificationKeyData(circuit);
74
- await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
75
- const timer = new Timer();
76
- const result = await verifyChonkProof(this.config.bbBinaryPath, proofPath, verificationKeyPath, this.logger, this.config.bbIVCConcurrency);
77
- verificationDuration = timer.ms();
78
- if (result.status === BB_RESULT.FAILURE) {
79
- const errorMessage = `Failed to verify ${proofType} proof for ${circuit}!`;
80
- throw new Error(errorMessage);
151
+ // Reconstruct the full proof with public inputs prepended, then convert Fr[] to Uint8Array[]
152
+ const proofWithPubInputs = tx.chonkProof.attachPublicInputs(tx.data.publicInputs().toFields());
153
+ const fieldsAsBuffers = proofWithPubInputs.fieldsWithPublicInputs.map((f)=>new Uint8Array(f.toBuffer()));
154
+ const instance = _ts_add_disposable_resource(env, await this.bbJsFactory.getInstance(), true);
155
+ const { verified, durationMs } = await instance.verifyChonkProof(fieldsAsBuffers, verificationKey.keyAsBytes);
156
+ if (!verified) {
157
+ throw new Error(`Failed to verify ${proofType} proof for ${circuit}!`);
81
158
  }
82
159
  this.logger.debug(`${proofType} verification successful`, {
83
160
  circuitName: mapProtocolArtifactNameToCircuitName(circuit),
84
- duration: result.durationMs,
161
+ duration: durationMs,
85
162
  eventName: 'circuit-verification',
86
163
  proofType: 'chonk'
87
164
  });
88
- };
89
- await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup, this.logger);
90
- return {
91
- valid: true,
92
- durationMs: verificationDuration,
93
- totalDurationMs: totalTimer.ms()
94
- };
165
+ return {
166
+ valid: true,
167
+ durationMs,
168
+ totalDurationMs: totalTimer.ms()
169
+ };
170
+ } catch (e) {
171
+ env.error = e;
172
+ env.hasError = true;
173
+ } finally{
174
+ const result = _ts_dispose_resources(env);
175
+ if (result) await result;
176
+ }
95
177
  } catch (err) {
96
178
  this.logger.warn(`Failed to verify ${proofType} proof for tx ${tx.getTxHash().toString()}: ${String(err)}`);
97
179
  return {
@@ -102,3 +184,10 @@ export class BBCircuitVerifier {
102
184
  }
103
185
  }
104
186
  }
187
+ /** Split a buffer into 32-byte Uint8Array field elements. */ function splitBufferToFieldArrays(buffer) {
188
+ const fields = [];
189
+ for(let i = 0; i < buffer.length; i += 32){
190
+ fields.push(new Uint8Array(buffer.subarray(i, i + 32)));
191
+ }
192
+ return fields;
193
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/bb-prover",
3
- "version": "0.0.1-commit.9ef841308",
3
+ "version": "0.0.1-commit.a5db02d",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -9,7 +9,8 @@
9
9
  "./client": "./dest/prover/client/bb_private_kernel_prover.js",
10
10
  "./verifier": "./dest/verifier/index.js",
11
11
  "./test": "./dest/test/index.js",
12
- "./config": "./dest/config.js"
12
+ "./config": "./dest/config.js",
13
+ "./debug": "./dest/bb/bb_js_debug.js"
13
14
  },
14
15
  "bin": {
15
16
  "bb-cli": "./dest/bb/index.js"
@@ -69,16 +70,16 @@
69
70
  ]
70
71
  },
71
72
  "dependencies": {
72
- "@aztec/bb.js": "0.0.1-commit.9ef841308",
73
- "@aztec/constants": "0.0.1-commit.9ef841308",
74
- "@aztec/foundation": "0.0.1-commit.9ef841308",
75
- "@aztec/noir-noirc_abi": "0.0.1-commit.9ef841308",
76
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.9ef841308",
77
- "@aztec/noir-types": "0.0.1-commit.9ef841308",
78
- "@aztec/simulator": "0.0.1-commit.9ef841308",
79
- "@aztec/stdlib": "0.0.1-commit.9ef841308",
80
- "@aztec/telemetry-client": "0.0.1-commit.9ef841308",
81
- "@aztec/world-state": "0.0.1-commit.9ef841308",
73
+ "@aztec/bb.js": "0.0.1-commit.a5db02d",
74
+ "@aztec/constants": "0.0.1-commit.a5db02d",
75
+ "@aztec/foundation": "0.0.1-commit.a5db02d",
76
+ "@aztec/noir-noirc_abi": "0.0.1-commit.a5db02d",
77
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.a5db02d",
78
+ "@aztec/noir-types": "0.0.1-commit.a5db02d",
79
+ "@aztec/simulator": "0.0.1-commit.a5db02d",
80
+ "@aztec/stdlib": "0.0.1-commit.a5db02d",
81
+ "@aztec/telemetry-client": "0.0.1-commit.a5db02d",
82
+ "@aztec/world-state": "0.0.1-commit.a5db02d",
82
83
  "commander": "^12.1.0",
83
84
  "msgpackr": "^1.11.2",
84
85
  "pako": "^2.1.0",
@@ -86,11 +87,11 @@
86
87
  "tslib": "^2.4.0"
87
88
  },
88
89
  "devDependencies": {
89
- "@aztec/ethereum": "0.0.1-commit.9ef841308",
90
- "@aztec/kv-store": "0.0.1-commit.9ef841308",
91
- "@aztec/noir-contracts.js": "0.0.1-commit.9ef841308",
92
- "@aztec/noir-test-contracts.js": "0.0.1-commit.9ef841308",
93
- "@aztec/protocol-contracts": "0.0.1-commit.9ef841308",
90
+ "@aztec/ethereum": "0.0.1-commit.a5db02d",
91
+ "@aztec/kv-store": "0.0.1-commit.a5db02d",
92
+ "@aztec/noir-contracts.js": "0.0.1-commit.a5db02d",
93
+ "@aztec/noir-test-contracts.js": "0.0.1-commit.a5db02d",
94
+ "@aztec/protocol-contracts": "0.0.1-commit.a5db02d",
94
95
  "@jest/globals": "^30.0.0",
95
96
  "@types/jest": "^30.0.0",
96
97
  "@types/node": "^22.15.17",
@@ -1,4 +1,4 @@
1
- import type { LogFn, LogLevel, Logger } from '@aztec/foundation/log';
1
+ import type { AvmStat } from '@aztec/bb.js';
2
2
  import { Timer } from '@aztec/foundation/timer';
3
3
  import {
4
4
  PublicTxSimulationTester,
@@ -15,77 +15,12 @@ import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server'
15
15
  import type { GlobalVariables } from '@aztec/stdlib/tx';
16
16
  import { NativeWorldStateService } from '@aztec/world-state';
17
17
 
18
- import fs from 'node:fs/promises';
19
- import { tmpdir } from 'node:os';
20
18
  import path from 'path';
21
19
 
22
- import { type BBResult, type BBSuccess, BB_RESULT, generateAvmProof, verifyAvmProof } from '../bb/execute.js';
20
+ import { BBJsFactory } from '../bb/bb_js_backend.js';
23
21
 
24
22
  const BB_PATH = path.resolve('../../barretenberg/cpp/build/bin/bb-avm');
25
23
 
26
- // An InterceptingLogger that records all log messages and forwards them to a wrapped logger.
27
- class InterceptingLogger implements Logger {
28
- public readonly logs: string[] = [];
29
- public level: LogLevel;
30
- public module: string;
31
-
32
- private logger: Logger;
33
-
34
- constructor(logger: Logger) {
35
- this.logger = logger;
36
- this.level = logger.level;
37
- this.module = logger.module;
38
- }
39
-
40
- isLevelEnabled(level: LogLevel): boolean {
41
- return this.logger.isLevelEnabled(level);
42
- }
43
-
44
- createChild(_childModule: string): Logger {
45
- throw new Error('Not implemented');
46
- }
47
-
48
- getBindings() {
49
- return this.logger.getBindings();
50
- }
51
-
52
- private intercept(level: LogLevel, msg: string, ...args: any[]) {
53
- this.logs.push(...msg.split('\n'));
54
- // Forward to the wrapped logger
55
- (this.logger[level] as LogFn)(msg, ...args);
56
- }
57
-
58
- // Log methods for each level
59
- silent(msg: string, ...args: any[]) {
60
- this.intercept('silent', msg, ...args);
61
- }
62
- fatal(msg: string, ...args: any[]) {
63
- this.intercept('fatal', msg, ...args);
64
- }
65
- warn(msg: string, ...args: any[]) {
66
- this.intercept('warn', msg, ...args);
67
- }
68
- info(msg: string, ...args: any[]) {
69
- this.intercept('info', msg, ...args);
70
- }
71
- verbose(msg: string, ...args: any[]) {
72
- this.intercept('verbose', msg, ...args);
73
- }
74
- debug(msg: string, ...args: any[]) {
75
- this.intercept('debug', msg, ...args);
76
- }
77
- trace(msg: string, ...args: any[]) {
78
- this.intercept('trace', msg, ...args);
79
- }
80
-
81
- // Error log function can be string or Error
82
- error(err: Error | string, ...args: any[]) {
83
- const msg = typeof err === 'string' ? err : err.message;
84
- this.logs.push(msg);
85
- this.logger.error(msg, err, ...args);
86
- }
87
- }
88
-
89
24
  // Config with collectHints enabled for proving tests
90
25
  const provingConfig: PublicSimulatorConfig = PublicSimulatorConfig.from({
91
26
  skipFeeEnforcement: false,
@@ -97,7 +32,7 @@ const provingConfig: PublicSimulatorConfig = PublicSimulatorConfig.from({
97
32
  });
98
33
 
99
34
  export class AvmProvingTester extends PublicTxSimulationTester {
100
- private bbWorkingDirectory: string = '';
35
+ private readonly bbJsFactory = new BBJsFactory(BB_PATH);
101
36
 
102
37
  constructor(
103
38
  private checkCircuitOnly: boolean,
@@ -121,53 +56,57 @@ export class AvmProvingTester extends PublicTxSimulationTester {
121
56
  return new AvmProvingTester(checkCircuitOnly, contractDataSource, merkleTrees, globals, metrics);
122
57
  }
123
58
 
124
- async prove(avmCircuitInputs: AvmCircuitInputs, txLabel: string = 'unlabeledTx'): Promise<BBResult> {
125
- // We use a new working directory for each proof.
126
- this.bbWorkingDirectory = await fs.mkdtemp(path.join(tmpdir(), 'bb-'));
59
+ /**
60
+ * Generate an AVM proof (or run check-circuit if configured). Records per-stage timings in the test metrics.
61
+ * Returns the in-memory proof fields on success; throws via jest expect() on failure.
62
+ */
63
+ async prove(avmCircuitInputs: AvmCircuitInputs, txLabel: string = 'unlabeledTx'): Promise<Uint8Array[]> {
64
+ const inputsBuffer = avmCircuitInputs.serializeWithMessagePack();
127
65
 
128
- const interceptingLogger = new InterceptingLogger(this.logger);
66
+ if (this.checkCircuitOnly) {
67
+ await using instance = await this.bbJsFactory.getInstance();
68
+ const { passed, stats } = await instance.checkAvmCircuit(inputsBuffer);
69
+ this.recordProverMetrics(stats, txLabel);
70
+ expect(passed).toBe(true);
71
+ return [];
72
+ }
129
73
 
130
- // Then we prove.
131
- const proofRes = await generateAvmProof(
132
- BB_PATH,
133
- this.bbWorkingDirectory,
134
- avmCircuitInputs,
135
- interceptingLogger,
136
- this.checkCircuitOnly,
137
- );
138
- if (proofRes.status === BB_RESULT.FAILURE) {
139
- this.logger.error(`Proof generation failed: ${proofRes.reason}`);
74
+ await using instance = await this.bbJsFactory.getInstance();
75
+ const { proof, stats } = await instance.generateAvmProof(inputsBuffer);
76
+ this.recordProverMetrics(stats, txLabel);
77
+ return proof;
78
+ }
79
+
80
+ async verify(proof: Uint8Array[], publicInputs: AvmCircuitPublicInputs): Promise<void> {
81
+ if (this.checkCircuitOnly) {
82
+ // Check-circuit did not generate a proof; nothing to verify.
83
+ return;
140
84
  }
141
- expect(proofRes.status).toEqual(BB_RESULT.SUCCESS);
85
+ const piBuffer = publicInputs.serializeWithMessagePack();
86
+ await using instance = await this.bbJsFactory.getInstance();
87
+ const { verified } = await instance.verifyAvmProof(proof, piBuffer);
88
+ expect(verified).toBe(true);
89
+ }
142
90
 
143
- // Parse the logs into a structured format.
144
- const logs = interceptingLogger.logs;
145
- // const traceSizes: { name: string; size: number }[] = [];
146
- // logs.forEach(log => {
147
- // const match = log.match(/\b(\w+): (\d+) \(~2/);
148
- // if (match) {
149
- // traceSizes.push({
150
- // name: match[1],
151
- // size: parseInt(match[2]),
152
- // });
153
- // }
154
- // });
155
- const times: { [key: string]: number } = {};
156
- logs.forEach(log => {
157
- const match = log.match(/\b([\w/]+)_ms: (\d+)/);
158
- if (match) {
159
- times[match[1]] = parseInt(match[2]);
160
- }
161
- });
91
+ public async proveVerify(avmCircuitInputs: AvmCircuitInputs, txLabel: string = 'unlabeledTx') {
92
+ const proof = await this.prove(avmCircuitInputs, txLabel);
93
+ await this.verify(proof, avmCircuitInputs.publicInputs);
94
+ }
162
95
 
163
- // Throw if logs did not contain any times.
96
+ private recordProverMetrics(stats: AvmStat[], txLabel: string) {
97
+ // Build a lookup keyed on the stage name with the `_ms` suffix stripped, matching the legacy
98
+ // stdout-scraped shape. bb::avm2::Stats::time() stores keys with `_ms` appended.
99
+ const times: { [key: string]: number } = {};
100
+ for (const { name, valueMs } of stats) {
101
+ const key = name.endsWith('_ms') ? name.slice(0, -'_ms'.length) : name;
102
+ times[key] = valueMs;
103
+ }
164
104
  if (Object.keys(times).length === 0) {
165
- throw new Error('AVM stdout did not contain any proving times in the stats!');
105
+ throw new Error('AVM response did not contain any proving-stage timings!');
166
106
  }
167
-
168
107
  // Hack to make labels match.
169
108
  const txLabelWithCount = `${txLabel}/${this.txCount - 1}`;
170
- // I need to cast because TS doesnt realize metrics is protected not private.
109
+ // Cast because TS doesn't realize `metrics` is protected, not private on the parent class.
171
110
  (this as any).metrics?.recordProverMetrics(txLabelWithCount, {
172
111
  proverSimulationStepMs: times['simulation/all'],
173
112
  proverProvingStepMs: times['proving/all'],
@@ -180,26 +119,6 @@ export class AvmProvingTester extends PublicTxSimulationTester {
180
119
  provingLogDerivativeInverseCommitmentsMs: times['prove/log_derivative_inverse_commitments_round'],
181
120
  provingWireCommitmentsMs: times['prove/wire_commitments_round'],
182
121
  });
183
-
184
- return proofRes as BBSuccess;
185
- }
186
-
187
- async verify(proofRes: BBSuccess, publicInputs: AvmCircuitPublicInputs): Promise<BBResult> {
188
- if (this.checkCircuitOnly) {
189
- // Skip verification if we are only checking the circuit.
190
- // Check-circuit does not generate a proof to verify.
191
- return proofRes;
192
- }
193
-
194
- return await verifyAvmProof(BB_PATH, this.bbWorkingDirectory, proofRes.proofPath!, publicInputs, this.logger);
195
- }
196
-
197
- public async proveVerify(avmCircuitInputs: AvmCircuitInputs, txLabel: string = 'unlabeledTx') {
198
- const provingRes = await this.prove(avmCircuitInputs, txLabel);
199
- expect(provingRes.status).toEqual(BB_RESULT.SUCCESS);
200
-
201
- const verificationRes = await this.verify(provingRes as BBSuccess, avmCircuitInputs.publicInputs);
202
- expect(verificationRes.status).toBe(BB_RESULT.SUCCESS);
203
122
  }
204
123
 
205
124
  public async simProveVerify(
@@ -273,7 +192,7 @@ export class AvmProvingTester extends PublicTxSimulationTester {
273
192
  gasLimits?: Gas,
274
193
  ) {
275
194
  await this.simProveVerify(
276
- /*sender=*/ AztecAddress.fromNumber(42),
195
+ /*sender=*/ AztecAddress.fromNumberUnsafe(42),
277
196
  /*setupCalls=*/ [],
278
197
  [appCall],
279
198
  undefined,