|
1 | 1 | #![no_main] |
2 | 2 | sp1_zkvm::entrypoint!(main); |
3 | 3 |
|
| 4 | +use lambdaworks_crypto::merkle_tree::merkle::MerkleTree; |
4 | 5 | use sha2::{Digest, Sha256}; |
5 | | -use sp1_aggregation_program::{compute_merkle_root, Input}; |
| 6 | +use sp1_aggregation_program::{Hash32, RootAggregatorInput}; |
6 | 7 |
|
7 | | -pub const LEAVES_AGG_PROGRAM_VK_HASH: [u32; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; |
| 8 | +pub const CHUNK_AGGREGATOR_PROGRAM_VK_HASH: [u32; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; |
8 | 9 |
|
9 | 10 | pub fn main() { |
10 | | - let input = sp1_zkvm::io::read::<Input>(); |
11 | | - |
12 | | - println!("Number of proofs in input: {}", input.proofs_vk_and_pub_inputs.len()); |
| 11 | + let input = sp1_zkvm::io::read::<RootAggregatorInput>(); |
13 | 12 |
|
14 | | - let mut proofs_hash: Vec<[u8; 32]> = vec![]; |
15 | | - println!("Initial proofs_hash length: {}", proofs_hash.len()); |
| 13 | + let mut leaves = vec![]; |
16 | 14 |
|
17 | 15 | // Verify the proofs. |
18 | | - for (i, proof) in input.proofs_vk_and_pub_inputs.iter().enumerate() { |
19 | | - println!("Processing proof {}, public_inputs length: {}", i, proof.public_inputs.len()); |
20 | | - |
| 16 | + for (proof, leaves_commitment) in input.proofs_and_leaves_commitment { |
21 | 17 | let vkey = proof.vk; |
22 | 18 | let public_values_digest = Sha256::digest(&proof.public_inputs); |
23 | 19 |
|
24 | 20 | // Ensure the aggregated chunk originates from the L1 aggregation program. |
25 | 21 | // This validation step guarantees that the proof was genuinely verified |
26 | 22 | // by this program. Without this check, a different program using the |
27 | 23 | // same public inputs could bypass verification. |
28 | | - |
29 | | - // TODO: Add the assert here |
30 | | - //assert!(proof.vk == LEAVES_AGG_PROGRAM_VK_HASH); |
| 24 | + assert!(proof.vk == CHUNK_AGGREGATOR_PROGRAM_VK_HASH); |
31 | 25 |
|
32 | 26 | let merkle_root: [u8; 32] = proof |
33 | 27 | .public_inputs |
34 | 28 | .clone() |
35 | 29 | .try_into() |
36 | 30 | .expect("Public input to be the hash of the chunk tree"); |
37 | 31 |
|
38 | | - proofs_hash.push(merkle_root); |
39 | | - println!("proofs_hash length after push: {}", proofs_hash.len()); |
| 32 | + // Reconstruct the merkle tree and verify that the roots match |
| 33 | + let leaves_commitment: Vec<Hash32> = |
| 34 | + leaves_commitment.into_iter().map(|el| Hash32(el)).collect(); |
| 35 | + let merkle_tree: MerkleTree<Hash32> = MerkleTree::build(&leaves_commitment).unwrap(); |
| 36 | + assert!(merkle_tree.root == merkle_root); |
40 | 37 |
|
41 | | - println!("vkey (debug): {:?}", vkey); |
42 | | - println!("public_values_digest (debug): {:?}", public_values_digest); |
| 38 | + leaves.extend(leaves_commitment); |
43 | 39 |
|
44 | 40 | sp1_zkvm::lib::verify::verify_sp1_proof(&vkey, &public_values_digest.into()); |
45 | 41 | } |
46 | 42 |
|
47 | | - println!("Final proofs_hash length before compute_merkle_root: {}", proofs_hash.len()); |
48 | | - let merkle_root = compute_merkle_root(proofs_hash); |
| 43 | + // Finally, compute the final merkle root with all the leaves |
| 44 | + let merkle_tree: MerkleTree<Hash32> = MerkleTree::build(&leaves).unwrap(); |
49 | 45 |
|
50 | | - sp1_zkvm::io::commit_slice(&merkle_root); |
| 46 | + sp1_zkvm::io::commit_slice(&merkle_tree.root); |
51 | 47 | } |
0 commit comments