Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Pad epochs with empty blocks #8842

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading