Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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 aggregation_mode/Cargo.lock

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

1 change: 1 addition & 0 deletions aggregation_mode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ sha3 = "0.10.8"
reqwest = { version = "0.12" }
ciborium = "=0.2.2"
lambdaworks-crypto = { git = "https://github.com/lambdaclass/lambdaworks.git", rev = "5f8f2cfcc8a1a22f77e8dff2d581f1166eefb80b", features = ["serde"]}
rayon = "1.10.0"
# Necessary for the VerificationData type
aligned-sdk = { path = "../batcher/aligned-sdk/" }
# zkvms
Expand Down
29 changes: 2 additions & 27 deletions aggregation_mode/src/aggregators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ pub mod sp1_aggregator;
use std::fmt::Display;

use lambdaworks_crypto::merkle_tree::traits::IsMerkleTreeBackend;
use risc0_aggregator::{
AlignedRisc0VerificationError, Risc0AggregationError, Risc0ProofReceiptAndImageId,
};
use risc0_aggregator::{Risc0AggregationError, Risc0ProofReceiptAndImageId};
use sha3::{Digest, Keccak256};
use sp1_aggregator::{
AlignedSP1VerificationError, SP1AggregationError, SP1ProofWithPubValuesAndElf,
};
use sp1_aggregator::{SP1AggregationError, SP1ProofWithPubValuesAndElf};
use tracing::info;

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -219,24 +215,3 @@ impl IsMerkleTreeBackend for AlignedProof {
hasher.finalize().into()
}
}

#[derive(Debug)]
pub enum AlignedVerificationError {
Sp1(AlignedSP1VerificationError),
Risc0(AlignedRisc0VerificationError),
}

impl AlignedProof {
pub fn verify(&self) -> Result<(), AlignedVerificationError> {
match self {
AlignedProof::SP1(proof) => sp1_aggregator::verify(proof).map_err(
|arg0: sp1_aggregator::AlignedSP1VerificationError| {
AlignedVerificationError::Sp1(arg0)
},
),
AlignedProof::Risc0(proof) => {
risc0_aggregator::verify(proof).map_err(AlignedVerificationError::Risc0)
}
}
}
}
48 changes: 28 additions & 20 deletions aggregation_mode/src/aggregators/risc0_aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,35 @@ pub struct Risc0ProofReceiptAndImageId {
pub receipt: Receipt,
}

#[derive(Debug)]
pub enum AlignedRisc0VerificationError {
Verification(String),
UnsupportedProof,
}

