Skip to content

Commit 5335d2a

Browse files
committed
feat: aggregator backends for new programs
1 parent e20cffc commit 5335d2a

File tree

3 files changed

+195
-116
lines changed

3 files changed

+195
-116
lines changed

aggregation_mode/src/aggregators/mod.rs

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -85,26 +85,27 @@ impl ZKVMEngine {
8585
.collect();
8686

8787
info!("Total proofs to aggregate {}", proofs.len());
88-
let mut agg_proof = if proofs.len() > MAX_PROOFS_PER_AGGREGATION {
89-
let chunks = proofs.chunks(MAX_PROOFS_PER_AGGREGATION);
90-
let mut agg_proofs: Vec<SP1ProofWithPubValuesAndElf> = vec![];
91-
92-
info!("Proofs length is higher than {}, aggregation will be performed in {} chunks", MAX_PROOFS_PER_AGGREGATION, chunks.len());
93-
for (i, chunk) in chunks.enumerate() {
94-
let agg_proof = sp1_aggregator::aggregate_proofs(chunk, false, false)
95-
.map_err(ProofAggregationError::SP1Aggregation)?;
96-
agg_proofs.push(agg_proof);
97-
98-
info!("Chunk number {} has been aggregated", i);
99-
}
100-
101-
info!("All chunks have been aggregated, performing last aggregation...");
102-
sp1_aggregator::aggregate_proofs(&agg_proofs, true, true)
103-
.map_err(ProofAggregationError::SP1Aggregation)?
104-
} else {
105-
sp1_aggregator::aggregate_proofs(&proofs, false, true)
106-
.map_err(ProofAggregationError::SP1Aggregation)?
107-
};
88+
let chunks = proofs.chunks(MAX_PROOFS_PER_AGGREGATION);
89+
let mut agg_proofs: Vec<(SP1ProofWithPubValuesAndElf, Vec<[u8; 32]>)> = vec![];
90+
91+
info!(
92+
"Proofs length is higher than {}, aggregation will be performed in {} chunks",
93+
MAX_PROOFS_PER_AGGREGATION,
94+
chunks.len()
95+
);
96+
for (i, chunk) in chunks.enumerate() {
97+
let leaves_commitment =
98+
chunk.iter().map(|e| e.hash_vk_and_pub_inputs()).collect();
99+
let agg_proof = sp1_aggregator::run_chunk_aggregator(chunk)
100+
.map_err(ProofAggregationError::SP1Aggregation)?;
101+
agg_proofs.push((agg_proof, leaves_commitment));
102+
103+
info!("Chunk number {} has been aggregated", i);
104+
}
105+
106+
info!("All chunks have been aggregated, performing last aggregation...");
107+
let mut agg_proof = sp1_aggregator::run_root_aggregator(&agg_proofs)
108+
.map_err(ProofAggregationError::SP1Aggregation)?;
108109

109110
let merkle_root: [u8; 32] = agg_proof
110111
.proof_with_pub_values
@@ -126,26 +127,29 @@ impl ZKVMEngine {
126127
.collect();
127128

128129
info!("Total proofs to aggregate {}", proofs.len());
129-
let agg_proof = if proofs.len() > MAX_PROOFS_PER_AGGREGATION {
130-
let chunks = proofs.chunks(MAX_PROOFS_PER_AGGREGATION);
131-
let mut agg_proofs: Vec<Risc0ProofReceiptAndImageId> = vec![];
132-
133-
info!("Proofs length is higher than {}, aggregation will be performed in {} chunks", MAX_PROOFS_PER_AGGREGATION, chunks.len());
134-
for (i, chunk) in chunks.enumerate() {
135-
let agg_proof = risc0_aggregator::aggregate_proofs(chunk, false, false)
136-
.map_err(ProofAggregationError::Risc0Aggregation)?;
137-
agg_proofs.push(agg_proof);
138-
139-
info!("Chunk number {} has been aggregated", i);
140-
}
141-
142-
info!("All chunks have been aggregated, performing last aggregation...");
143-
risc0_aggregator::aggregate_proofs(&agg_proofs, true, true)
144-
.map_err(ProofAggregationError::Risc0Aggregation)?
145-
} else {
146-
risc0_aggregator::aggregate_proofs(&proofs, false, true)
147-
.map_err(ProofAggregationError::Risc0Aggregation)?
148-
};
130+
let chunks = proofs.chunks(MAX_PROOFS_PER_AGGREGATION);
131+
let mut agg_proofs: Vec<(Risc0ProofReceiptAndImageId, Vec<[u8; 32]>)> = vec![];
132+
133+
info!(
134+
"Proofs length is higher than {}, aggregation will be performed in {} chunks",
135+
MAX_PROOFS_PER_AGGREGATION,
136+
chunks.len()
137+
);
138+
for (i, chunk) in chunks.enumerate() {
139+
let leaves_commitment = chunk
140+
.iter()
141+
.map(|e| e.hash_image_id_and_public_inputs())
142+
.collect();
143+
let agg_proof = risc0_aggregator::run_chunk_aggregator(chunk)
144+
.map_err(ProofAggregationError::Risc0Aggregation)?;
145+
agg_proofs.push((agg_proof, leaves_commitment));
146+
147+
info!("Chunk number {} has been aggregated", i);
148+
}
149+
150+
info!("All chunks have been aggregated, performing last aggregation...");
151+
let agg_proof = risc0_aggregator::run_root_aggregator(&agg_proofs)
152+
.map_err(ProofAggregationError::Risc0Aggregation)?;
149153

150154
// Note: journal.decode() won't work here as risc0 deserializer works under u32 words
151155
let public_input_bytes = agg_proof.receipt.journal.as_ref();
@@ -170,9 +174,7 @@ impl AlignedProof {
170174
pub fn commitment(&self) -> [u8; 32] {
171175
match self {
172176
AlignedProof::SP1(proof) => proof.hash_vk_and_pub_inputs(),
173-
//AlignedProof::Risc0(proof) => proof.hash_image_id_and_public_inputs(),
174-
AlignedProof::Risc0(proof) => todo!(),
175-
177+
AlignedProof::Risc0(proof) => proof.hash_image_id_and_public_inputs(),
176178
}
177179
}
178180
}
@@ -225,8 +227,7 @@ impl AlignedProof {
225227
},
226228
),
227229
AlignedProof::Risc0(proof) => {
228-
todo!()
229-
//risc0_aggregator::verify(proof).map_err(AlignedVerificationError::Risc0)
230+
risc0_aggregator::verify(proof).map_err(AlignedVerificationError::Risc0)
230231
}
231232
}
232233
}

