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: Empty block root circuit #8805

Merged
merged 2 commits into from
Sep 26, 2024
Merged
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
3 changes: 2 additions & 1 deletion l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ library Constants {
uint256 internal constant BLOCK_ROOT_ROLLUP_INDEX = 22;
uint256 internal constant BLOCK_MERGE_ROLLUP_INDEX = 23;
uint256 internal constant ROOT_ROLLUP_INDEX = 24;
uint256 internal constant BLOCK_ROOT_ROLLUP_FINAL_INDEX = 25;
uint256 internal constant BLOCK_ROOT_ROLLUP_EMPTY_INDEX = 25;
uint256 internal constant BLOCK_ROOT_ROLLUP_FINAL_INDEX = 26;
uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4;
uint256 internal constant INITIALIZATION_SLOT_SEPARATOR = 1000000000;
uint256 internal constant INITIAL_L2_BLOCK_NUM = 1;
Expand Down
1 change: 1 addition & 0 deletions noir-projects/noir-protocol-circuits/Nargo.template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ members = [
"crates/rollup-base-simulated",
"crates/rollup-block-merge",
"crates/rollup-block-root",
"crates/rollup-block-root-empty",
"crates/rollup-block-root-final",
"crates/rollup-root",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "rollup_block_root_empty"
type = "bin"
authors = [""]
compiler_version = ">=0.18.0"

[dependencies]
rollup_lib = { path = "../rollup-lib" }
types = { path = "../types" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use rollup_lib::block_root::{EmptyBlockRootRollupInputs, BlockRootOrBlockMergePublicInputs};

#[recursive]
fn main(inputs: EmptyBlockRootRollupInputs) -> pub BlockRootOrBlockMergePublicInputs {
inputs.empty_block_root_rollup_circuit()
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ pub struct BlockRootOrBlockMergePublicInputs {
prover_id: Field, // TODO(#7346): Temporarily added prover_id while we verify block-root proofs on L1
}

impl BlockRootOrBlockMergePublicInputs {
fn is_padding(self) -> bool {
self.previous_archive == self.new_archive
}
}

impl Empty for BlockRootOrBlockMergePublicInputs {
fn empty() -> Self {
BlockRootOrBlockMergePublicInputs {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs;
use types::{abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, global_variables::GlobalVariables}};
use crate::abis::block_root_or_block_merge_public_inputs::FeeRecipient;

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,
}

impl EmptyBlockRootRollupInputs {
pub fn empty_block_root_rollup_circuit(self) -> BlockRootOrBlockMergePublicInputs {
BlockRootOrBlockMergePublicInputs {
previous_archive: self.archive,
new_archive: self.archive,
previous_block_hash: self.block_hash,
end_block_hash: self.block_hash,
start_global_variables: self.global_variables,
end_global_variables: self.global_variables,
out_hash: self.out_hash,
fees: [FeeRecipient::empty(); 32],
vk_tree_root: self.vk_tree_root,
prover_id: self.prover_id
}
}
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod block_root_rollup_inputs;
mod empty_block_root_rollup_inputs;

// Re-exports
pub use block_root_rollup_inputs::BlockRootRollupInputs;
pub use empty_block_root_rollup_inputs::EmptyBlockRootRollupInputs;
pub use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs;

mod tests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,22 @@ pub fn assert_prev_block_rollups_follow_on_from_each_other(
assert(
left.end_global_variables.version == right.start_global_variables.version, "input blocks have different chain version"
);
assert(
left.end_global_variables.block_number + 1 == right.start_global_variables.block_number, "input block numbers do not follow on from each other"
);
assert(
left.end_global_variables.timestamp < right.start_global_variables.timestamp, "input block timestamps do not follow on from each other"
);

if right.is_padding() {
assert(
left.end_global_variables.block_number == right.start_global_variables.block_number, "input block numbers do not match"
);
assert(
left.end_global_variables.timestamp == right.start_global_variables.timestamp, "input block timestamps do not match"
);
} else {
assert(
left.end_global_variables.block_number + 1 == right.start_global_variables.block_number, "input block numbers do not follow on from each other"
);
assert(
left.end_global_variables.timestamp < right.start_global_variables.timestamp, "input block timestamps do not follow on from each other"
);
}
}

pub fn accumulate_fees(left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs) -> Field {
Expand Down Expand Up @@ -134,12 +144,16 @@ pub fn compute_out_hash(previous_rollup_data: [PreviousRollupData; 2]) -> Field
}
// TODO(Miranda): combine fns?
pub fn compute_blocks_out_hash(previous_rollup_data: [PreviousRollupBlockData; 2]) -> Field {
accumulate_sha256(
[
previous_rollup_data[0].block_root_or_block_merge_public_inputs.out_hash,
previous_rollup_data[1].block_root_or_block_merge_public_inputs.out_hash
]
)
if previous_rollup_data[1].block_root_or_block_merge_public_inputs.is_padding() {
previous_rollup_data[0].block_root_or_block_merge_public_inputs.out_hash
} else {
accumulate_sha256(
[
previous_rollup_data[0].block_root_or_block_merge_public_inputs.out_hash,
previous_rollup_data[1].block_root_or_block_merge_public_inputs.out_hash
]
)
}
}

pub fn compute_kernel_out_hash(l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX]) -> Field {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ global MERGE_ROLLUP_INDEX: u32 = 21;
global BLOCK_ROOT_ROLLUP_INDEX: u32 = 22;
global BLOCK_MERGE_ROLLUP_INDEX: u32 = 23;
global ROOT_ROLLUP_INDEX: u32 = 24;
global BLOCK_ROOT_ROLLUP_FINAL_INDEX: u32 = 25;
global BLOCK_ROOT_ROLLUP_EMPTY_INDEX: u32 = 25;
global BLOCK_ROOT_ROLLUP_FINAL_INDEX: u32 = 26;

// MISC CONSTANTS
global FUNCTION_SELECTOR_NUM_BYTES: Field = 4;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::constants::{
EMPTY_NESTED_INDEX, PRIVATE_KERNEL_EMPTY_INDEX, PUBLIC_KERNEL_INNER_INDEX,
PUBLIC_KERNEL_MERGE_INDEX, PUBLIC_KERNEL_TAIL_INDEX, BASE_PARITY_INDEX, ROOT_PARITY_INDEX,
BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_INDEX, BLOCK_MERGE_ROLLUP_INDEX,
ROOT_ROLLUP_INDEX, PRIVATE_KERNEL_RESET_TINY_INDEX, BLOCK_ROOT_ROLLUP_FINAL_INDEX
ROOT_ROLLUP_INDEX, PRIVATE_KERNEL_RESET_TINY_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX,
BLOCK_ROOT_ROLLUP_FINAL_INDEX
};
use crate::merkle_tree::merkle_tree::MerkleTree;

Expand Down Expand Up @@ -41,7 +42,8 @@ pub fn get_vk_merkle_tree() -> MerkleTree<VK_TREE_WIDTH> {
leaves[BLOCK_ROOT_ROLLUP_INDEX] = 22;
leaves[BLOCK_MERGE_ROLLUP_INDEX] = 23;
leaves[ROOT_ROLLUP_INDEX] = 24;
leaves[BLOCK_ROOT_ROLLUP_FINAL_INDEX] = 25;
leaves[BLOCK_ROOT_ROLLUP_EMPTY_INDEX] = 25;
leaves[BLOCK_ROOT_ROLLUP_FINAL_INDEX] = 26;

MerkleTree::new(leaves)
}
25 changes: 25 additions & 0 deletions yarn-project/bb-prover/src/prover/bb_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
type BlockMergeRollupInputs,
type BlockRootOrBlockMergePublicInputs,
type BlockRootRollupInputs,
type EmptyBlockRootRollupInputs,
EmptyNestedCircuitInputs,
EmptyNestedData,
Fr,
Expand Down Expand Up @@ -57,6 +58,7 @@ import {
convertBlockMergeRollupOutputsFromWitnessMap,
convertBlockRootRollupInputsToWitnessMap,
convertBlockRootRollupOutputsFromWitnessMap,
convertEmptyBlockRootRollupInputsToWitnessMap,
convertMergeRollupInputsToWitnessMap,
convertMergeRollupOutputsFromWitnessMap,
convertPrivateKernelEmptyInputsToWitnessMap,
Expand Down Expand Up @@ -380,6 +382,29 @@ export class BBNativeRollupProver implements ServerCircuitProver {
return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
}

/**
* Simulates the empty block root rollup circuit from its inputs.
* @param input - Inputs to the circuit.
* @returns The public inputs as outputs of the simulation.
*/
public async getEmptyBlockRootRollupProof(
input: EmptyBlockRootRollupInputs,
): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
const { circuitOutput, proof } = await this.createRecursiveProof(
input,
'EmptyBlockRootRollupArtifact',
RECURSIVE_PROOF_LENGTH,
convertEmptyBlockRootRollupInputsToWitnessMap,
convertBlockRootRollupOutputsFromWitnessMap,
);

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

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

return makePublicInputsAndRecursiveProof(circuitOutput, proof, verificationKey);
}

/**
* Simulates the block root rollup circuit from its inputs.
* Returns a non-recursive proof to verify on L1.
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/bb-prover/src/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export function mapProtocolArtifactNameToCircuitName(
return 'merge-rollup';
case 'BlockRootRollupArtifact':
return 'block-root-rollup';
case 'EmptyBlockRootRollupArtifact':
return 'empty-block-root-rollup';
case 'BlockMergeRollupArtifact':
return 'block-merge-rollup';
case 'RootRollupArtifact':
Expand Down
37 changes: 37 additions & 0 deletions yarn-project/bb-prover/src/test/test_circuit_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
type BlockMergeRollupInputs,
type BlockRootOrBlockMergePublicInputs,
type BlockRootRollupInputs,
type EmptyBlockRootRollupInputs,
EmptyNestedData,
type KernelCircuitPublicInputs,
type MergeRollupInputs,
Expand Down Expand Up @@ -52,6 +53,7 @@ import {
convertBlockMergeRollupOutputsFromWitnessMap,
convertBlockRootRollupInputsToWitnessMap,
convertBlockRootRollupOutputsFromWitnessMap,
convertEmptyBlockRootRollupInputsToWitnessMap,
convertMergeRollupInputsToWitnessMap,
convertMergeRollupOutputsFromWitnessMap,
convertPrivateKernelEmptyInputsToWitnessMap,
Expand Down Expand Up @@ -347,6 +349,41 @@ export class TestCircuitProver implements ServerCircuitProver {
);
}

/**
* Simulates the empty block root rollup circuit from its inputs.
* @param input - Inputs to the circuit.
* @returns The public inputs as outputs of the simulation.
*/
@trackSpan('TestCircuitProver.getEmptyBlockRootRollupProof')
public async getEmptyBlockRootRollupProof(
input: EmptyBlockRootRollupInputs,
): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
const timer = new Timer();
const witnessMap = convertEmptyBlockRootRollupInputsToWitnessMap(input);

// use WASM here as it is faster for small circuits
const witness = await this.wasmSimulator.simulateCircuit(
witnessMap,
SimulatedServerCircuitArtifacts.EmptyBlockRootRollupArtifact,
);

const result = convertBlockRootRollupOutputsFromWitnessMap(witness);

this.instrumentation.recordDuration('simulationDuration', 'empty-block-root-rollup', timer);
emitCircuitSimulationStats(
'empty-block-root-rollup',
timer.ms(),
input.toBuffer().length,
result.toBuffer().length,
this.logger,
);
return makePublicInputsAndRecursiveProof(
result,
makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH),
ProtocolCircuitVks['EmptyBlockRootRollupArtifact'],
);
}

public getBlockRootRollupFinalProof(
input: BlockRootRollupInputs,
): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
Expand Down
9 changes: 9 additions & 0 deletions yarn-project/circuit-types/src/interfaces/proving-job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
type BlockMergeRollupInputs,
type BlockRootOrBlockMergePublicInputs,
type BlockRootRollupInputs,
type EmptyBlockRootRollupInputs,
type KernelCircuitPublicInputs,
type MergeRollupInputs,
type NESTED_RECURSIVE_PROOF_LENGTH,
Expand Down Expand Up @@ -75,6 +76,7 @@ export enum ProvingRequestType {

BASE_ROLLUP,
MERGE_ROLLUP,
EMPTY_BLOCK_ROOT_ROLLUP,
BLOCK_ROOT_ROLLUP,
BLOCK_ROOT_ROLLUP_FINAL,
BLOCK_MERGE_ROLLUP,
Expand Down Expand Up @@ -102,6 +104,8 @@ export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): Ci
return 'base-rollup';
case ProvingRequestType.MERGE_ROLLUP:
return 'merge-rollup';
case ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP:
return 'empty-block-root-rollup';
case ProvingRequestType.BLOCK_ROOT_ROLLUP:
return 'block-root-rollup';
case ProvingRequestType.BLOCK_ROOT_ROLLUP_FINAL:
Expand Down Expand Up @@ -164,6 +168,10 @@ export type ProvingRequest =
type: ProvingRequestType.BLOCK_ROOT_ROLLUP;
inputs: BlockRootRollupInputs;
}
| {
type: ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP;
inputs: EmptyBlockRootRollupInputs;
}
| {
type: ProvingRequestType.BLOCK_ROOT_ROLLUP_FINAL;
inputs: BlockRootRollupInputs;
Expand Down Expand Up @@ -195,6 +203,7 @@ export type ProvingRequestPublicInputs = {

[ProvingRequestType.BASE_ROLLUP]: PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>;
[ProvingRequestType.MERGE_ROLLUP]: PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>;
[ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>;
[ProvingRequestType.BLOCK_ROOT_ROLLUP]: PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>;
[ProvingRequestType.BLOCK_ROOT_ROLLUP_FINAL]: PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>;
[ProvingRequestType.BLOCK_MERGE_ROLLUP]: PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>;
Expand Down
11 changes: 11 additions & 0 deletions yarn-project/circuit-types/src/interfaces/server_circuit_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
type BlockMergeRollupInputs,
type BlockRootOrBlockMergePublicInputs,
type BlockRootRollupInputs,
type EmptyBlockRootRollupInputs,
type KernelCircuitPublicInputs,
type MergeRollupInputs,
type NESTED_RECURSIVE_PROOF_LENGTH,
Expand Down Expand Up @@ -105,6 +106,16 @@ export interface ServerCircuitProver {
epochNumber?: number,
): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>>;

/**
* Creates a proof for the given input.
* @param input - Input to the circuit.
*/
getEmptyBlockRootRollupProof(
input: EmptyBlockRootRollupInputs,
signal?: AbortSignal,
epochNumber?: number,
): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>>;

/**
* Creates a proof for the given input.
* @param input - Input to the circuit.
Expand Down
1 change: 1 addition & 0 deletions yarn-project/circuit-types/src/stats/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export type CircuitName =
| 'base-rollup'
| 'merge-rollup'
| 'block-root-rollup'
| 'empty-block-root-rollup'
| 'block-root-rollup-final'
| 'block-merge-rollup'
| 'root-rollup'
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ export const MERGE_ROLLUP_INDEX = 21;
export const BLOCK_ROOT_ROLLUP_INDEX = 22;
export const BLOCK_MERGE_ROLLUP_INDEX = 23;
export const ROOT_ROLLUP_INDEX = 24;
export const BLOCK_ROOT_ROLLUP_FINAL_INDEX = 25;
export const BLOCK_ROOT_ROLLUP_EMPTY_INDEX = 25;
export const BLOCK_ROOT_ROLLUP_FINAL_INDEX = 26;
export const FUNCTION_SELECTOR_NUM_BYTES = 4;
export const INITIALIZATION_SLOT_SEPARATOR = 1000000000;
export const INITIAL_L2_BLOCK_NUM = 1;
Expand Down
1 change: 1 addition & 0 deletions yarn-project/circuits.js/src/structs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export * from './rollup/base_or_merge_rollup_public_inputs.js';
export * from './rollup/base_rollup.js';
export * from './rollup/block_merge_rollup.js';
export * from './rollup/block_root_or_block_merge_public_inputs.js';
export * from './rollup/empty_block_root_rollup_inputs.js';
export * from './rollup/block_root_rollup.js';
export * from './rollup/merge_rollup.js';
export * from './rollup/previous_rollup_block_data.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { makeEmptyBlockRootRollupInputs } from '../../tests/factories.js';
import { EmptyBlockRootRollupInputs } from './empty_block_root_rollup_inputs.js';

describe('EmptyBlockRootRollupInputs', () => {
it(`serializes a EmptyBlockRootRollupInputs to buffer and deserializes it back`, () => {
const expected = makeEmptyBlockRootRollupInputs();
const buffer = expected.toBuffer();
const res = EmptyBlockRootRollupInputs.fromBuffer(buffer);
expect(res).toEqual(expected);
});

it(`serializes a EmptyBlockRootRollupInputs to hex string and deserializes it back`, () => {
const expected = makeEmptyBlockRootRollupInputs();
const str = expected.toString();
const res = EmptyBlockRootRollupInputs.fromString(str);
expect(res).toEqual(expected);
});
});
Loading
Loading