@aztec/bb-prover 0.0.1-commit.3fd054f6 → 0.0.1-commit.431c48d
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.
- package/dest/avm_proving_tests/avm_proving_tester.d.ts +9 -5
- package/dest/avm_proving_tests/avm_proving_tester.d.ts.map +1 -1
- package/dest/avm_proving_tests/avm_proving_tester.js +147 -105
- package/dest/bb/bb_js_backend.d.ts +196 -0
- package/dest/bb/bb_js_backend.d.ts.map +1 -0
- package/dest/bb/bb_js_backend.js +385 -0
- package/dest/bb/bb_js_debug.d.ts +52 -0
- package/dest/bb/bb_js_debug.d.ts.map +1 -0
- package/dest/bb/bb_js_debug.js +176 -0
- package/dest/bb/file_names.d.ts +4 -0
- package/dest/bb/file_names.d.ts.map +1 -0
- package/dest/bb/file_names.js +5 -0
- package/dest/config.d.ts +7 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/index.d.ts +3 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -1
- package/dest/prover/client/bb_private_kernel_prover.d.ts +12 -4
- package/dest/prover/client/bb_private_kernel_prover.d.ts.map +1 -1
- package/dest/prover/client/bb_private_kernel_prover.js +46 -10
- package/dest/prover/proof_utils.d.ts +11 -1
- package/dest/prover/proof_utils.d.ts.map +1 -1
- package/dest/prover/proof_utils.js +24 -1
- package/dest/prover/server/bb_prover.d.ts +6 -7
- package/dest/prover/server/bb_prover.d.ts.map +1 -1
- package/dest/prover/server/bb_prover.js +210 -79
- package/dest/test/test_circuit_prover.d.ts +3 -3
- package/dest/test/test_circuit_prover.d.ts.map +1 -1
- package/dest/test/test_circuit_prover.js +2 -2
- package/dest/verification_key/verification_key_data.js +1 -1
- package/dest/verifier/batch_chonk_verifier.d.ts +2 -1
- package/dest/verifier/batch_chonk_verifier.d.ts.map +1 -1
- package/dest/verifier/batch_chonk_verifier.js +5 -0
- package/dest/verifier/bb_verifier.d.ts +4 -1
- package/dest/verifier/bb_verifier.d.ts.map +1 -1
- package/dest/verifier/bb_verifier.js +134 -45
- package/dest/verifier/queued_chonk_verifier.d.ts +13 -1
- package/dest/verifier/queued_chonk_verifier.d.ts.map +1 -1
- package/dest/verifier/queued_chonk_verifier.js +1 -1
- package/package.json +18 -17
- package/src/avm_proving_tests/avm_proving_tester.ts +46 -127
- package/src/bb/bb_js_backend.ts +441 -0
- package/src/bb/bb_js_debug.ts +227 -0
- package/src/bb/file_names.ts +6 -0
- package/src/config.ts +6 -1
- package/src/index.ts +2 -1
- package/src/prover/client/bb_private_kernel_prover.ts +133 -18
- package/src/prover/proof_utils.ts +41 -1
- package/src/prover/server/bb_prover.ts +130 -141
- package/src/test/test_circuit_prover.ts +3 -5
- package/src/verification_key/verification_key_data.ts +1 -1
- package/src/verifier/batch_chonk_verifier.ts +5 -0
- package/src/verifier/bb_verifier.ts +66 -76
- package/src/verifier/queued_chonk_verifier.ts +2 -1
- package/dest/bb/execute.d.ts +0 -108
- package/dest/bb/execute.d.ts.map +0 -1
- package/dest/bb/execute.js +0 -652
- package/src/bb/execute.ts +0 -687
|
@@ -1,22 +1,92 @@
|
|
|
1
|
-
|
|
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
|
|
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
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
await
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
|
|
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:
|
|
127
|
+
duration: durationMs,
|
|
56
128
|
eventName: 'circuit-verification',
|
|
57
129
|
proofType: 'ultra-honk'
|
|
58
130
|
});
|
|
59
|
-
}
|
|
60
|
-
|
|
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
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
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
|
-
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
throw new Error(
|
|
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:
|
|
161
|
+
duration: durationMs,
|
|
85
162
|
eventName: 'circuit-verification',
|
|
86
163
|
proofType: 'chonk'
|
|
87
164
|
});
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
+
}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import type { ClientProtocolCircuitVerifier, IVCProofVerificationResult } from '@aztec/stdlib/interfaces/server';
|
|
2
2
|
import type { Tx } from '@aztec/stdlib/tx';
|
|
3
3
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
4
|
+
/** Records verification timing and failure metrics for an IVC (chonk) proof verifier. */
|
|
5
|
+
export declare class IVCVerifierMetrics {
|
|
6
|
+
private ivcVerificationHistogram;
|
|
7
|
+
private ivcTotalVerificationHistogram;
|
|
8
|
+
private ivcFailureCount;
|
|
9
|
+
private localHistogramOk;
|
|
10
|
+
private localHistogramFails;
|
|
11
|
+
private aggDurationMetrics;
|
|
12
|
+
constructor(client: TelemetryClient, name?: string);
|
|
13
|
+
recordIVCVerification(result: IVCProofVerificationResult): void;
|
|
14
|
+
private aggregate;
|
|
15
|
+
}
|
|
4
16
|
export declare class QueuedIVCVerifier implements ClientProtocolCircuitVerifier {
|
|
5
17
|
private verifier;
|
|
6
18
|
private telemetry;
|
|
@@ -11,4 +23,4 @@ export declare class QueuedIVCVerifier implements ClientProtocolCircuitVerifier
|
|
|
11
23
|
verifyProof(tx: Tx): Promise<IVCProofVerificationResult>;
|
|
12
24
|
stop(): Promise<void>;
|
|
13
25
|
}
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVldWVkX2Nob25rX3ZlcmlmaWVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdmVyaWZpZXIvcXVldWVkX2Nob25rX3ZlcmlmaWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLDZCQUE2QixFQUFFLDBCQUEwQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDakgsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDM0MsT0FBTyxFQU1MLEtBQUssZUFBZSxFQUlyQixNQUFNLHlCQUF5QixDQUFDO0FBSWpDLHlGQUF5RjtBQUN6RixxQkFBYSxrQkFBa0I7SUFDN0IsT0FBTyxDQUFDLHdCQUF3QixDQUFZO0lBQzVDLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBWTtJQUNqRCxPQUFPLENBQUMsZUFBZSxDQUFnQjtJQUN2QyxPQUFPLENBQUMsZ0JBQWdCLENBR3JCO0lBQ0gsT0FBTyxDQUFDLG1CQUFtQixDQUd4QjtJQUVILE9BQU8sQ0FBQyxrQkFBa0IsQ0FBaUU7SUFFM0YsWUFBWSxNQUFNLEVBQUUsZUFBZSxFQUFFLElBQUksU0FBc0IsRUFrQjlEO0lBRUQscUJBQXFCLENBQUMsTUFBTSxFQUFFLDBCQUEwQixRQVN2RDtJQUVELE9BQU8sQ0FBQyxTQUFTLENBY2Y7Q0FDSDtBQUVELHFCQUFhLGlCQUFrQixZQUFXLDZCQUE2QjtJQUtuRSxPQUFPLENBQUMsUUFBUTtJQUVoQixPQUFPLENBQUMsU0FBUztJQUNqQixPQUFPLENBQUMsTUFBTTtJQVBoQixPQUFPLENBQUMsS0FBSyxDQUFjO0lBQzNCLE9BQU8sQ0FBQyxPQUFPLENBQXFCO0lBRXBDLFlBQ1UsUUFBUSxFQUFFLDZCQUE2QixFQUMvQyxXQUFXLEVBQUUsTUFBTSxFQUNYLFNBQVMsR0FBRSxlQUFzQyxFQUNqRCxNQUFNLHlDQUFrRCxFQU1qRTtJQUVZLFdBQVcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUlwRTtJQUVLLElBQUksSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBRzFCO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queued_chonk_verifier.d.ts","sourceRoot":"","sources":["../../src/verifier/queued_chonk_verifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AACjH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAML,KAAK,eAAe,EAIrB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"queued_chonk_verifier.d.ts","sourceRoot":"","sources":["../../src/verifier/queued_chonk_verifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AACjH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAML,KAAK,eAAe,EAIrB,MAAM,yBAAyB,CAAC;AAIjC,yFAAyF;AACzF,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,wBAAwB,CAAY;IAC5C,OAAO,CAAC,6BAA6B,CAAY;IACjD,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,gBAAgB,CAGrB;IACH,OAAO,CAAC,mBAAmB,CAGxB;IAEH,OAAO,CAAC,kBAAkB,CAAiE;IAE3F,YAAY,MAAM,EAAE,eAAe,EAAE,IAAI,SAAsB,EAkB9D;IAED,qBAAqB,CAAC,MAAM,EAAE,0BAA0B,QASvD;IAED,OAAO,CAAC,SAAS,CAcf;CACH;AAED,qBAAa,iBAAkB,YAAW,6BAA6B;IAKnE,OAAO,CAAC,QAAQ;IAEhB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAqB;IAEpC,YACU,QAAQ,EAAE,6BAA6B,EAC/C,WAAW,EAAE,MAAM,EACX,SAAS,GAAE,eAAsC,EACjD,MAAM,yCAAkD,EAMjE;IAEY,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAIpE;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1B;CACF"}
|
|
@@ -2,7 +2,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
2
2
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
3
3
|
import { Attributes, Metrics, createUpDownCounterWithDefault, getTelemetryClient } from '@aztec/telemetry-client';
|
|
4
4
|
import { createHistogram } from 'node:perf_hooks';
|
|
5
|
-
class IVCVerifierMetrics {
|
|
5
|
+
/** Records verification timing and failure metrics for an IVC (chonk) proof verifier. */ export class IVCVerifierMetrics {
|
|
6
6
|
ivcVerificationHistogram;
|
|
7
7
|
ivcTotalVerificationHistogram;
|
|
8
8
|
ivcFailureCount;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/bb-prover",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.431c48d",
|
|
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.
|
|
73
|
-
"@aztec/constants": "0.0.1-commit.
|
|
74
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
75
|
-
"@aztec/noir-noirc_abi": "0.0.1-commit.
|
|
76
|
-
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.
|
|
77
|
-
"@aztec/noir-types": "0.0.1-commit.
|
|
78
|
-
"@aztec/simulator": "0.0.1-commit.
|
|
79
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
80
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
81
|
-
"@aztec/world-state": "0.0.1-commit.
|
|
73
|
+
"@aztec/bb.js": "0.0.1-commit.431c48d",
|
|
74
|
+
"@aztec/constants": "0.0.1-commit.431c48d",
|
|
75
|
+
"@aztec/foundation": "0.0.1-commit.431c48d",
|
|
76
|
+
"@aztec/noir-noirc_abi": "0.0.1-commit.431c48d",
|
|
77
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.431c48d",
|
|
78
|
+
"@aztec/noir-types": "0.0.1-commit.431c48d",
|
|
79
|
+
"@aztec/simulator": "0.0.1-commit.431c48d",
|
|
80
|
+
"@aztec/stdlib": "0.0.1-commit.431c48d",
|
|
81
|
+
"@aztec/telemetry-client": "0.0.1-commit.431c48d",
|
|
82
|
+
"@aztec/world-state": "0.0.1-commit.431c48d",
|
|
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.
|
|
90
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
91
|
-
"@aztec/noir-contracts.js": "0.0.1-commit.
|
|
92
|
-
"@aztec/noir-test-contracts.js": "0.0.1-commit.
|
|
93
|
-
"@aztec/protocol-contracts": "0.0.1-commit.
|
|
90
|
+
"@aztec/ethereum": "0.0.1-commit.431c48d",
|
|
91
|
+
"@aztec/kv-store": "0.0.1-commit.431c48d",
|
|
92
|
+
"@aztec/noir-contracts.js": "0.0.1-commit.431c48d",
|
|
93
|
+
"@aztec/noir-test-contracts.js": "0.0.1-commit.431c48d",
|
|
94
|
+
"@aztec/protocol-contracts": "0.0.1-commit.431c48d",
|
|
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 {
|
|
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 {
|
|
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
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
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.
|
|
195
|
+
/*sender=*/ AztecAddress.fromNumberUnsafe(42),
|
|
277
196
|
/*setupCalls=*/ [],
|
|
278
197
|
[appCall],
|
|
279
198
|
undefined,
|