aggregation_mode/src/aggregators/risc0_aggregator.rs

Lines changed: 79 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
//include!(concat!(env!("OUT_DIR"), "/methods.rs"));
1+
include!(concat!(env!("OUT_DIR"), "/methods.rs"));
22

33
use risc0_zkvm::{default_prover, ExecutorEnv, ProverOpts, Receipt};
44
use sha3::{Digest, Keccak256};
55

6-
76
pub struct Risc0ProofReceiptAndImageId {
87
pub image_id: [u8; 32],
98
pub receipt: Receipt,
@@ -29,13 +28,12 @@ pub enum AlignedRisc0VerificationError {
2928
UnsupportedProof,
3029
}
3130

32-
/// Byte representation of the aggregator image_id, converted from `[u32; 8]` to `[u8; 32]`.
33-
/*
34-
pub const RISC0_AGGREGATOR_PROGRAM_ID_BYTES: [u8; 32] = {
31+
/// Byte representation of the chunk aggregator image_id, converted from `[u32; 8]` to `[u8; 32]`.
32+
pub const RISC0_CHUNK_AGGREGATOR_PROGRAM_ID_BYTES: [u8; 32] = {
3533
let mut res = [0u8; 32];
3634
let mut i = 0;
3735
while i < 8 {
38-
let bytes = RISC0_AGGREGATOR_PROGRAM_ID[i].to_le_bytes();
36+
let bytes = RISC0_CHUNK_AGGREGATOR_PROGRAM_ID[i].to_le_bytes();
3937
res[i * 4] = bytes[0];
4038
res[i * 4 + 1] = bytes[1];
4139
res[i * 4 + 2] = bytes[2];
@@ -45,6 +43,20 @@ pub const RISC0_AGGREGATOR_PROGRAM_ID_BYTES: [u8; 32] = {
4543
res
4644
};
4745

46+
/// Byte representation of the root aggregator image_id, converted from `[u32; 8]` to `[u8; 32]`.
47+
pub const RISC0_ROOT_AGGREGATOR_PROGRAM_ID_BYTES: [u8; 32] = {
48+
let mut res = [0u8; 32];
49+
let mut i = 0;
50+
while i < 8 {
51+
let bytes = RISC0_ROOT_AGGREGATOR_PROGRAM_ID[i].to_le_bytes();
52+
res[i * 4] = bytes[0];
53+
res[i * 4 + 1] = bytes[1];
54+
res[i * 4 + 2] = bytes[2];
55+
res[i * 4 + 3] = bytes[3];
56+
i += 1;
57+
}
58+
res
59+
};
4860

4961
impl Risc0ProofReceiptAndImageId {
5062
pub fn hash_image_id_and_public_inputs(&self) -> [u8; 32] {
@@ -55,11 +67,8 @@ impl Risc0ProofReceiptAndImageId {
5567
}
5668
}
5769

58-
59-
pub(crate) fn aggregate_proofs(
70+
pub(crate) fn run_chunk_aggregator(
6071
proofs: &[Risc0ProofReceiptAndImageId],
61-
is_aggregated_chunk: bool,
62-
should_wrap_to_groth16: bool,
6372
) -> Result<Risc0ProofReceiptAndImageId, Risc0AggregationError> {
6473
let mut env_builder = ExecutorEnv::builder();
6574

@@ -74,8 +83,8 @@ pub(crate) fn aggregate_proofs(
7483
}
7584

7685
// write input data
77-
let input = risc0_aggregation_program::Input {
78-
proofs_image_id_and_pub_inputs
86+
let input = risc0_aggregation_program::ChunkAggregatorInput {
87+
proofs_image_id_and_pub_inputs,
7988
};
8089
env_builder
8190
.write(&input)
@@ -87,30 +96,79 @@ pub(crate) fn aggregate_proofs(
8796

8897
let prover = default_prover();
8998

90-
let opts = if should_wrap_to_groth16 {
91-
ProverOpts::groth16()
92-
} else {
93-
ProverOpts::composite()
94-
};
95-
9699
let receipt = prover
97-
.prove_with_opts(env, RISC0_AGGREGATOR_PROGRAM_ELF, &opts)
100+
.prove_with_opts(
101+
env,
102+
RISC0_CHUNK_AGGREGATOR_PROGRAM_ELF,
103+
&ProverOpts::composite(),
104+
)
98105
.map_err(|e| Risc0AggregationError::Prove(e.to_string()))?
99106
.receipt;
100107

101108
receipt
102-
.verify(RISC0_AGGREGATOR_PROGRAM_ID)
109+
.verify(RISC0_CHUNK_AGGREGATOR_PROGRAM_ID)
103110
.map_err(|e| Risc0AggregationError::Verification(e.to_string()))?;
104111

105112
let proof = Risc0ProofReceiptAndImageId {
106-
image_id: RISC0_AGGREGATOR_PROGRAM_ID_BYTES,
113+
image_id: RISC0_CHUNK_AGGREGATOR_PROGRAM_ID_BYTES,
107114
receipt,
108115
};
109116

110117
Ok(proof)
111118
}
112119

120+
pub(crate) fn run_root_aggregator(
121+
proofs: &[(Risc0ProofReceiptAndImageId, Vec<[u8; 32]>)],
122+
) -> Result<Risc0ProofReceiptAndImageId, Risc0AggregationError> {
123+
let mut env_builder = ExecutorEnv::builder();
124+
125+
// write assumptions and proof image id + pub inputs
126+
let mut proofs_and_leaves_commitment = vec![];
127+
for (proof, leaves_commitment) in proofs {
128+
proofs_and_leaves_commitment.push((
129+
risc0_aggregation_program::Risc0ImageIdAndPubInputs {
130+
image_id: proof.image_id,
131+
public_inputs: proof.receipt.journal.bytes.clone(),
132+
},
133+
leaves_commitment.clone(),
134+
));
135+
env_builder.add_assumption(proof.receipt.clone());
136+
}
113137

138+
// write input data
139+
let input = risc0_aggregation_program::RootAggregatorInput {
140+
proofs_and_leaves_commitment: proofs_and_leaves_commitment,
141+
};
142+
env_builder
143+
.write(&input)
144+
.map_err(|e| Risc0AggregationError::WriteInput(e.to_string()))?;
145+
146+
let env = env_builder
147+
.build()
148+
.map_err(|e| Risc0AggregationError::BuildExecutor(e.to_string()))?;
149+
150+
let prover = default_prover();
151+
152+
let receipt = prover
153+
.prove_with_opts(
154+
env,
155+
RISC0_ROOT_AGGREGATOR_PROGRAM_ELF,
156+
&ProverOpts::groth16(),
157+
)
158+
.map_err(|e| Risc0AggregationError::Prove(e.to_string()))?
159+
.receipt;
160+
161+
receipt
162+
.verify(RISC0_ROOT_AGGREGATOR_PROGRAM_ID)
163+
.map_err(|e| Risc0AggregationError::Verification(e.to_string()))?;
164+
165+
let proof = Risc0ProofReceiptAndImageId {
166+
image_id: RISC0_ROOT_AGGREGATOR_PROGRAM_ID_BYTES,
167+
receipt,
168+
};
169+
170+
Ok(proof)
171+
}
114172

115173
pub(crate) fn verify(
116174
proof: &Risc0ProofReceiptAndImageId,
@@ -125,19 +183,3 @@ pub(crate) fn verify(
125183
Err(AlignedRisc0VerificationError::UnsupportedProof)
126184
}
127185
}
128-
*/
129-
130-
pub(crate) fn aggregate_proofs(
131-
proofs: &[Risc0ProofReceiptAndImageId],
132-
is_aggregated_chunk: bool,
133-
should_wrap_to_groth16: bool,
134-
) -> Result<Risc0ProofReceiptAndImageId, Risc0AggregationError> {
135-
136-
todo!()
137-
}
138-
139-
pub(crate) fn verify(
140-
proof: &Risc0ProofReceiptAndImageId,
141-
) -> Result<(), AlignedRisc0VerificationError> {
142-
todo!();
143-
}

0 commit comments

Comments
 (0)