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

chore: aggregation client tweaks #84

Merged
merged 4 commits into from
Aug 30, 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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/zkconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"finalizationPeriod": 0,
"chainId": 11155420,
"owner": "0xDEd0000E32f8F40414d3ab3a830f735a3553E18e",
"vkey": "0x001f78c9aacd8d2d9ba9132f9e2640f4db8d8db05b4862df2f5140f4a3db508f",
"vkey": "0x0010ea62be193a3c288183b203657e75184b8b92d5f872a25e2ff065d5e9c84d",
"verifierGateway": "0x3B6041173B80E77f038f3F2C0f9744f04837185e",
"l2OutputOracleProxy": "0x863508f057c09f7b94e582d74404859ecd36a306"
}
Binary file modified elf/aggregation-elf
Binary file not shown.
Binary file modified elf/range-elf
Binary file not shown.
1 change: 1 addition & 0 deletions programs/aggregation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ op-succinct-client-utils = { workspace = true }
alloy-consensus = { workspace = true }
alloy-primitives = { workspace = true }
serde_cbor.workspace = true
itertools.workspace = true
100 changes: 49 additions & 51 deletions programs/aggregation/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,99 +1,97 @@
//! A simple program that aggregates the proofs of multiple programs proven with the zkVM.
//! A program that aggregates the proofs of the multi-block program.

#![cfg_attr(target_os = "zkvm", no_main)]
#[cfg(target_os = "zkvm")]
sp1_zkvm::entrypoint!(main);

use std::collections::HashMap;

use alloy_consensus::Header;
use alloy_primitives::B256;
use itertools::Itertools;
use op_succinct_client_utils::{types::AggregationInputs, RawBootInfo};
use sha2::{Digest, Sha256};
use std::collections::HashMap;

/// Note: This is the hardcoded program vkey for the multi-block program. Whenever the multi-block
/// program changes, update this.
/// TODO: The aggregation program should take in an arbitrary vkey digest, and the smart contract
/// The verification key for the multi-block program.
///
/// Whenever the multi-block program changes, you will need to update this.
///
/// TODO: The aggregation program should take in an arbitrary vkey digest and the smart contract
/// should verify the proof matches the arbitrary vkey digest stored in the contract. This means
/// that the aggregate program would no longer need to update this value.
const MULTI_BLOCK_PROGRAM_VKEY_DIGEST: [u32; 8] =
[1172625895, 1280247262, 651076015, 321432881, 243715685, 1565992912, 1444792760, 1908047081];

/// Verify that the L1 heads in the boot infos are in the header chain.
fn verify_l1_heads(agg_inputs: &AggregationInputs, headers: &[Header]) {
// Create a map of each l1_head in the BootInfo's to booleans
let mut l1_heads_map: HashMap<B256, bool> =
agg_inputs.boot_infos.iter().map(|boot_info| (boot_info.l1_head, false)).collect();

// Iterate through all headers in the chain.
let mut current_hash = agg_inputs.latest_l1_checkpoint_head;
// Iterate through the headers in reverse order. The headers should be sequentially linked and
// include the L1 head of each boot info.
for header in headers.iter().rev() {
assert_eq!(current_hash, header.hash_slow());

// Mark the l1_head as found if it's in our map
if let Some(found) = l1_heads_map.get_mut(&current_hash) {
*found = true;
}

current_hash = header.parent_hash;
}

// Check if all l1_heads were found in the chain.
for (l1_head, found) in l1_heads_map.iter() {
assert!(*found, "L1 head {:?} not found in the provided header chain", l1_head);
}
}
[1807316243, 1400630407, 873277975, 658999266, 422343326, 774525422, 1268417967, 711858264];