impl Risc0ProofReceiptAndImageId {
pub fn new(image_id: [u8; 32], receipt: Receipt) -> Self {
Self { image_id, receipt }
}

pub fn new_with_verification(
image_id: [u8; 32],
receipt: Receipt,
) -> Result<Self, AlignedRisc0VerificationError> {
let is_supported_proof =
receipt.inner.composite().is_ok() || receipt.inner.succinct().is_ok();

if is_supported_proof {
receipt
.verify(image_id)
.map_err(|e| AlignedRisc0VerificationError::Verification(e.to_string()))?;
} else {
return Err(AlignedRisc0VerificationError::UnsupportedProof);
}

Ok(Self { image_id, receipt })
}

pub fn public_inputs(&self) -> &Vec<u8> {
&self.receipt.journal.bytes
}
Expand All @@ -22,12 +50,6 @@ pub enum Risc0AggregationError {
Verification(String),
}

#[derive(Debug)]
pub enum AlignedRisc0VerificationError {
Verification(String),
UnsupportedProof,
}

/// Byte representation of the user proofs aggregator image_id, converted from `[u32; 8]` to `[u8; 32]`.
pub const RISC0_USER_PROOFS_AGGREGATOR_PROGRAM_ID_BYTES: [u8; 32] = {
let mut res = [0u8; 32];
Expand Down Expand Up @@ -169,17 +191,3 @@ pub(crate) fn run_chunk_aggregator(

Ok(proof)
}

pub(crate) fn verify(
proof: &Risc0ProofReceiptAndImageId,
) -> Result<(), AlignedRisc0VerificationError> {
// only stark proofs are supported for recursion
if proof.receipt.inner.composite().is_ok() || proof.receipt.inner.succinct().is_ok() {
proof
.receipt
.verify(proof.image_id)
.map_err(|e| AlignedRisc0VerificationError::Verification(e.to_string()))
} else {
Err(AlignedRisc0VerificationError::UnsupportedProof)
}
}
97 changes: 58 additions & 39 deletions aggregation_mode/src/aggregators/sp1_aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ use std::sync::LazyLock;

use alloy::primitives::Keccak256;
use sp1_aggregation_program::SP1VkAndPubInputs;
#[cfg(feature = "prove")]
use sp1_sdk::EnvProver;
use sp1_sdk::{
EnvProver, HashableKey, Prover, ProverClient, SP1ProofWithPublicValues, SP1Stdin,
CpuProver, HashableKey, Prover, ProverClient, SP1ProofWithPublicValues, SP1Stdin,
SP1VerifyingKey,
};

Expand All @@ -13,25 +15,68 @@ const CHUNK_PROGRAM_ELF: &[u8] =
const USER_PROOFS_PROGRAM_ELF: &[u8] =
include_bytes!("../../aggregation_programs/sp1/elf/sp1_user_proofs_aggregator_program");

#[cfg(feature = "prove")]
static SP1_PROVER_CLIENT: LazyLock<EnvProver> = LazyLock::new(ProverClient::from_env);

/// Separate prover instance configured to always use the CPU.
/// This is used for verification, which is performed in parallel and
/// cannot be done on the GPU.
static SP1_PROVER_CLIENT_CPU: LazyLock<CpuProver> =
LazyLock::new(|| ProverClient::builder().cpu().build());

pub struct SP1ProofWithPubValuesAndElf {
pub proof_with_pub_values: SP1ProofWithPublicValues,
pub elf: Vec<u8>,
pub vk: SP1VerifyingKey,
}

#[derive(Debug)]
pub enum AlignedSP1VerificationError {
Verification(sp1_sdk::SP1VerificationError),
UnsupportedProof,
}

impl SP1ProofWithPubValuesAndElf {
pub fn new(proof_with_pub_values: SP1ProofWithPublicValues, elf: Vec<u8>) -> Self {
let vk = vk_from_elf(&elf);

Self {
proof_with_pub_values,
elf,
vk,
}
}

pub fn new_with_verification(
proof_with_pub_values: SP1ProofWithPublicValues,
elf: Vec<u8>,
) -> Result<Self, AlignedSP1VerificationError> {
let client = &*SP1_PROVER_CLIENT_CPU;

let (_pk, vk) = client.setup(&elf);

// only sp1 compressed proofs are supported for aggregation now
match proof_with_pub_values.proof {
sp1_sdk::SP1Proof::Compressed(_) => client
.verify(&proof_with_pub_values, &vk)
.map_err(AlignedSP1VerificationError::Verification),
_ => Err(AlignedSP1VerificationError::UnsupportedProof),
}?;

Ok(Self {
proof_with_pub_values,
elf,
vk,
})
}

pub fn hash_vk_and_pub_inputs(&self) -> [u8; 32] {
let mut hasher = Keccak256::new();
let vk_bytes = &self.vk().hash_bytes();
let vk_bytes = &self.vk.hash_bytes();
hasher.update(vk_bytes);
hasher.update(self.proof_with_pub_values.public_values.as_slice());
hasher.finalize().into()
}

pub fn vk(&self) -> SP1VerifyingKey {
vk_from_elf(&self.elf)
}
}

#[derive(Debug)]
Expand All @@ -56,15 +101,15 @@ pub(crate) fn run_user_proofs_aggregator(
.proofs_vk_and_pub_inputs
.push(SP1VkAndPubInputs {
public_inputs: proof.proof_with_pub_values.public_values.to_vec(),
vk: proof.vk().hash_u32(),
vk: proof.vk.hash_u32(),
});
}

stdin.write(&program_input);

// write proofs
for input_proof in proofs.iter() {
let vk = input_proof.vk().vk;
let vk = input_proof.vk.vk.clone();
// we only support sp1 Compressed proofs for now
let sp1_sdk::SP1Proof::Compressed(proof) = input_proof.proof_with_pub_values.proof.clone()
else {
Expand Down Expand Up @@ -96,6 +141,7 @@ pub(crate) fn run_user_proofs_aggregator(
let proof_and_elf = SP1ProofWithPubValuesAndElf {
proof_with_pub_values: proof,
elf: USER_PROOFS_PROGRAM_ELF.to_vec(),
vk,
};

Ok(proof_and_elf)
Expand All @@ -115,7 +161,7 @@ pub(crate) fn run_chunk_aggregator(
program_input.proofs_and_leaves_commitment.push((
SP1VkAndPubInputs {
public_inputs: proof.proof_with_pub_values.public_values.to_vec(),
vk: proof.vk().hash_u32(),
vk: proof.vk.hash_u32(),
},
leaves_commitment.clone(),
));
Expand All @@ -125,7 +171,7 @@ pub(crate) fn run_chunk_aggregator(

// write proofs
for (input_proof, _) in proofs.iter() {
let vk = input_proof.vk().vk;
let vk = input_proof.vk.vk.clone();
// we only support sp1 Compressed proofs for now
let sp1_sdk::SP1Proof::Compressed(proof) = input_proof.proof_with_pub_values.proof.clone()
else {
Expand Down Expand Up @@ -168,41 +214,14 @@ pub(crate) fn run_chunk_aggregator(
let proof_and_elf = SP1ProofWithPubValuesAndElf {
proof_with_pub_values: proof,
elf: CHUNK_PROGRAM_ELF.to_vec(),
vk,
};

Ok(proof_and_elf)
}

#[derive(Debug)]
pub enum AlignedSP1VerificationError {
Verification(sp1_sdk::SP1VerificationError),
UnsupportedProof,
}

pub(crate) fn verify(
sp1_proof_with_pub_values_and_elf: &SP1ProofWithPubValuesAndElf,
) -> Result<(), AlignedSP1VerificationError> {
let client = &*SP1_PROVER_CLIENT;

let (_pk, vk) = client.setup(&sp1_proof_with_pub_values_and_elf.elf);

// only sp1 compressed proofs are supported for aggregation now
match sp1_proof_with_pub_values_and_elf
.proof_with_pub_values
.proof
{
sp1_sdk::SP1Proof::Compressed(_) => client
.verify(
&sp1_proof_with_pub_values_and_elf.proof_with_pub_values,
&vk,
)
.map_err(AlignedSP1VerificationError::Verification),
_ => Err(AlignedSP1VerificationError::UnsupportedProof),
}
}

pub fn vk_from_elf(elf: &[u8]) -> SP1VerifyingKey {
let prover = &*SP1_PROVER_CLIENT;
let prover = &*SP1_PROVER_CLIENT_CPU;
let (_, vk) = prover.setup(elf);
vk
}
1 change: 1 addition & 0 deletions aggregation_mode/src/backend/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct Config {
pub last_aggregated_block_filepath: String,
pub ecdsa: ECDSAConfig,
pub proofs_per_chunk: u16,
pub pre_verification_enabled: bool,
}

impl Config {
Expand Down
Loading
Loading