Skip to content

Commit

Permalink
feat: Prover node submits epoch proofs (#8794)
Browse files Browse the repository at this point in the history
Prover node now submits epoch proofs instead of block root proofs. Epoch
length is configurable for now. Adds a new empty block root rollup
circuit to pad epochs with a single block.
  • Loading branch information
spalladino authored and Rumata888 committed Sep 27, 2024
1 parent 3846536 commit 5fdbb76
Show file tree
Hide file tree
Showing 47 changed files with 689 additions and 520 deletions.
41 changes: 29 additions & 12 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
IProofCommitmentEscrow public immutable PROOF_COMMITMENT_ESCROW;
uint256 public immutable VERSION;
IFeeJuicePortal public immutable FEE_JUICE_PORTAL;
IVerifier public verifier;
IVerifier public blockProofVerifier;

ChainTips public tips;
DataStructures.EpochProofClaim public proofClaim;
Expand All @@ -80,14 +80,19 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
// Testing only. This should be removed eventually.
uint256 private assumeProvenThroughBlockNumber;

// Listed at the end of the contract to avoid changing storage slots
// TODO(palla/prover) Drop blockProofVerifier and move this verifier to that slot
IVerifier public epochProofVerifier;

constructor(
IRegistry _registry,
IFeeJuicePortal _fpcJuicePortal,
bytes32 _vkTreeRoot,
address _ares,
address[] memory _validators
) Leonidas(_ares) {
verifier = new MockVerifier();
blockProofVerifier = new MockVerifier();
epochProofVerifier = new MockVerifier();
REGISTRY = _registry;
FEE_JUICE_PORTAL = _fpcJuicePortal;
PROOF_COMMITMENT_ESCROW = new MockProofCommitmentEscrow();
Expand All @@ -100,7 +105,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
// Genesis block
blocks[0] = BlockLog({
archive: bytes32(Constants.GENESIS_ARCHIVE_ROOT),
blockHash: bytes32(0),
blockHash: bytes32(0), // TODO(palla/prover): The first block does not have hash zero
slotNumber: Slot.wrap(0)
});
for (uint256 i = 0; i < _validators.length; i++) {
Expand Down Expand Up @@ -144,8 +149,19 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
*
* @param _verifier - The new verifier contract
*/
function setVerifier(address _verifier) external override(ITestRollup) onlyOwner {
verifier = IVerifier(_verifier);
function setBlockVerifier(address _verifier) external override(ITestRollup) onlyOwner {
blockProofVerifier = IVerifier(_verifier);
}

/**
* @notice Set the verifier contract
*
* @dev This is only needed for testing, and should be removed
*
* @param _verifier - The new verifier contract
*/
function setEpochVerifier(address _verifier) external override(ITestRollup) onlyOwner {
epochProofVerifier = IVerifier(_verifier);
}

/**
Expand Down Expand Up @@ -410,7 +426,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
publicInputs[i + 91] = part;
}

if (!verifier.verify(_proof, publicInputs)) {
if (!blockProofVerifier.verify(_proof, publicInputs)) {
revert Errors.Rollup__InvalidProof();
}

Expand Down Expand Up @@ -484,7 +500,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
bytes32[] memory publicInputs =
getEpochProofPublicInputs(_epochSize, _args, _fees, _aggregationObject);

if (!verifier.verify(_proof, publicInputs)) {
if (!epochProofVerifier.verify(_proof, publicInputs)) {
revert Errors.Rollup__InvalidProof();
}

Expand Down Expand Up @@ -550,7 +566,8 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
}

bytes32 expectedPreviousBlockHash = blocks[previousBlockNumber].blockHash;
if (expectedPreviousBlockHash != _args[2]) {
// TODO: Remove 0 check once we inject the proper genesis block hash
if (expectedPreviousBlockHash != 0 && expectedPreviousBlockHash != _args[2]) {
revert Errors.Rollup__InvalidPreviousBlockHash(expectedPreviousBlockHash, _args[2]);
}

Expand Down Expand Up @@ -608,16 +625,16 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
// out_hash: root of this epoch's l2 to l1 message tree
publicInputs[8] = _args[5];

// fees[9-40]: array of recipient-value pairs
// fees[9-72]: array of recipient-value pairs
for (uint256 i = 0; i < 64; i++) {
publicInputs[9 + i] = _fees[i];
}

// vk_tree_root
publicInputs[41] = vkTreeRoot;
publicInputs[73] = vkTreeRoot;

// prover_id: id of current epoch's prover
publicInputs[42] = _args[6];
publicInputs[74] = _args[6];

// the block proof is recursive, which means it comes with an aggregation object
// this snippet copies it into the public inputs needed for verification
Expand All @@ -628,7 +645,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup {
assembly {
part := calldataload(add(_aggregationObject.offset, mul(i, 32)))
}
publicInputs[i + 43] = part;
publicInputs[i + 75] = part;
}

return publicInputs;
Expand Down
3 changes: 2 additions & 1 deletion l1-contracts/src/core/interfaces/IRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeMath.sol";

interface ITestRollup {
function setVerifier(address _verifier) external;
function setBlockVerifier(address _verifier) external;
function setEpochVerifier(address _verifier) external;
function setVkTreeRoot(bytes32 _vkTreeRoot) external;
function setAssumeProvenThroughBlockNumber(uint256 blockNumber) external;
}
Expand Down
9 changes: 5 additions & 4 deletions l1-contracts/test/Rollup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -671,10 +671,11 @@ contract RollupTest is DecoderBase {
);
_submitEpochProof(rollup, 1, wrong, data.archive, preBlockHash, data.blockHash, bytes32(0));

vm.expectRevert(
abi.encodeWithSelector(Errors.Rollup__InvalidPreviousBlockHash.selector, preBlockHash, wrong)
);
_submitEpochProof(rollup, 1, preArchive, data.archive, wrong, data.blockHash, bytes32(0));
// TODO: Reenable when we setup proper initial block hash
// vm.expectRevert(
// abi.encodeWithSelector(Errors.Rollup__InvalidPreviousBlockHash.selector, preBlockHash, wrong)
// );
// _submitEpochProof(rollup, 1, preArchive, data.archive, wrong, data.blockHash, bytes32(0));
}

function testSubmitProofInvalidArchive() public setUpFor("empty_block_1") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub struct EmptyBlockRootRollupInputs {
archive: AppendOnlyTreeSnapshot,
block_hash: Field,
global_variables: GlobalVariables,
out_hash: Field,
vk_tree_root: Field,
// TODO(#7346): Temporarily added prover_id while we verify block-root proofs on L1
prover_id: Field,
Expand All @@ -21,7 +20,7 @@ impl EmptyBlockRootRollupInputs {
end_block_hash: self.block_hash,
start_global_variables: self.global_variables,
end_global_variables: self.global_variables,
out_hash: self.out_hash,
out_hash: 0, // out_hash is ignored when merging if the block proof is padding
fees: [FeeRecipient::empty(); 32],
vk_tree_root: self.vk_tree_root,
prover_id: self.prover_id
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ boxes/*/src/artifacts/*.json
boxes/*/src/artifacts/*.ts
boxes/*/src/contracts/target/*.json
*.md
end-to-end/src/fixtures/dumps/block_result.json
end-to-end/src/fixtures/dumps/*.json
12 changes: 6 additions & 6 deletions yarn-project/bb-prover/src/honk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ const UltraKeccakHonkCircuits = [
'BlockRootRollupFinalArtifact',
'RootRollupArtifact',
] as const satisfies ProtocolArtifact[];
type UltraKeccakHonkCircuits = (typeof UltraKeccakHonkCircuits)[number];
type UltraHonkCircuits = Exclude<ProtocolArtifact, UltraKeccakHonkCircuits>;
export type UltraKeccakHonkProtocolArtifact = (typeof UltraKeccakHonkCircuits)[number];
export type UltraHonkProtocolArtifact = Exclude<ProtocolArtifact, UltraKeccakHonkProtocolArtifact>;

export function getUltraHonkFlavorForCircuit(artifact: UltraKeccakHonkCircuits): 'ultra_keccak_honk';
export function getUltraHonkFlavorForCircuit(artifact: UltraHonkCircuits): 'ultra_honk';
export function getUltraHonkFlavorForCircuit(artifact: UltraKeccakHonkProtocolArtifact): 'ultra_keccak_honk';
export function getUltraHonkFlavorForCircuit(artifact: UltraHonkProtocolArtifact): '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);
function isUltraKeccakHonkCircuit(artifact: ProtocolArtifact): artifact is UltraKeccakHonkProtocolArtifact {
return UltraKeccakHonkCircuits.includes(artifact as UltraKeccakHonkProtocolArtifact);
}
1 change: 1 addition & 0 deletions yarn-project/bb-prover/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './test/index.js';
export * from './verifier/index.js';
export * from './config.js';
export * from './bb/execute.js';
export * from './honk.js';

export { type ClientProtocolCircuitVerifier } from '@aztec/circuit-types';
7 changes: 4 additions & 3 deletions yarn-project/bb-prover/src/prover/bb_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
convertBlockRootRollupInputsToWitnessMap,
convertBlockRootRollupOutputsFromWitnessMap,
convertEmptyBlockRootRollupInputsToWitnessMap,
convertEmptyBlockRootRollupOutputsFromWitnessMap,
convertMergeRollupInputsToWitnessMap,
convertMergeRollupOutputsFromWitnessMap,
convertPrivateKernelEmptyInputsToWitnessMap,
Expand Down Expand Up @@ -395,12 +396,12 @@ export class BBNativeRollupProver implements ServerCircuitProver {
'EmptyBlockRootRollupArtifact',
RECURSIVE_PROOF_LENGTH,
convertEmptyBlockRootRollupInputsToWitnessMap,
convertBlockRootRollupOutputsFromWitnessMap,
convertEmptyBlockRootRollupOutputsFromWitnessMap,
);

const verificationKey = await this.getVerificationKeyDataForCircuit('BlockRootRollupArtifact');
const verificationKey = await this.getVerificationKeyDataForCircuit('EmptyBlockRootRollupArtifact');

await this.verifyProof('BlockRootRollupArtifact', proof.binaryProof);
await this.verifyProof('EmptyBlockRootRollupArtifact', proof.binaryProof);

return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
}
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/bb-prover/src/test/test_circuit_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
convertBlockRootRollupInputsToWitnessMap,
convertBlockRootRollupOutputsFromWitnessMap,
convertEmptyBlockRootRollupInputsToWitnessMap,
convertEmptyBlockRootRollupOutputsFromWitnessMap,
convertMergeRollupInputsToWitnessMap,
convertMergeRollupOutputsFromWitnessMap,
convertPrivateKernelEmptyInputsToWitnessMap,
Expand Down Expand Up @@ -367,7 +368,7 @@ export class TestCircuitProver implements ServerCircuitProver {
SimulatedServerCircuitArtifacts.EmptyBlockRootRollupArtifact,
);

const result = convertBlockRootRollupOutputsFromWitnessMap(witness);
const result = convertEmptyBlockRootRollupOutputsFromWitnessMap(witness);

this.instrumentation.recordDuration('simulationDuration', 'empty-block-root-rollup', timer);
emitCircuitSimulationStats(
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/bb-prover/src/verifier/bb_verifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
verifyProof,
} from '../bb/execute.js';
import { type BBConfig } from '../config.js';
import { getUltraHonkFlavorForCircuit } from '../honk.js';
import { type UltraKeccakHonkProtocolArtifact, getUltraHonkFlavorForCircuit } from '../honk.js';
import { mapProtocolArtifactNameToCircuitName } from '../stats.js';
import { extractVkData } from '../verification_key/verification_key_data.js';

Expand Down Expand Up @@ -127,7 +127,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier {
await runInDirectory(this.config.bbWorkingDirectory, operation, this.config.bbSkipCleanup);
}

public async generateSolidityContract(circuit: ProtocolArtifact, contractName: string) {
public async generateSolidityContract(circuit: UltraKeccakHonkProtocolArtifact, contractName: string) {
const result = await generateContractForCircuit(
this.config.bbBinaryPath,
this.config.bbWorkingDirectory,
Expand Down
8 changes: 7 additions & 1 deletion yarn-project/circuit-types/src/interfaces/block-prover.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type Fr, type GlobalVariables, type Proof } from '@aztec/circuits.js';
import { type Fr, type GlobalVariables, type Proof, type RootRollupPublicInputs } from '@aztec/circuits.js';

import { type L2Block } from '../l2_block.js';
import { type ProcessedTx } from '../tx/processed_tx.js';
Expand Down Expand Up @@ -32,6 +32,8 @@ export type ProvingBlockResult = SimulationBlockResult & {
aggregationObject: Fr[];
};

export type ProvingEpochResult = { publicInputs: RootRollupPublicInputs; proof: Proof };

/** Receives processed txs as part of block simulation or proving. */
export interface ProcessedTxHandler {
/**
Expand Down Expand Up @@ -75,4 +77,8 @@ export interface BlockProver extends BlockSimulator {

export interface EpochProver extends BlockProver {
startNewEpoch(epochNumber: number, totalNumBlocks: number): ProvingTicket;

setEpochCompleted(): void;

finaliseEpoch(): ProvingEpochResult;
}
7 changes: 3 additions & 4 deletions yarn-project/circuit-types/src/interfaces/prover-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type TxHash } from '@aztec/circuit-types';
import { Fr } from '@aztec/circuits.js';
import { type ConfigMappingsType, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';

import { type BlockProver } from './block-prover.js';
import { type EpochProver } from './block-prover.js';
import { type MerkleTreeOperations } from './merkle_tree_operations.js';
import { type ProvingJobSource } from './proving-job.js';

Expand Down Expand Up @@ -84,10 +84,9 @@ function parseProverId(str: string) {
/**
* The interface to the prover client.
* Provides the ability to generate proofs and build rollups.
* TODO(palla/prover-node): Rename this interface
*/
export interface ProverClient {
createBlockProver(db: MerkleTreeOperations): BlockProver;
export interface EpochProverManager {
createEpochProver(db: MerkleTreeOperations): EpochProver;

start(): Promise<void>;

Expand Down
7 changes: 7 additions & 0 deletions yarn-project/circuits.js/src/structs/proof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ export class Proof {
static fromString(str: string) {
return Proof.fromBuffer(Buffer.from(str, 'hex'));
}

/** Returns whether this proof is actually empty. */
public isEmpty() {
return (
this.buffer.length === EMPTY_PROOF_SIZE && this.buffer.every(byte => byte === 0) && this.numPublicInputs === 0
);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export class EmptyBlockRootRollupInputs {
public readonly archive: AppendOnlyTreeSnapshot,
public readonly blockHash: Fr,
public readonly globalVariables: GlobalVariables,
public readonly outHash: Fr,
public readonly vkTreeRoot: Fr,
// // TODO(#7346): Temporarily added prover_id while we verify block-root proofs on L1
public readonly proverId: Fr,
Expand Down Expand Up @@ -50,14 +49,7 @@ export class EmptyBlockRootRollupInputs {
* @returns An array of fields.
*/
static getFields(fields: FieldsOf<EmptyBlockRootRollupInputs>) {
return [
fields.archive,
fields.blockHash,
fields.globalVariables,
fields.outHash,
fields.vkTreeRoot,
fields.proverId,
] as const;
return [fields.archive, fields.blockHash, fields.globalVariables, fields.vkTreeRoot, fields.proverId] as const;
}

/**
Expand All @@ -73,7 +65,6 @@ export class EmptyBlockRootRollupInputs {
GlobalVariables.fromBuffer(reader),
Fr.fromBuffer(reader),
Fr.fromBuffer(reader),
Fr.fromBuffer(reader),
);
}

Expand Down
1 change: 0 additions & 1 deletion yarn-project/circuits.js/src/tests/factories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,6 @@ export function makeEmptyBlockRootRollupInputs(
globalVariables ?? makeGlobalVariables(seed + 0x200),
fr(seed + 0x300),
fr(seed + 0x400),
fr(seed + 0x500),
);
}

Expand Down
Loading

0 comments on commit 5fdbb76

Please sign in to comment.