Skip to content

Commit

Permalink
chore: Bench client ivc proof verification (#7553)
Browse files Browse the repository at this point in the history
Wires the `verify_client_ivc` bb call to the BBVerifier in ts (which
still needs love so we don't read the vk from the tx object), and runs
it multiple times as part of the full prover e2e to benchmark how much
it takes to verify a client ivc proof. Outputs event logs like the
following, though they are not yet loaded by bench-aggregate:

```
{"circuitName":"private-kernel-tail-to-public","duration":3640.18761600001,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:19.785Z"}
{"circuitName":"private-kernel-tail","duration":3630.627105999971,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:23.419Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3636.371545000002,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:27.057Z"}
{"circuitName":"private-kernel-tail","duration":3561.3480010000058,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:30.620Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3588.0015310000163,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:34.211Z"}
{"circuitName":"private-kernel-tail","duration":3610.198040999996,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:37.824Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3569.164287999971,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:41.396Z"}
{"circuitName":"private-kernel-tail","duration":3557.741927999945,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:44.955Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3568.2085040000384,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:48.526Z"}
{"circuitName":"private-kernel-tail","duration":3557.740408999962,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:52.088Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3568.786586000002,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:55.659Z"}
{"circuitName":"private-kernel-tail","duration":3559.4025660000043,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:37:59.221Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3567.728372999991,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:02.792Z"}
{"circuitName":"private-kernel-tail","duration":3566.036272999947,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:06.362Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3569.9772229999653,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:09.935Z"}
{"circuitName":"private-kernel-tail","duration":3561.0968479999574,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:13.499Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3569.0639850000152,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:17.071Z"}
{"circuitName":"private-kernel-tail","duration":3562.8168169999844,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:20.639Z"}
{"circuitName":"private-kernel-tail-to-public","duration":3568.064185999974,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:24.209Z"}
{"circuitName":"private-kernel-tail","duration":3558.7975469999947,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:27.771Z"}
{"circuitName":"private-kernel-tail","duration":3616.5346459999564,"eventName":"circuit-verification","level":"debug","message":"ClientIVC verification successful","namespace":"aztec:bb-verifier","proofType":"client-ivc","timestamp":"2024-07-22T19:38:31.404Z"}
```
  • Loading branch information
spalladino authored Jul 25, 2024
1 parent 1a97698 commit b060309
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 20 deletions.
40 changes: 40 additions & 0 deletions yarn-project/bb-prover/src/bb/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,46 @@ export async function verifyAvmProof(
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', log);
}

/**
* Verifies a ClientIvcProof
* TODO(#7370) The verification keys should be supplied separately
* @param pathToBB - The full path to the bb binary
* @param targetPath - The path to the folder with the proof, accumulator, and verification keys
* @param log - A logging function
* @returns An object containing a result indication and duration taken
*/
export async function verifyClientIvcProof(
pathToBB: string,
targetPath: string,
log: LogFn,
): Promise<BBFailure | BBSuccess> {
const binaryPresent = await fs
.access(pathToBB, fs.constants.R_OK)
.then(_ => true)
.catch(_ => false);
if (!binaryPresent) {
return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` };
}

try {
const args = ['-o', targetPath];
const timer = new Timer();
const command = 'verify_client_ivc';
const result = await executeBB(pathToBB, command, args, log);
const duration = timer.ms();
if (result.status == BB_RESULT.SUCCESS) {
return { status: BB_RESULT.SUCCESS, durationMs: duration };
}
// Not a great error message here but it is difficult to decipher what comes from bb
return {
status: BB_RESULT.FAILURE,
reason: `Failed to verify proof. Exit code ${result.exitCode}. Signal ${result.signal}.`,
};
} catch (error) {
return { status: BB_RESULT.FAILURE, reason: `${error}` };
}
}

/**
* Used for verifying proofs with BB
* @param pathToBB - The full path to the bb binary
Expand Down
56 changes: 44 additions & 12 deletions yarn-project/bb-prover/src/verifier/bb_verifier.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type ClientProtocolCircuitVerifier, Tx } from '@aztec/circuit-types';
import { type CircuitVerificationStats } from '@aztec/circuit-types/stats';
import { type Proof, type VerificationKeyData } from '@aztec/circuits.js';
import { runInDirectory } from '@aztec/foundation/fs';
import { type DebugLogger, type LogFn, createDebugLogger } from '@aztec/foundation/log';
Expand All @@ -17,9 +18,11 @@ import {
VK_FILENAME,
generateContractForCircuit,
generateKeyForNoirCircuit,
verifyClientIvcProof,
verifyProof,
} from '../bb/execute.js';
import { type BBConfig } from '../config.js';
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
import { extractVkData } from '../verification_key/verification_key_data.js';

export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
Expand Down Expand Up @@ -106,7 +109,12 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
throw new Error(errorMessage);
}

this.logger.debug(`${circuit} verification successful`);
this.logger.debug(`${circuit} verification successful`, {
circuitName: mapProtocolArtifactNameToCircuitName(circuit),
duration: result.durationMs,
eventName: 'circuit-verification',
proofType: 'ultra-honk',
} satisfies CircuitVerificationStats);
};
await runInDirectory(this.config.bbWorkingDirectory, operation);
}
Expand All @@ -128,19 +136,43 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
return fs.readFile(result.contractPath!, 'utf-8');
}

verifyProof(tx: Tx): Promise<boolean> {
const expectedCircuit: ClientProtocolArtifact = tx.data.forPublic
? 'PrivateKernelTailToPublicArtifact'
: 'PrivateKernelTailArtifact';

public async verifyProof(tx: Tx): Promise<boolean> {
try {
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1050) we need a proper verify flow for clientIvcProof
// For now we handle only the trivial blank data case
// await this.verifyProofForCircuit(expectedCircuit, proof);
return Promise.resolve(!tx.clientIvcProof.isEmpty());
// TODO(#7370) The verification keys should be supplied separately and based on the expectedCircuit
// rather than read from the tx object itself. We also need the vks for the translator and ecc, which
// are not being saved along the other vks yet. Reuse the 'verifyProofForCircuit' method above once
// we have all the verification keys available.
const expectedCircuit: ClientProtocolArtifact = tx.data.forPublic
? 'PrivateKernelTailToPublicArtifact'
: 'PrivateKernelTailArtifact';
const circuit = 'ClientIVC';

// Block below is almost copy-pasted from verifyProofForCircuit
const operation = async (bbWorkingDirectory: string) => {
const logFunction = (message: string) => {
this.logger.debug(`${circuit} BB out - ${message}`);
};

await tx.clientIvcProof.writeToOutputDirectory(bbWorkingDirectory);
const result = await verifyClientIvcProof(this.config.bbBinaryPath, bbWorkingDirectory, logFunction);

if (result.status === BB_RESULT.FAILURE) {
const errorMessage = `Failed to verify ${circuit} proof!`;
throw new Error(errorMessage);
}

this.logger.debug(`${circuit} verification successful`, {
circuitName: mapProtocolArtifactNameToCircuitName(expectedCircuit),
duration: result.durationMs,
eventName: 'circuit-verification',
proofType: 'client-ivc',
} satisfies CircuitVerificationStats);
};
await runInDirectory(this.config.bbWorkingDirectory, operation);
return true;
} catch (err) {
this.logger.warn(`Failed to verify ${expectedCircuit} proof for tx ${Tx.getHash(tx)}: ${String(err)}`);
return Promise.resolve(false);
this.logger.warn(`Failed to verify ClientIVC proof for tx ${Tx.getHash(tx)}: ${String(err)}`);
return false;
}
}
}
12 changes: 12 additions & 0 deletions yarn-project/circuit-types/src/stats/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,18 @@ export type CircuitProvingStats = {
numPublicInputs: number;
};

/** Stats for verifying a circuit */
export type CircuitVerificationStats = {
/** Name of the event. */
eventName: 'circuit-verification';
/** Name of the circuit. */
circuitName: CircuitName;
/** Type of proof (client-ivc, honk, etc) */
proofType: 'client-ivc' | 'ultra-honk';
/** Duration in ms. */
duration: number;
};

/** Stats for an L2 block built by a sequencer. */
export type L2BlockBuiltStats = {
/** Name of the event. */
Expand Down
24 changes: 16 additions & 8 deletions yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getSchnorrAccount, getSchnorrWallet } from '@aztec/accounts/schnorr';
import { PublicFeePaymentMethod, TxStatus, sleep } from '@aztec/aztec.js';
import { type AccountWallet } from '@aztec/aztec.js/wallet';
import { BBCircuitVerifier } from '@aztec/bb-prover';
import { CompleteAddress, Fq, Fr, GasSettings } from '@aztec/circuits.js';
import { FPCContract, GasTokenContract, TestContract, TokenContract } from '@aztec/noir-contracts.js';
import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token';
Expand All @@ -18,6 +19,11 @@ jest.setTimeout(1_800_000);

const txTimeoutSec = 3600;

// How many times we'll run bb verify on each tx for benchmarking purposes
const txVerifyIterations = process.env.BENCH_TX_VERIFY_ITERATIONS
? parseInt(process.env.BENCH_TX_VERIFY_ITERATIONS)
: 10;

// This makes AVM proving throw if there's a failure.
process.env.AVM_PROVING_STRICT = '1';

Expand Down Expand Up @@ -191,22 +197,24 @@ describe('benchmarks/proving', () => {
// };

ctx.logger.info('Proving transactions');
await Promise.all([
fnCalls[0].prove({
fee: feeFnCall0,
}),
const provenTxs = await Promise.all([
fnCalls[0].prove({ fee: feeFnCall0 }),
fnCalls[1].prove(),
// fnCalls[2].prove(),
// fnCalls[3].prove(),
]);

ctx.logger.info('Finished proving');
ctx.logger.info('Verifying transactions client proofs');
const verifier = await BBCircuitVerifier.new((await getBBConfig(ctx.logger))!);
for (let i = 0; i < txVerifyIterations; i++) {
for (const tx of provenTxs) {
expect(await verifier.verifyProof(tx)).toBe(true);
}
}

ctx.logger.info('Sending transactions');
const txs = [
fnCalls[0].send({
fee: feeFnCall0,
}),
fnCalls[0].send({ fee: feeFnCall0 }),
fnCalls[1].send(),
// fnCalls[2].send(),
// fnCalls[3].send(),
Expand Down

0 comments on commit b060309

Please sign in to comment.