@aztec-labs/bb-prover 6.0.0-rc.1 → 6.0.0-rc.2
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/bb/bb_js_backend.d.ts +29 -19
- package/dest/bb/bb_js_backend.d.ts.map +1 -1
- package/dest/bb/bb_js_backend.js +54 -72
- package/dest/prover/server/bb_prover.d.ts +1 -1
- package/dest/prover/server/bb_prover.d.ts.map +1 -1
- package/dest/prover/server/bb_prover.js +3 -2
- package/dest/test/fake_bb_js.d.ts +66 -0
- package/dest/test/fake_bb_js.d.ts.map +1 -0
- package/dest/test/fake_bb_js.js +111 -0
- package/dest/verifier/bb_verifier.d.ts +14 -3
- package/dest/verifier/bb_verifier.d.ts.map +1 -1
- package/dest/verifier/bb_verifier.js +101 -32
- package/dest/verifier/queued_chonk_verifier.d.ts +1 -1
- package/dest/verifier/queued_chonk_verifier.d.ts.map +1 -1
- package/dest/verifier/queued_chonk_verifier.js +7 -2
- package/package.json +14 -14
- package/src/bb/bb_js_backend.ts +66 -75
- package/src/prover/server/bb_prover.ts +3 -2
- package/src/test/fake_bb_js.ts +125 -0
- package/src/verifier/bb_verifier.ts +87 -11
- package/src/verifier/queued_chonk_verifier.ts +7 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRetryableError } from '@aztec-labs/foundation/error';
|
|
1
2
|
import { type Logger, createLogger } from '@aztec-labs/foundation/log';
|
|
2
3
|
import { Timer } from '@aztec-labs/foundation/timer';
|
|
3
4
|
import { ProtocolCircuitVks } from '@aztec-labs/noir-protocol-circuits-types/server/vks';
|
|
@@ -14,24 +15,43 @@ import { Tx } from '@aztec-labs/stdlib/tx';
|
|
|
14
15
|
import type { VerificationKeyData } from '@aztec-labs/stdlib/vks';
|
|
15
16
|
import { promises as fs } from 'fs';
|
|
16
17
|
|
|
17
|
-
import { BBJsFactory } from '../bb/bb_js_backend.js';
|
|
18
|
+
import { type BBJsApi, BBJsFactory } from '../bb/bb_js_backend.js';
|
|
18
19
|
import type { BBConfig } from '../config.js';
|
|
19
20
|
import { getUltraHonkFlavorForCircuit } from '../honk.js';
|
|
20
21
|
|
|
22
|
+
/** Thrown when no live bb process could check a proof, so the proof was neither accepted nor rejected. */
|
|
23
|
+
export class ProofVerifierUnavailableError extends Error {
|
|
24
|
+
constructor(message: string, options?: ErrorOptions) {
|
|
25
|
+
super(message, options);
|
|
26
|
+
this.name = 'ProofVerifierUnavailableError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
21
30
|
export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
|
|
31
|
+
/** bb instances a Chonk verification tries, while each one's bb dies under it, before the verifier is unavailable. */
|
|
32
|
+
private static readonly MAX_CHONK_VERIFY_ATTEMPTS = 2;
|
|
33
|
+
|
|
22
34
|
private bbJsFactory: BBJsFactory;
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
protected constructor(
|
|
25
37
|
private config: BBConfig,
|
|
26
38
|
private logger: Logger,
|
|
39
|
+
bbJsFactory?: BBJsFactory,
|
|
27
40
|
) {
|
|
28
41
|
// BB_NUM_IVC_VERIFIERS bounds the number of long-lived bb processes the pool keeps alive.
|
|
29
42
|
// If 0, fall back to spawning a fresh bb per verification.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
const poolSize = config.numConcurrentIVCVerifiers > 0 ? config.numConcurrentIVCVerifiers : undefined;
|
|
44
|
+
this.bbJsFactory =
|
|
45
|
+
bbJsFactory ??
|
|
46
|
+
new BBJsFactory(config.bbBinaryPath, {
|
|
47
|
+
poolSize,
|
|
48
|
+
// A pooled instance outlives the call that borrowed it, so it replaces a bb process that dies
|
|
49
|
+
// under it and the next borrower gets a working one. Each verification stands alone, so a
|
|
50
|
+
// replacement has nothing to carry over. A fresh-per-call instance has nothing to heal.
|
|
51
|
+
respawn: poolSize !== undefined,
|
|
52
|
+
logger,
|
|
53
|
+
debugDir: config.bbDebugOutputDir,
|
|
54
|
+
});
|
|
35
55
|
}
|
|
36
56
|
|
|
37
57
|
public stop(): Promise<void> {
|
|
@@ -85,9 +105,13 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
|
|
|
85
105
|
} satisfies CircuitVerificationStats);
|
|
86
106
|
}
|
|
87
107
|
|
|
88
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* Verify a Chonk (IVC) proof from a transaction via bb.js API. Throws {@link ProofVerifierUnavailableError} when no
|
|
110
|
+
* live bb process could check the proof; any other failure returns `valid: false`.
|
|
111
|
+
*/
|
|
89
112
|
public async verifyProof(tx: Tx): Promise<IVCProofVerificationResult> {
|
|
90
113
|
const proofType = 'Chonk';
|
|
114
|
+
const txHash = tx.getTxHash().toString();
|
|
91
115
|
try {
|
|
92
116
|
const totalTimer = new Timer();
|
|
93
117
|
|
|
@@ -98,8 +122,11 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
|
|
|
98
122
|
const proofWithPubInputs = tx.chonkProof.attachPublicInputs(tx.data.publicInputs().toFields());
|
|
99
123
|
const fieldsAsBuffers = proofWithPubInputs.fieldsWithPublicInputs.map(f => new Uint8Array(f.toBuffer()));
|
|
100
124
|
|
|
101
|
-
|
|
102
|
-
|
|
125
|
+
const { verified, durationMs } = await this.verifyChonkProofOnLiveInstance(
|
|
126
|
+
fieldsAsBuffers,
|
|
127
|
+
verificationKey.keyAsBytes,
|
|
128
|
+
txHash,
|
|
129
|
+
);
|
|
103
130
|
|
|
104
131
|
if (!verified) {
|
|
105
132
|
throw new Error(`Failed to verify ${proofType} proof for ${circuit}!`);
|
|
@@ -114,10 +141,59 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
|
|
|
114
141
|
|
|
115
142
|
return { valid: true, durationMs, totalDurationMs: totalTimer.ms() };
|
|
116
143
|
} catch (err) {
|
|
117
|
-
|
|
144
|
+
if (err instanceof ProofVerifierUnavailableError) {
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
this.logger.warn(`Failed to verify ${proofType} proof`, { txHash, err });
|
|
118
148
|
return { valid: false, durationMs: 0, totalDurationMs: 0 };
|
|
119
149
|
}
|
|
120
150
|
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Runs a Chonk verification on a pooled bb instance. A call that failed for environmental reasons — its bb process
|
|
154
|
+
* died, or could not be started — is retried; any other failure is the verification's own verdict and is rethrown.
|
|
155
|
+
*
|
|
156
|
+
* The error says so itself, through the `retry` property bb.js sets. Asking the instance whether it is still alive
|
|
157
|
+
* would be a guess: the process can die between the answer and the next call.
|
|
158
|
+
*/
|
|
159
|
+
private async verifyChonkProofOnLiveInstance(
|
|
160
|
+
fieldsWithPublicInputs: Uint8Array[],
|
|
161
|
+
verificationKey: Uint8Array,
|
|
162
|
+
txHash: string,
|
|
163
|
+
): Promise<{ verified: boolean; durationMs: number }> {
|
|
164
|
+
for (let attempt = 1; ; attempt++) {
|
|
165
|
+
let borrowed: BBJsApi & AsyncDisposable;
|
|
166
|
+
try {
|
|
167
|
+
borrowed = await this.bbJsFactory.getInstance();
|
|
168
|
+
} catch (err) {
|
|
169
|
+
// A bb that could not be started is worth another go, within the same budget a death gets.
|
|
170
|
+
// Anything else — the factory destroyed under us — will not improve by asking again. Either
|
|
171
|
+
// way no proof was checked, so this is never the proof's fault.
|
|
172
|
+
if (isRetryableError(err) && attempt < BBCircuitVerifier.MAX_CHONK_VERIFY_ATTEMPTS) {
|
|
173
|
+
this.logger.warn('no bb instance available to verify a proof; retrying', { txHash, attempt });
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
throw new ProofVerifierUnavailableError('No bb instance available to verify the proof', { cause: err });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await using instance = borrowed;
|
|
180
|
+
try {
|
|
181
|
+
return await instance.verifyChonkProof(fieldsWithPublicInputs, verificationKey);
|
|
182
|
+
} catch (err) {
|
|
183
|
+
// Only an environmental failure is worth retrying; anything else is the verification's own
|
|
184
|
+
// verdict and belongs to the caller.
|
|
185
|
+
if (!isRetryableError(err)) {
|
|
186
|
+
throw err;
|
|
187
|
+
}
|
|
188
|
+
if (attempt >= BBCircuitVerifier.MAX_CHONK_VERIFY_ATTEMPTS) {
|
|
189
|
+
throw new ProofVerifierUnavailableError(`bb died while verifying the proof, on ${attempt} attempts`, {
|
|
190
|
+
cause: err,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
this.logger.warn('bb died while verifying a proof; retrying', { txHash, attempt });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
121
197
|
}
|
|
122
198
|
|
|
123
199
|
/** Split a buffer into 32-byte Uint8Array field elements. */
|
|
@@ -102,7 +102,12 @@ export class QueuedIVCVerifier implements ClientProtocolCircuitVerifier {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
async stop(): Promise<void> {
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
// Stopped first so that verifications waiting for a bb instance fail rather than keep the queue from draining. Queued
|
|
106
|
+
// verifications that have not started yet fail too.
|
|
107
|
+
try {
|
|
108
|
+
await this.verifier.stop();
|
|
109
|
+
} finally {
|
|
110
|
+
await this.queue.end();
|
|
111
|
+
}
|
|
107
112
|
}
|
|
108
113
|
}
|