@@ -2,8 +2,10 @@ use std::sync::LazyLock;
22
33use alloy:: primitives:: Keccak256 ;
44use sp1_aggregation_program:: SP1VkAndPubInputs ;
5+ #[ cfg( feature = "prove" ) ]
6+ use sp1_sdk:: EnvProver ;
57use sp1_sdk:: {
6- EnvProver , HashableKey , Prover , ProverClient , SP1ProofWithPublicValues , SP1Stdin ,
8+ CpuProver , HashableKey , Prover , ProverClient , SP1ProofWithPublicValues , SP1Stdin ,
79 SP1VerifyingKey ,
810} ;
911
@@ -13,25 +15,59 @@ const CHUNK_PROGRAM_ELF: &[u8] =
1315const USER_PROOFS_PROGRAM_ELF : & [ u8 ] =
1416 include_bytes ! ( "../../aggregation_programs/sp1/elf/sp1_user_proofs_aggregator_program" ) ;
1517
18+ #[ cfg( feature = "prove" ) ]
1619static SP1_PROVER_CLIENT : LazyLock < EnvProver > = LazyLock :: new ( ProverClient :: from_env) ;
1720
21+ /// Separate prover instance configured to always use the CPU.
22+ /// This is used for verification, which is performed in parallel and
23+ /// cannot be done on the GPU.
24+ static SP1_PROVER_CLIENT_CPU : LazyLock < CpuProver > =
25+ LazyLock :: new ( || ProverClient :: builder ( ) . cpu ( ) . build ( ) ) ;
26+
1827pub struct SP1ProofWithPubValuesAndElf {
1928 pub proof_with_pub_values : SP1ProofWithPublicValues ,
2029 pub elf : Vec < u8 > ,
30+ pub vk : SP1VerifyingKey ,
31+ }
32+
33+ #[ derive( Debug ) ]
34+ pub enum AlignedSP1VerificationError {
35+ Verification ( sp1_sdk:: SP1VerificationError ) ,
36+ UnsupportedProof ,
2137}
2238
2339impl SP1ProofWithPubValuesAndElf {
40+ /// Constructs a new instance of the struct by verifying a given SP1 proof with its public values.
41+ pub fn new (
42+ proof_with_pub_values : SP1ProofWithPublicValues ,
43+ elf : Vec < u8 > ,
44+ ) -> Result < Self , AlignedSP1VerificationError > {
45+ let client = & * SP1_PROVER_CLIENT_CPU ;
46+
47+ let ( _pk, vk) = client. setup ( & elf) ;
48+
49+ // only sp1 compressed proofs are supported for aggregation now
50+ match proof_with_pub_values. proof {
51+ sp1_sdk:: SP1Proof :: Compressed ( _) => client
52+ . verify ( & proof_with_pub_values, & vk)
53+ . map_err ( AlignedSP1VerificationError :: Verification ) ,
54+ _ => Err ( AlignedSP1VerificationError :: UnsupportedProof ) ,
55+ } ?;
56+
57+ Ok ( Self {
58+ proof_with_pub_values,
59+ elf,
60+ vk,
61+ } )
62+ }
63+
2464 pub fn hash_vk_and_pub_inputs ( & self ) -> [ u8 ; 32 ] {
2565 let mut hasher = Keccak256 :: new ( ) ;
26- let vk_bytes = & self . vk ( ) . hash_bytes ( ) ;
66+ let vk_bytes = & self . vk . hash_bytes ( ) ;
2767 hasher. update ( vk_bytes) ;
2868 hasher. update ( self . proof_with_pub_values . public_values . as_slice ( ) ) ;
2969 hasher. finalize ( ) . into ( )
3070 }
31-
32- pub fn vk ( & self ) -> SP1VerifyingKey {
33- vk_from_elf ( & self . elf )
34- }
3571}
3672
3773#[ derive( Debug ) ]
@@ -56,15 +92,15 @@ pub(crate) fn run_user_proofs_aggregator(
5692 . proofs_vk_and_pub_inputs
5793 . push ( SP1VkAndPubInputs {
5894 public_inputs : proof. proof_with_pub_values . public_values . to_vec ( ) ,
59- vk : proof. vk ( ) . hash_u32 ( ) ,
95+ vk : proof. vk . hash_u32 ( ) ,
6096 } ) ;
6197 }
6298
6399 stdin. write ( & program_input) ;
64100
65101 // write proofs
66102 for input_proof in proofs. iter ( ) {
67- let vk = input_proof. vk ( ) . vk ;
103+ let vk = input_proof. vk . vk . clone ( ) ;
68104 // we only support sp1 Compressed proofs for now
69105 let sp1_sdk:: SP1Proof :: Compressed ( proof) = input_proof. proof_with_pub_values . proof . clone ( )
70106 else {
@@ -96,6 +132,7 @@ pub(crate) fn run_user_proofs_aggregator(
96132 let proof_and_elf = SP1ProofWithPubValuesAndElf {
97133 proof_with_pub_values : proof,
98134 elf : USER_PROOFS_PROGRAM_ELF . to_vec ( ) ,
135+ vk,
99136 } ;
100137
101138 Ok ( proof_and_elf)
@@ -115,7 +152,7 @@ pub(crate) fn run_chunk_aggregator(
115152 program_input. proofs_and_leaves_commitment . push ( (
116153 SP1VkAndPubInputs {
117154 public_inputs : proof. proof_with_pub_values . public_values . to_vec ( ) ,
118- vk : proof. vk ( ) . hash_u32 ( ) ,
155+ vk : proof. vk . hash_u32 ( ) ,
119156 } ,
120157 leaves_commitment. clone ( ) ,
121158 ) ) ;
@@ -125,7 +162,7 @@ pub(crate) fn run_chunk_aggregator(
125162
126163 // write proofs
127164 for ( input_proof, _) in proofs. iter ( ) {
128- let vk = input_proof. vk ( ) . vk ;
165+ let vk = input_proof. vk . vk . clone ( ) ;
129166 // we only support sp1 Compressed proofs for now
130167 let sp1_sdk:: SP1Proof :: Compressed ( proof) = input_proof. proof_with_pub_values . proof . clone ( )
131168 else {
@@ -168,41 +205,14 @@ pub(crate) fn run_chunk_aggregator(
168205 let proof_and_elf = SP1ProofWithPubValuesAndElf {
169206 proof_with_pub_values : proof,
170207 elf : CHUNK_PROGRAM_ELF . to_vec ( ) ,
208+ vk,
171209 } ;
172210
173211 Ok ( proof_and_elf)
174212}
175213
176- #[ derive( Debug ) ]
177- pub enum AlignedSP1VerificationError {
178- Verification ( sp1_sdk:: SP1VerificationError ) ,
179- UnsupportedProof ,
180- }
181-
182- pub ( crate ) fn verify (
183- sp1_proof_with_pub_values_and_elf : & SP1ProofWithPubValuesAndElf ,
184- ) -> Result < ( ) , AlignedSP1VerificationError > {
185- let client = & * SP1_PROVER_CLIENT ;
186-
187- let ( _pk, vk) = client. setup ( & sp1_proof_with_pub_values_and_elf. elf ) ;
188-
189- // only sp1 compressed proofs are supported for aggregation now
190- match sp1_proof_with_pub_values_and_elf
191- . proof_with_pub_values
192- . proof
193- {
194- sp1_sdk:: SP1Proof :: Compressed ( _) => client
195- . verify (
196- & sp1_proof_with_pub_values_and_elf. proof_with_pub_values ,
197- & vk,
198- )
199- . map_err ( AlignedSP1VerificationError :: Verification ) ,
200- _ => Err ( AlignedSP1VerificationError :: UnsupportedProof ) ,
201- }
202- }
203-
204214pub fn vk_from_elf ( elf : & [ u8 ] ) -> SP1VerifyingKey {
205- let prover = & * SP1_PROVER_CLIENT ;
215+ let prover = & * SP1_PROVER_CLIENT_CPU ;
206216 let ( _, vk) = prover. setup ( elf) ;
207217 vk
208218}
0 commit comments