Skip to content

Commit

Permalink
chore: Bench client ivc proof verification
Browse files Browse the repository at this point in the history
  • Loading branch information
spalladino committed Jul 22, 2024
1 parent 609a68f commit c7d8052
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 17 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
20 changes: 15 additions & 5 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,16 +197,20 @@ 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) {
await verifier.verifyProof(tx);
}
}

ctx.logger.info('Sending transactions');
const txs = [
Expand Down

0 comments on commit c7d8052

Please sign in to comment.