Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alexghr committed Aug 30, 2024
1 parent 54c9de1 commit f046fdb
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 58 deletions.
9 changes: 4 additions & 5 deletions yarn-project/bb-prover/src/bb/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,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}/${flavor}/vk/${circuitName}`;
const circuitOutputDirectory = `${workingDirectory}/vk/${circuitName}`;
const outputPath = `${circuitOutputDirectory}`;
const bytecodeHash = sha256(bytecode);

Expand Down Expand Up @@ -277,7 +277,7 @@ export async function computeVerificationKey(
const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`;

// The verification key is written to this path
const outputPath = `${workingDirectory}/${flavor}/vk`;
const outputPath = `${workingDirectory}/vk`;

const binaryPresent = await fs
.access(pathToBB, fs.constants.R_OK)
Expand All @@ -296,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 Down Expand Up @@ -360,8 +360,7 @@ export async function generateProof(
const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`;

// The proof is written to e.g. /workingDirectory/ultra_honk/proof
const outputPath = `${workingDirectory}/${flavor}`;
await fs.mkdir(outputPath, { recursive: true });
const outputPath = `${workingDirectory}`;

const binaryPresent = await fs
.access(pathToBB, fs.constants.R_OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver {
directory,
circuitType,
bytecode,
'ultra_honk',
circuitType === 'App' ? 'ultra_honk' : getUltraHonkFlavorForCircuit(circuitType),
this.log.debug,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { L2Block, deployL1Contract, fileURLToPath } from '@aztec/aztec.js';
import { BBCircuitVerifier } from '@aztec/bb-prover';
import { AGGREGATION_OBJECT_LENGTH, Fr, HEADER_LENGTH, Proof } from '@aztec/circuits.js';
import { type L1ContractAddresses } from '@aztec/ethereum';
import { makeTuple } from '@aztec/foundation/array';
import { type Logger } from '@aztec/foundation/log';
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
import { AvailabilityOracleAbi, RollupAbi } from '@aztec/l1-artifacts';
Expand Down Expand Up @@ -34,6 +35,7 @@ import { getLogger, setupL1Contracts, startAnvil } from '../fixtures/utils.js';
describe('proof_verification', () => {
let proof: Proof;
let proverId: Fr;
let vkTreeRoot: Fr;
let block: L2Block;
let aggregationObject: Fr[];
let anvil: Anvil | undefined;
Expand All @@ -53,12 +55,14 @@ describe('proof_verification', () => {
if (!rpcUrl) {
({ anvil, rpcUrl } = await startAnvil());
}
logger.info('anvil done');

({ l1ContractAddresses, publicClient, walletClient } = await setupL1Contracts(
rpcUrl,
mnemonicToAccount(MNEMONIC),
logger,
));
logger.info('l1 contracts done');

const bb = await getBBConfig(logger);
const acvm = await getACVMConfig(logger);
Expand All @@ -70,12 +74,16 @@ describe('proof_verification', () => {

bbTeardown = bb!.cleanup;
acvmTeardown = acvm!.cleanup;
logger.info('bb, acvm done');

const content = await circuitVerifier.generateSolidityContract('BlockRootRollupArtifact', 'UltraHonkVerifier.sol');
logger.info('generated contract');

const input = {
language: 'Solidity',
sources: {
'UltraHonkVerifier.sol': {
content: await circuitVerifier.generateSolidityContract('BlockRootRollupArtifact', 'UltraHonkVerifier.sol'),
content,
},
},
settings: {
Expand All @@ -94,6 +102,7 @@ describe('proof_verification', () => {
};

const output = JSON.parse(solc.compile(JSON.stringify(input)));
logger.info('compiled contract');

const abi = output.contracts['UltraHonkVerifier.sol']['HonkVerifier'].abi;
const bytecode: string = output.contracts['UltraHonkVerifier.sol']['HonkVerifier'].evm.bytecode.object;
Expand All @@ -104,6 +113,7 @@ describe('proof_verification', () => {
client: publicClient,
abi,
}) as any;
logger.info('deployed verifier');
});

afterAll(async () => {
Expand All @@ -121,42 +131,82 @@ describe('proof_verification', () => {
);

block = L2Block.fromString(blockResult.block);
// TODO(#6624): Note that with honk proofs the below writes incorrect test data to file.
// The serialisation does not account for the prepended fields (circuit size, PI size, PI offset) in new Honk proofs, so the written data is shifted.
proof = Proof.fromString(blockResult.proof);
proverId = Fr.ZERO;
proverId = Fr.fromString(blockResult.proverId);
vkTreeRoot = Fr.fromString(blockResult.vkTreeRoot);
aggregationObject = blockResult.aggregationObject.map((x: string) => Fr.fromString(x));
});

describe('bb', () => {
describe.skip('bb', () => {
it('verifies proof', async () => {
await expect(circuitVerifier.verifyProofForCircuit('BlockRootRollupArtifact', proof)).resolves.toBeUndefined();
});
});
// TODO(#6624) & TODO(#7346): The below PIs do not correspond to BlockRoot/Root circuits.
// They will need to be updated to whichever circuit we are using when switching on this test.

describe('HonkVerifier', () => {
it('verifies full proof', async () => {
const reader = BufferReader.asReader(proof.buffer);
// +2 fields for archive
const archive = reader.readArray(2, Fr);
const header = reader.readArray(HEADER_LENGTH, Fr);
const aggObject = reader.readArray(AGGREGATION_OBJECT_LENGTH, Fr);
// skip proof size which is an uint32
const reader = BufferReader.asReader(proof.buffer.subarray(4));
const [circuitSize, numPublicInputs, publicInputsOffset] = reader.readArray(3, Fr);
const publicInputs = reader.readArray(numPublicInputs.toNumber(), Fr).map(x => x.toString());

console.log({
circuitSize: circuitSize.toString(),
numPublicInputs: numPublicInputs.toString(),
publicInputsOffset: publicInputsOffset.toString(),
binaryProofSize: proof.buffer.length,
publicInputsLength: publicInputs.length,
});

const publicInputs = [...archive, ...header, ...aggObject].map(x => x.toString());
const proofStr = `0x${Buffer.concat([
circuitSize.toBuffer(),
numPublicInputs.toBuffer(),
publicInputsOffset.toBuffer(),
reader.readToEnd(),
]).toString('hex')}` as const;

const proofStr = `0x${proof.buffer
.subarray((HEADER_LENGTH + 2 + AGGREGATION_OBJECT_LENGTH) * Fr.SIZE_IN_BYTES)
.toString('hex')}` as const;
// console.log(publicInputs);

await expect(verifierContract.read.verify([proofStr, publicInputs])).resolves.toBeTruthy();
});

it('verifies proof taking public inputs from block', async () => {
const proofStr = `0x${proof.withoutPublicInputs().toString('hex')}`;
const publicInputs = [...block.archive.toFields(), ...block.header.toFields(), ...aggregationObject].map(x =>
x.toString(),
);
const reader = BufferReader.asReader(proof.buffer.subarray(4));
const [circuitSize, numPublicInputs, publicInputsOffset] = reader.readArray(3, Fr);
const publicInputsFromProof = reader.readArray(numPublicInputs.toNumber(), Fr).map(x => x.toString());

const proofStr = `0x${Buffer.concat([
circuitSize.toBuffer(),
numPublicInputs.toBuffer(),
publicInputsOffset.toBuffer(),
reader.readToEnd(),
]).toString('hex')}` as const;

const publicInputs = [
block.header.lastArchive.root,
block.header.globalVariables.blockNumber,
block.archive.root,
new Fr(block.archive.nextAvailableLeafIndex),
Fr.ZERO, // prev block hash
block.hash(),
...block.header.globalVariables.toFields(), // start global vars
...block.header.globalVariables.toFields(), // end global vars
new Fr(block.header.contentCommitment.outHash),
block.header.globalVariables.coinbase.toField(), // the fee taker's address
block.header.totalFees, // how much they got
...Array(62).fill(Fr.ZERO), // 31 other (fee takers, fee) pairs
vkTreeRoot,
proverId, // 0x51
...aggregationObject,
].map((x: Fr) => x.toString());

console.log({ len: publicInputsFromProof.length, publicInputsFromProof });
console.log({ len: publicInputs.length, publicInputs });
expect(publicInputs.length).toEqual(publicInputsFromProof.length);
expect(publicInputs.slice(0, 27)).toEqual(publicInputsFromProof.slice(0, 27));
expect(publicInputs.slice(27, 89)).toEqual(publicInputsFromProof.slice(27, 89));
expect(publicInputs.slice(89, 91)).toEqual(publicInputsFromProof.slice(89, 91));
expect(publicInputs.slice(91)).toEqual(publicInputsFromProof.slice(91));

await expect(verifierContract.read.verify([proofStr, publicInputs])).resolves.toBeTruthy();
});
Expand Down
9 changes: 1 addition & 8 deletions yarn-project/end-to-end/src/e2e_prover/full.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,7 @@ describe('full_prover', () => {
}
// TODO(#6624): Note that with honk proofs the below writes incorrect test data to file.
// The serialisation does not account for the prepended fields (circuit size, PI size, PI offset) in new Honk proofs, so the written data is shifted.
writeTestData(
'yarn-project/end-to-end/src/fixtures/dumps/block_result.json',
JSON.stringify({
block: blockResult.block.toString(),
proof: blockResult.proof.toString(),
aggregationObject: blockResult.aggregationObject.map((x: Fr) => x.toString()),
}),
);
writeTestData('yarn-project/end-to-end/src/fixtures/dumps/block_result.json', JSON.stringify(blockResult));
}
},
TIMEOUT,
Expand Down
23 changes: 1 addition & 22 deletions yarn-project/end-to-end/src/fixtures/dumps/block_result.json

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions yarn-project/prover-client/src/orchestrator/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,8 @@ export class ProvingOrchestrator implements BlockProver {
};

pushTestData('blockResults', {
proverId: this.proverId.toString(),
vkTreeRoot: getVKTreeRoot().toString(),
block: l2Block.toString(),
proof: this.provingState.finalProof.toString(),
aggregationObject: blockResult.aggregationObject.map(x => x.toString()),
Expand Down Expand Up @@ -1156,9 +1158,10 @@ export class ProvingOrchestrator implements BlockProver {
}

function extractAggregationObject(proof: Proof, numPublicInputs: number): Fr[] {
// TODO (alexg) fix this
const buffer = proof.buffer.subarray(
Fr.SIZE_IN_BYTES * (numPublicInputs - AGGREGATION_OBJECT_LENGTH),
Fr.SIZE_IN_BYTES * numPublicInputs,
4 + Fr.SIZE_IN_BYTES * (3 + numPublicInputs - AGGREGATION_OBJECT_LENGTH),
4 + Fr.SIZE_IN_BYTES * (3 + numPublicInputs),
);
// TODO(#7159): Remove the following workaround
if (buffer.length === 0) {
Expand Down

0 comments on commit f046fdb

Please sign in to comment.