pub fn main() {
// Read in the public values corresponding to each multi-block proof.
fn main() {
// Read in the aggregation inputs corresponding to each multi-block proof.
let agg_inputs = sp1_zkvm::io::read::<AggregationInputs>();
// Note: The headers are in order from start to end. We use serde_cbor as bincode serialization
// causes issues with the zkVM.

// Read in the headers.
//
// Note: The headers are in order from start to end. We use [serde_cbor] as bincode
// serialization causes issues with the zkVM.
let headers_bytes = sp1_zkvm::io::read_vec();
let headers: Vec<Header> = serde_cbor::from_slice(&headers_bytes).unwrap();
assert!(!agg_inputs.boot_infos.is_empty());

// Confirm that the boot infos are sequential.
agg_inputs.boot_infos.windows(2).for_each(|pair| {
let (prev_boot_info, boot_info) = (&pair[0], &pair[1]);

// The claimed block of the previous boot info must be the L2 output root of the current
agg_inputs.boot_infos.iter().tuples().for_each(|(prev_boot_info, curr_boot_info)| {
// The claimed block of the previous boot info must be the l2 output root of the current
// boot.
assert_eq!(prev_boot_info.l2_claim, boot_info.l2_output_root);
assert_eq!(prev_boot_info.l2_claim, curr_boot_info.l2_output_root);

// The chain ID must be the same for all the boot infos, to ensure they're
// The chain id must be the same for all the boot infos, to ensure they're
// from the same chain and span batch range.
assert_eq!(prev_boot_info.chain_id, boot_info.chain_id);
assert_eq!(prev_boot_info.chain_id, curr_boot_info.chain_id);
});

// Verify each multi-block program proof.
agg_inputs.boot_infos.iter().for_each(|boot_info| {
// In the multi-block program, the public values digest is just the hash of the ABI encoded
// boot info.
// Compute the public values digest as the hash of the abi-encoded [`RawBootInfo`].
let abi_encoded_boot_info = boot_info.abi_encode();
let pv_digest = Sha256::digest(abi_encoded_boot_info);

// Verify the proof against the public values digest.
if cfg!(target_os = "zkvm") {
sp1_lib::verify::verify_sp1_proof(&MULTI_BLOCK_PROGRAM_VKEY_DIGEST, &pv_digest.into());
}
});

// Verify the L1 heads of each boot info are on the L1.
verify_l1_heads(&agg_inputs, &headers);
// Create a map of each l1 head in the [`RawBootInfo`]s to booleans
let mut l1_heads_map: HashMap<B256, bool> =
agg_inputs.boot_infos.iter().map(|boot_info| (boot_info.l1_head, false)).collect();

// Iterate through the headers in reverse order. The headers should be sequentially linked and
// include the l1 head of each boot info.
let mut current_hash = agg_inputs.latest_l1_checkpoint_head;
for header in headers.iter().rev() {
assert_eq!(current_hash, header.hash_slow());

// Mark the l1 head as found if it's in our map.
if let Some(found) = l1_heads_map.get_mut(&current_hash) {
*found = true;
}

current_hash = header.parent_hash;
}

// Check if all l1 heads were found in the chain.
for (l1_head, found) in l1_heads_map.iter() {
assert!(*found, "l1 head {:?} not found in the provided header chain", l1_head);
}

let first_boot_info = &agg_inputs.boot_infos[0];
let last_boot_info = &agg_inputs.boot_infos[agg_inputs.boot_infos.len() - 1];
// Consolidate the boot info into a single BootInfo struct that represents the range proven.

// Consolidate the boot info into an aggregated [`RawBootInfo`] that proves the range.
let final_boot_info = RawBootInfo {
// The first boot info's L2 output root is the L2 output root of the range.
l2_output_root: first_boot_info.l2_output_root,
l2_claim_block: last_boot_info.l2_claim_block,
l2_claim: last_boot_info.l2_claim,
l1_head: agg_inputs.latest_l1_checkpoint_head,
chain_id: last_boot_info.chain_id,
};

// Commit to the aggregated boot info.
// Commit to the aggregated [`RawBootInfo`].
sp1_zkvm::io::commit_slice(&final_boot_info.abi_encode());
}
2 changes: 1 addition & 1 deletion proposer/succinct/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn build_native_host_runner() {
// /// Build a program for the zkVM.
// fn build_zkvm_program(program: &str) {
// build_program_with_args(
// &format!("../programs/{}", program),
// &format!("../../programs/{}", program),
// BuildArgs {
// elf_name: format!("{}-elf", program),
// // docker: true,
Expand Down
2 changes: 1 addition & 1 deletion scripts/prove/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// /// Build a program for the zkVM.
// fn build_zkvm_program(program: &str) {
// build_program_with_args(
// &format!("../programs/{}", program),
// &format!("../../programs/{}", program),
// BuildArgs {
// elf_name: format!("{}-elf", program),
// // docker: true,
Expand Down
Loading