Skip to content

Commit

Permalink
fix(bb-prover): create structure for AVM vk
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Aug 28, 2024
1 parent 5929a42 commit 0e1411c
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 34 deletions.
1 change: 1 addition & 0 deletions barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#define HEADER_LENGTH 24
#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 691
#define PUBLIC_CONTEXT_INPUTS_LENGTH 42
#define AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS 66
#define SENDER_SELECTOR 0
#define ADDRESS_SELECTOR 1
#define STORAGE_ADDRESS_SELECTOR 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,12 @@ global NESTED_RECURSIVE_PROOF_LENGTH = 439;
global TUBE_PROOF_LENGTH = RECURSIVE_PROOF_LENGTH; // in the future these can differ

global VERIFICATION_KEY_LENGTH_IN_FIELDS = 128;
// VK is composed of
// - circuit size encoded as a fr field element (32 bytes)
// - num of inputs encoded as a fr field element (32 bytes)
// - 16 affine elements (curve base field fq) encoded as fr elements takes (16 * 4 * 32 bytes)
// 16 above refers to the constant AvmFlavor::NUM_PRECOMPUTED_ENTITIES
global AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS = 2 + 16 * 4;

/**
* Enumerate the hash_indices which are used for pedersen hashing.
Expand Down
17 changes: 5 additions & 12 deletions yarn-project/bb-prover/src/avm_proving.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
AvmCircuitInputs,
AvmVerificationKeyData,
AztecAddress,
ContractStorageRead,
ContractStorageUpdateRequest,
Expand Down Expand Up @@ -49,7 +50,7 @@ import path from 'path';
import { PublicSideEffectTrace } from '../../simulator/src/public/side_effect_trace.js';
import { SerializableContractInstance } from '../../types/src/contracts/contract_instance.js';
import { type BBSuccess, BB_RESULT, generateAvmProof, verifyAvmProof } from './bb/execute.js';
import { extractVkData } from './verification_key/verification_key_data.js';
import { extractAvmVkData } from './verification_key/verification_key_data.js';

const TIMEOUT = 60_000;
const TIMESTAMP = new Fr(99833);
Expand Down Expand Up @@ -279,18 +280,10 @@ const proveAndVerifyAvmTestContract = async (
const proofRes = await generateAvmProof(bbPath, bbWorkingDirectory, avmCircuitInputs, logger);
expect(proofRes.status).toEqual(BB_RESULT.SUCCESS);

// Then we test VK extraction.
// Then we test VK extraction and serialization.
const succeededRes = proofRes as BBSuccess;
const verificationKey = await extractVkData(succeededRes.vkPath!);

// VK is composed of
// - circuit size encoded as a fr field element (32 bytes)
// - num of inputs encoded as a fr field element (32 bytes)
// - 16 affine elements (curve base field fq) encoded as fr elements takes (16 * 4 * 32 bytes)
// 16 above refers to the constant AvmFlavor::NUM_PRECOMPUTED_ENTITIES
// Total number of bytes = 2112
const NUM_PRECOMPUTED_ENTITIES = 16;
expect(verificationKey.keyAsBytes).toHaveLength(NUM_PRECOMPUTED_ENTITIES * 4 * 32 + 2 * 32);
const vkData = await extractAvmVkData(succeededRes.vkPath!);
AvmVerificationKeyData.fromBuffer(vkData.toBuffer());

// Then we verify.
const rawVkPath = path.join(succeededRes.vkPath!, 'vk');
Expand Down
17 changes: 9 additions & 8 deletions yarn-project/bb-prover/src/prover/bb_prover.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable require-await */
import {
type ProofAndVerificationKey,
type AvmProofAndVerificationKey,
type PublicInputsAndRecursiveProof,
type PublicKernelNonTailRequest,
type PublicKernelTailRequest,
Expand All @@ -11,6 +11,7 @@ import { type CircuitProvingStats, type CircuitWitnessGenerationStats } from '@a
import {
AGGREGATION_OBJECT_LENGTH,
type AvmCircuitInputs,
type AvmVerificationKeyData,
type BaseOrMergeRollupPublicInputs,
type BaseParityInputs,
type BaseRollupInputs,
Expand Down Expand Up @@ -94,7 +95,7 @@ import type { ACVMConfig, BBConfig } from '../config.js';
import { ProverInstrumentation } from '../instrumentation.js';
import { PublicKernelArtifactMapping } from '../mappings/mappings.js';
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
import { extractVkData } from '../verification_key/verification_key_data.js';
import { extractAvmVkData, extractVkData } from '../verification_key/verification_key_data.js';

const logger = createDebugLogger('aztec:bb-prover');

Expand Down Expand Up @@ -202,7 +203,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
@trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({
[Attributes.APP_CIRCUIT_NAME]: inputs.functionName,
}))
public async getAvmProof(inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
public async getAvmProof(inputs: AvmCircuitInputs): Promise<AvmProofAndVerificationKey> {
const proofAndVk = await this.createAvmProof(inputs);
await this.verifyAvmProof(proofAndVk.proof, proofAndVk.verificationKey);
return proofAndVk;
Expand Down Expand Up @@ -626,14 +627,14 @@ export class BBNativeRollupProver implements ServerCircuitProver {
return provingResult;
}

private async createAvmProof(input: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
const operation = async (bbWorkingDirectory: string): Promise<ProofAndVerificationKey> => {
private async createAvmProof(input: AvmCircuitInputs): Promise<AvmProofAndVerificationKey> {
const operation = async (bbWorkingDirectory: string): Promise<AvmProofAndVerificationKey> => {
const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory);

const rawProof = await fs.readFile(provingResult.proofPath!);
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6773): this VK data format is wrong.
// In particular, the number of public inputs, etc will be wrong.
const verificationKey = await extractVkData(provingResult.vkPath!);
const verificationKey = await extractAvmVkData(provingResult.vkPath!);
const proof = new Proof(rawProof, verificationKey.numPublicInputs);

const circuitType = 'avm-circuit' as const;
Expand Down Expand Up @@ -765,7 +766,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {
return await this.verifyWithKey(verificationKey, proof);
}

public async verifyAvmProof(proof: Proof, verificationKey: VerificationKeyData) {
public async verifyAvmProof(proof: Proof, verificationKey: AvmVerificationKeyData) {
return await this.verifyWithKeyInternal(proof, verificationKey, verifyAvmProof);
}

Expand All @@ -775,7 +776,7 @@ export class BBNativeRollupProver implements ServerCircuitProver {

private async verifyWithKeyInternal(
proof: Proof,
verificationKey: VerificationKeyData,
verificationKey: { keyAsBytes: Buffer },
verificationFunction: VerificationFunction,
) {
const operation = async (bbWorkingDirectory: string) => {
Expand Down
7 changes: 4 additions & 3 deletions yarn-project/bb-prover/src/test/test_circuit_prover.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
type ProofAndVerificationKey,
type AvmProofAndVerificationKey,
type PublicInputsAndRecursiveProof,
type PublicKernelNonTailRequest,
type PublicKernelTailRequest,
Expand All @@ -8,6 +8,7 @@ import {
} from '@aztec/circuit-types';
import {
type AvmCircuitInputs,
AvmVerificationKeyData,
type BaseOrMergeRollupPublicInputs,
type BaseParityInputs,
type BaseRollupInputs,
Expand Down Expand Up @@ -475,12 +476,12 @@ export class TestCircuitProver implements ServerCircuitProver {
);
}

public async getAvmProof(_inputs: AvmCircuitInputs): Promise<ProofAndVerificationKey> {
public async getAvmProof(_inputs: AvmCircuitInputs): Promise<AvmProofAndVerificationKey> {
// We can't simulate the AVM because we don't have enough context to do so (e.g., DBs).
// We just return an empty proof and VK data.
this.logger.debug('Skipping AVM simulation in TestCircuitProver.');
await this.delay();
return { proof: makeEmptyProof(), verificationKey: VerificationKeyData.makeFake() };
return { proof: makeEmptyProof(), verificationKey: AvmVerificationKeyData.makeFake() };
}

private async delay(): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import {
AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS,
AvmVerificationKeyAsFields,
AvmVerificationKeyData,
Fr,
type VERIFICATION_KEY_LENGTH_IN_FIELDS,
VERIFICATION_KEY_LENGTH_IN_FIELDS,
VerificationKeyAsFields,
VerificationKeyData,
} from '@aztec/circuits.js';
import { type Tuple } from '@aztec/foundation/serialize';

import { strict as assert } from 'assert';
import * as fs from 'fs/promises';
import * as path from 'path';

Expand All @@ -25,7 +29,25 @@ export async function extractVkData(vkDirectoryPath: string): Promise<Verificati
const fields = fieldsJson.map(Fr.fromString);
// The first item is the hash, this is not part of the actual VK
const vkHash = fields[0];
assert(fields.length === VERIFICATION_KEY_LENGTH_IN_FIELDS, 'Invalid verification key length');
const vkAsFields = new VerificationKeyAsFields(fields as Tuple<Fr, typeof VERIFICATION_KEY_LENGTH_IN_FIELDS>, vkHash);
const vk = new VerificationKeyData(vkAsFields, rawBinary);
return vk;
}

// TODO: This was adapted from the above function. A refactor might be needed.
export async function extractAvmVkData(vkDirectoryPath: string): Promise<AvmVerificationKeyData> {
const [rawFields, rawBinary] = await Promise.all([
fs.readFile(path.join(vkDirectoryPath, VK_FIELDS_FILENAME), { encoding: 'utf-8' }),
fs.readFile(path.join(vkDirectoryPath, VK_FILENAME)),
]);
const fieldsJson = JSON.parse(rawFields);
const fields = fieldsJson.map(Fr.fromString);
// The first item is the hash, this is not part of the actual VK
// TODO: is the above actually the case?
const vkHash = fields[0];
assert(fields.length === AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, 'Invalid AVM verification key length');
const vkAsFields = new AvmVerificationKeyAsFields(fields, vkHash);
const vk = new AvmVerificationKeyData(vkAsFields, rawBinary);
return vk;
}
7 changes: 4 additions & 3 deletions yarn-project/circuit-types/src/interfaces/proving-job.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
type AvmCircuitInputs,
type AvmVerificationKeyData,
type BaseOrMergeRollupPublicInputs,
type BaseParityInputs,
type BaseRollupInputs,
Expand All @@ -25,9 +26,9 @@ import {

import type { PublicKernelNonTailRequest, PublicKernelTailRequest } from '../tx/processed_tx.js';

export type ProofAndVerificationKey = {
export type AvmProofAndVerificationKey = {
proof: Proof;
verificationKey: VerificationKeyData;
verificationKey: AvmVerificationKeyData;
};

export type PublicInputsAndRecursiveProof<T> = {
Expand Down Expand Up @@ -133,7 +134,7 @@ export type ProvingRequest =

export type ProvingRequestPublicInputs = {
[ProvingRequestType.PRIVATE_KERNEL_EMPTY]: PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>;
[ProvingRequestType.PUBLIC_VM]: ProofAndVerificationKey;
[ProvingRequestType.PUBLIC_VM]: AvmProofAndVerificationKey;

[ProvingRequestType.PUBLIC_KERNEL_NON_TAIL]: PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>;
[ProvingRequestType.PUBLIC_KERNEL_TAIL]: PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
type ProofAndVerificationKey,
type AvmProofAndVerificationKey,
type PublicInputsAndRecursiveProof,
type PublicInputsAndTubeProof,
type PublicKernelNonTailRequest,
Expand Down Expand Up @@ -149,7 +149,11 @@ export interface ServerCircuitProver {
* Create a proof for the AVM circuit.
* @param inputs - Inputs to the AVM circuit.
*/
getAvmProof(inputs: AvmCircuitInputs, signal?: AbortSignal, epochNumber?: number): Promise<ProofAndVerificationKey>;
getAvmProof(
inputs: AvmCircuitInputs,
signal?: AbortSignal,
epochNumber?: number,
): Promise<AvmProofAndVerificationKey>;
}

/**
Expand Down
1 change: 1 addition & 0 deletions yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export const RECURSIVE_PROOF_LENGTH = 439;
export const NESTED_RECURSIVE_PROOF_LENGTH = 439;
export const TUBE_PROOF_LENGTH = 439;
export const VERIFICATION_KEY_LENGTH_IN_FIELDS = 128;
export const AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS = 66;
export const SENDER_SELECTOR = 0;
export const ADDRESS_SELECTOR = 1;
export const STORAGE_ADDRESS_SELECTOR = 1;
Expand Down
Loading

0 comments on commit 0e1411c

Please sign in to comment.