Skip to content

Commit

Permalink
fix: Revert "feat: ultra keccak honk verifier (#8427)
Browse files Browse the repository at this point in the history
Reverts #8391, which reverted #8261 :)
Also adds a few enhancements to bring it up to date with latest crypto
changes

---------

Co-authored-by: ludamad <adam.domurad@gmail.com>
  • Loading branch information
alexghr and ludamad authored Sep 9, 2024
1 parent 1e91469 commit 31df5ea
Show file tree
Hide file tree
Showing 22 changed files with 220 additions and 240 deletions.
9 changes: 6 additions & 3 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,7 @@ void prove_honk_output_all(const std::string& bytecodePath,
using VerificationKey = Flavor::VerificationKey;

bool honk_recursion = false;
if constexpr (IsAnyOf<Flavor, UltraFlavor>) {
if constexpr (IsAnyOf<Flavor, UltraFlavor, UltraKeccakFlavor>) {
honk_recursion = true;
}

Expand Down Expand Up @@ -1477,12 +1477,12 @@ int main(int argc, char* argv[])
} else if (command == "prove_keccak_ultra_honk") {
std::string output_path = get_option(args, "-o", "./proofs/proof");
prove_honk<UltraKeccakFlavor>(bytecode_path, witness_path, output_path);
} else if (command == "prove_keccak_ultra_honk_output_all") {
} else if (command == "prove_ultra_keccak_honk_output_all") {
std::string output_path = get_option(args, "-o", "./proofs/proof");
prove_honk_output_all<UltraKeccakFlavor>(bytecode_path, witness_path, output_path);
} else if (command == "verify_ultra_honk") {
return verify_honk<UltraFlavor>(proof_path, vk_path) ? 0 : 1;
} else if (command == "verify_keccak_ultra_honk") {
} else if (command == "verify_ultra_keccak_honk") {
return verify_honk<UltraKeccakFlavor>(proof_path, vk_path) ? 0 : 1;
} else if (command == "write_vk_ultra_honk") {
std::string output_path = get_option(args, "-o", "./target/vk");
Expand All @@ -1507,6 +1507,9 @@ int main(int argc, char* argv[])
} else if (command == "vk_as_fields_mega_honk") {
std::string output_path = get_option(args, "-o", vk_path + "_fields.json");
vk_as_fields_honk<MegaFlavor>(vk_path, output_path);
} else if (command == "vk_as_fields_ultra_keccak_honk") {
std::string output_path = get_option(args, "-o", vk_path + "_fields.json");
vk_as_fields_honk<UltraKeccakFlavor>(vk_path, output_path);
} else {
std::cerr << "Unknown command: " << command << "\n";
return 1;
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ protocol-verification-keys:
rollup-verifier-contract:
FROM +bb-cli
COPY --dir +protocol-verification-keys/usr/src/bb /usr/src
RUN --entrypoint write-contract -c RootRollupArtifact -n UltraHonkVerifier.sol
RUN --entrypoint write-contract -c BlockRootRollupArtifact -n UltraHonkVerifier.sol
SAVE ARTIFACT /usr/src/bb /usr/src/bb

txe:
Expand Down
4 changes: 3 additions & 1 deletion yarn-project/bb-prover/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"tslib": "^2.4.0"
},
"devDependencies": {
"@aztec/ethereum": "workspace:^",
"@jest/globals": "^29.5.0",
"@types/jest": "^29.5.0",
"@types/memdown": "^3.0.0",
Expand All @@ -81,7 +82,8 @@
"jest": "^29.5.0",
"jest-mock-extended": "^3.0.3",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
"typescript": "^5.0.4",
"viem": "^2.7.15"
},
"files": [
"dest",
Expand Down
36 changes: 3 additions & 33 deletions yarn-project/bb-prover/src/bb/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,6 @@ export function getProgram(log: LogFn): Command {
log(Object.keys(ProtocolCircuitArtifacts).reduce((prev: string, x: string) => prev.concat(`\n${x}`)));
});

program
.command('write-pk')
.description('Generates the proving key for the specified circuit')
.requiredOption(
'-w, --working-directory <string>',
'A directory to use for storing input/output files',
BB_WORKING_DIRECTORY,
)
.requiredOption('-b, --bb-path <string>', 'The path to the BB binary', BB_BINARY_PATH)
.requiredOption('-c, --circuit <string>', 'The name of a protocol circuit')
.action(async options => {
const compiledCircuit = ProtocolCircuitArtifacts[options.circuit as ProtocolArtifact];
if (!compiledCircuit) {
log(`Failed to find circuit ${options.circuit}`);
return;
}
try {
await fs.access(options.workingDirectory, fs.constants.W_OK);
} catch (error) {
log(`Working directory does not exist`);
return;
}
await generateKeyForNoirCircuit(
options.bbPath,
options.workingDirectory,
options.circuit,
compiledCircuit,
'pk',
log,
);
});

program
.command('write-vk')
.description('Generates the verification key for the specified circuit')
Expand All @@ -67,6 +35,7 @@ export function getProgram(log: LogFn): Command {
)
.requiredOption('-b, --bb-path <string>', 'The path to the BB binary', BB_BINARY_PATH)
.requiredOption('-c, --circuit <string>', 'The name of a protocol circuit')
.requiredOption('-f, --flavor <string>', 'The name of the verification key flavor', 'ultra_honk')
.action(async options => {
const compiledCircuit = ProtocolCircuitArtifacts[options.circuit as ProtocolArtifact];
if (!compiledCircuit) {
Expand All @@ -84,7 +53,8 @@ export function getProgram(log: LogFn): Command {
options.workingDirectory,
options.circuit,
compiledCircuit,
'vk',
options.flavor,
// (options.circuit as ServerProtocolArtifact) === 'RootRollupArtifact' ? 'ultra_keccak_honk' : 'ultra_honk',
log,
);
});
Expand Down
37 changes: 21 additions & 16 deletions yarn-project/bb-prover/src/bb/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import * as proc from 'child_process';
import * as fs from 'fs/promises';
import { basename, dirname, join } from 'path';

import { type UltraHonkFlavor } from '../honk.js';

export const VK_FILENAME = 'vk';
export const VK_FIELDS_FILENAME = 'vk_fields.json';
export const PROOF_FILENAME = 'proof';
Expand Down Expand Up @@ -113,7 +115,7 @@ export async function generateKeyForNoirCircuit(
workingDirectory: string,
circuitName: string,
compiledCircuit: NoirCompiledCircuit,
key: 'vk' | 'pk',
flavor: UltraHonkFlavor,
log: LogFn,
force = false,
): Promise<BBSuccess | BBFailure> {
Expand All @@ -123,7 +125,7 @@ export async function generateKeyForNoirCircuit(
// The bytecode hash file is also written here as /workingDirectory/pk/BaseParityArtifact/bytecode-hash
// The bytecode is written to e.g. /workingDirectory/pk/BaseParityArtifact/bytecode
// The bytecode is removed after the key is generated, leaving just the hash file
const circuitOutputDirectory = `${workingDirectory}/${key}/${circuitName}`;
const circuitOutputDirectory = `${workingDirectory}/vk/${circuitName}`;
const outputPath = `${circuitOutputDirectory}`;
const bytecodeHash = sha256(bytecode);

Expand All @@ -148,20 +150,20 @@ export async function generateKeyForNoirCircuit(
// args are the output path and the input bytecode path
const args = ['-o', `${outputPath}/${VK_FILENAME}`, '-b', bytecodePath];
const timer = new Timer();
let result = await executeBB(pathToBB, `write_${key}_ultra_honk`, args, log);
let result = await executeBB(pathToBB, `write_vk_${flavor}`, args, log);
// If we succeeded and the type of key if verification, have bb write the 'fields' version too
if (result.status == BB_RESULT.SUCCESS && key === 'vk') {
if (result.status == BB_RESULT.SUCCESS) {
const asFieldsArgs = ['-k', `${outputPath}/${VK_FILENAME}`, '-o', `${outputPath}/${VK_FIELDS_FILENAME}`, '-v'];
result = await executeBB(pathToBB, `vk_as_fields_ultra_honk`, asFieldsArgs, log);
result = await executeBB(pathToBB, `vk_as_fields_${flavor}`, asFieldsArgs, log);
}
const duration = timer.ms();

if (result.status == BB_RESULT.SUCCESS) {
return {
status: BB_RESULT.SUCCESS,
durationMs: duration,
pkPath: key === 'pk' ? outputPath : undefined,
vkPath: key === 'vk' ? outputPath : undefined,
pkPath: undefined,
vkPath: outputPath,
proofPath: undefined,
};
}
Expand All @@ -179,8 +181,8 @@ export async function generateKeyForNoirCircuit(
return {
status: BB_RESULT.ALREADY_PRESENT,
durationMs: 0,
pkPath: key === 'pk' ? outputPath : undefined,
vkPath: key === 'vk' ? outputPath : undefined,
pkPath: undefined,
vkPath: outputPath,
};
}

Expand Down Expand Up @@ -261,6 +263,7 @@ export async function computeVerificationKey(
workingDirectory: string,
circuitName: string,
bytecode: Buffer,
flavor: UltraHonkFlavor,
log: LogFn,
): Promise<BBFailure | BBSuccess> {
// Check that the working directory exists
Expand Down Expand Up @@ -293,7 +296,7 @@ export async function computeVerificationKey(
};
let result = await executeBB(
pathToBB,
'write_vk_ultra_honk',
`write_vk_${flavor}`,
['-o', outputPath, '-b', bytecodePath, '-v'],
logFunction,
);
Expand All @@ -302,7 +305,7 @@ export async function computeVerificationKey(
}
result = await executeBB(
pathToBB,
'vk_as_fields_ultra_honk',
`vk_as_fields_${flavor}`,
['-o', outputPath + '_fields.json', '-k', outputPath, '-v'],
logFunction,
);
Expand Down Expand Up @@ -343,6 +346,7 @@ export async function generateProof(
circuitName: string,
bytecode: Buffer,
inputWitnessFile: string,
flavor: UltraHonkFlavor,
log: LogFn,
): Promise<BBFailure | BBSuccess> {
// Check that the working directory exists
Expand All @@ -355,7 +359,7 @@ export async function generateProof(
// The bytecode is written to e.g. /workingDirectory/BaseParityArtifact-bytecode
const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`;

// The proof is written to e.g. /workingDirectory/proof
// The proof is written to e.g. /workingDirectory/ultra_honk/proof
const outputPath = `${workingDirectory}`;

const binaryPresent = await fs
Expand All @@ -374,7 +378,7 @@ export async function generateProof(
const logFunction = (message: string) => {
log(`${circuitName} BB out - ${message}`);
};
const result = await executeBB(pathToBB, 'prove_ultra_honk_output_all', args, logFunction);
const result = await executeBB(pathToBB, `prove_${flavor}_output_all`, args, logFunction);
const duration = timer.ms();

if (result.status == BB_RESULT.SUCCESS) {
Expand Down Expand Up @@ -599,9 +603,10 @@ export async function verifyProof(
pathToBB: string,
proofFullPath: string,
verificationKeyPath: string,
ultraHonkFlavor: UltraHonkFlavor,
log: LogFn,
): Promise<BBFailure | BBSuccess> {
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'verify_ultra_honk', log);
return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, `verify_${ultraHonkFlavor}`, log);
}

/**
Expand Down Expand Up @@ -674,7 +679,7 @@ async function verifyProofInternal(
pathToBB: string,
proofFullPath: string,
verificationKeyPath: string,
command: 'verify_ultra_honk' | 'avm_verify',
command: 'verify_ultra_honk' | 'verify_ultra_keccak_honk' | 'avm_verify',
log: LogFn,
): Promise<BBFailure | BBSuccess> {
const binaryPresent = await fs
Expand Down Expand Up @@ -851,7 +856,7 @@ export async function generateContractForCircuit(
workingDirectory,
circuitName,
compiledCircuit,
'vk',
'ultra_keccak_honk',
log,
force,
);
Expand Down
18 changes: 18 additions & 0 deletions yarn-project/bb-prover/src/honk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type ProtocolArtifact } from '@aztec/noir-protocol-circuits-types';

export type UltraHonkFlavor = 'ultra_honk' | 'ultra_keccak_honk';

const UltraKeccakHonkCircuits = ['BlockRootRollupArtifact'] as const;
type UltraKeccakHonkCircuits = (typeof UltraKeccakHonkCircuits)[number];
type UltraHonkCircuits = Exclude<ProtocolArtifact, UltraKeccakHonkCircuits>;

export function getUltraHonkFlavorForCircuit(artifact: UltraKeccakHonkCircuits): 'ultra_keccak_honk';
export function getUltraHonkFlavorForCircuit(artifact: UltraHonkCircuits): 'ultra_honk';
export function getUltraHonkFlavorForCircuit(artifact: ProtocolArtifact): UltraHonkFlavor;
export function getUltraHonkFlavorForCircuit(artifact: ProtocolArtifact): UltraHonkFlavor {
return isUltraKeccakHonkCircuit(artifact) ? 'ultra_keccak_honk' : 'ultra_honk';
}

function isUltraKeccakHonkCircuit(artifact: ProtocolArtifact): artifact is UltraKeccakHonkCircuits {
return UltraKeccakHonkCircuits.includes(artifact as UltraKeccakHonkCircuits);
}
20 changes: 17 additions & 3 deletions yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
verifyProof,
} from '../bb/execute.js';
import { type BBConfig } from '../config.js';
import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../honk.js';
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
import { extractVkData } from '../verification_key/verification_key_data.js';

Expand Down Expand Up @@ -213,7 +214,12 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
this.log.debug(`${circuitType} BB out - ${message}`);
};

const result = await this.verifyProofFromKey(verificationKey.keyAsBytes, proof, logFunction);
const result = await this.verifyProofFromKey(
getUltraHonkFlavorForCircuit(circuitType),
verificationKey.keyAsBytes,
proof,
logFunction,
);

if (result.status === BB_RESULT.FAILURE) {
const errorMessage = `Failed to verify ${circuitType} proof!`;
Expand All @@ -224,6 +230,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
}

private async verifyProofFromKey(
flavor: UltraHonkFlavor,
verificationKey: Buffer,
proof: Proof,
logFunction: (message: string) => void = () => {},
Expand All @@ -234,7 +241,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {

await fs.writeFile(proofFileName, proof.buffer);
await fs.writeFile(verificationKeyPath, verificationKey);
return await verifyProof(this.bbBinaryPath, proofFileName, verificationKeyPath!, logFunction);
return await verifyProof(this.bbBinaryPath, proofFileName, verificationKeyPath!, flavor, logFunction);
};
return await this.runInDirectory(operation);
}
Expand Down Expand Up @@ -301,7 +308,14 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {

const timer = new Timer();

const vkResult = await computeVerificationKey(this.bbBinaryPath, directory, circuitType, bytecode, this.log.debug);
const vkResult = await computeVerificationKey(
this.bbBinaryPath,
directory,
circuitType,
bytecode,
circuitType === 'App' ? 'ultra_honk' : getUltraHonkFlavorForCircuit(circuitType),
this.log.debug,
);

if (vkResult.status === BB_RESULT.FAILURE) {
this.log.error(`Failed to generate proof for ${circuitType}${dbgCircuitName}: ${vkResult.reason}`);
Expand Down
Loading

0 comments on commit 31df5ea

Please sign in to comment.