@@ -240,6 +240,146 @@ fn fri_verifier_query_round<
240240 Ok ( ( ) )
241241}
242242
243+ pub fn verify_fri_proof_v2 <
244+ F : RichField + Extendable < D > ,
245+ C : GenericConfig < D , F = F > ,
246+ const D : usize ,
247+ > (
248+ instance : & FriInstanceInfo < F , D > ,
249+ openings : & FriOpenings < F , D > ,
250+ challenges : & FriChallenges < F , D > ,
251+ initial_merkle_caps : & [ & MerkleCap < F , C :: Hasher > ] ,
252+ proof : & FriProof < F , C :: Hasher , D > ,
253+ params : & FriParams ,
254+ ) -> Result < ( ) > {
255+ validate_fri_proof_shape :: < F , C , D > ( proof, instance, params) ?;
256+
257+ // Size of the LDE domain.
258+ let n = params. lde_size ( ) ;
259+
260+ // Check PoW.
261+ fri_verify_proof_of_work ( challenges. fri_pow_response , & params. config ) ?;
262+
263+ // Check that parameters are coherent.
264+ ensure ! (
265+ params. config. num_query_rounds == proof. query_round_proofs. len( ) ,
266+ "Number of query rounds does not match config."
267+ ) ;
268+
269+ let precomputed_reduced_evals =
270+ PrecomputedReducedOpenings :: from_os_and_alpha ( openings, challenges. fri_alpha ) ;
271+ for ( & x_index, round_proof) in challenges
272+ . fri_query_indices
273+ . iter ( )
274+ . zip ( & proof. query_round_proofs )
275+ {
276+ fri_verifier_query_round_v2 :: < F , C , D > (
277+ instance,
278+ challenges,
279+ & precomputed_reduced_evals,
280+ initial_merkle_caps,
281+ proof,
282+ x_index,
283+ n,
284+ round_proof,
285+ params,
286+ ) ?;
287+ }
288+
289+ Ok ( ( ) )
290+ }
291+
292+ fn fri_verify_initial_proof_v2 < F : RichField , H : Hasher < F > > (
293+ x_index : usize ,
294+ proof : & FriInitialTreeProof < F , H > ,
295+ initial_merkle_caps : & [ & MerkleCap < F , H > ] ,
296+ ) -> Result < ( ) > {
297+ for ( ( evals, merkle_proof) , cap) in proof. evals_proofs . iter ( ) . zip ( initial_merkle_caps) {
298+ verify_merkle_proof_to_cap :: < F , H > ( evals. clone ( ) , x_index, cap, merkle_proof) ?;
299+ }
300+
301+ Ok ( ( ) )
302+ }
303+
304+ fn fri_verifier_query_round_v2 <
305+ F : RichField + Extendable < D > ,
306+ C : GenericConfig < D , F = F > ,
307+ const D : usize ,
308+ > (
309+ instance : & FriInstanceInfo < F , D > ,
310+ challenges : & FriChallenges < F , D > ,
311+ precomputed_reduced_evals : & PrecomputedReducedOpenings < F , D > ,
312+ initial_merkle_caps : & [ & MerkleCap < F , C :: Hasher > ] ,
313+ proof : & FriProof < F , C :: Hasher , D > ,
314+ mut x_index : usize ,
315+ n : usize ,
316+ round_proof : & FriQueryRound < F , C :: Hasher , D > ,
317+ params : & FriParams ,
318+ ) -> Result < ( ) > {
319+ fri_verify_initial_proof_v2 :: < F , C :: Hasher > (
320+ x_index,
321+ & round_proof. initial_trees_proof ,
322+ initial_merkle_caps,
323+ ) ?;
324+ // `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
325+ let log_n = log2_strict ( n) ;
326+ let mut subgroup_x = F :: MULTIPLICATIVE_GROUP_GENERATOR
327+ * F :: primitive_root_of_unity ( log_n) . exp_u64 ( reverse_bits ( x_index, log_n) as u64 ) ;
328+
329+ // old_eval is the last derived evaluation; it will be checked for consistency with its
330+ // committed "parent" value in the next iteration.
331+ let mut old_eval = fri_combine_initial :: < F , C , D > (
332+ instance,
333+ & round_proof. initial_trees_proof ,
334+ challenges. fri_alpha ,
335+ subgroup_x,
336+ precomputed_reduced_evals,
337+ params,
338+ ) ;
339+
340+ for ( i, & arity_bits) in params. reduction_arity_bits . iter ( ) . enumerate ( ) {
341+ let arity = 1 << arity_bits;
342+ let evals = & round_proof. steps [ i] . evals ;
343+
344+ // Split x_index into the index of the coset x is in, and the index of x within that coset.
345+ let coset_index = x_index >> arity_bits;
346+ let x_index_within_coset = x_index & ( arity - 1 ) ;
347+
348+ // Check consistency with our old evaluation from the previous round.
349+ ensure ! ( evals[ x_index_within_coset] == old_eval) ;
350+
351+ // Infer P(y) from {P(x)}_{x^arity=y}.
352+ old_eval = compute_evaluation (
353+ subgroup_x,
354+ x_index_within_coset,
355+ arity_bits,
356+ evals,
357+ challenges. fri_betas [ i] ,
358+ ) ;
359+
360+ verify_merkle_proof_to_cap :: < F , C :: Hasher > (
361+ flatten ( evals) ,
362+ coset_index,
363+ & proof. commit_phase_merkle_caps [ i] ,
364+ & round_proof. steps [ i] . merkle_proof ,
365+ ) ?;
366+
367+ // Update the point x to x^arity.
368+ subgroup_x = subgroup_x. exp_power_of_2 ( arity_bits) ;
369+
370+ x_index = coset_index;
371+ }
372+
373+ // Final check of FRI. After all the reductions, we check that the final polynomial is equal
374+ // to the one sent by the prover.
375+ ensure ! (
376+ proof. final_poly. eval( subgroup_x. into( ) ) == old_eval,
377+ "Final polynomial evaluation is invalid."
378+ ) ;
379+
380+ Ok ( ( ) )
381+ }
382+
243383/// For each opening point, holds the reduced (by `alpha`) evaluations of each polynomial that's
244384/// opened at that point.
245385#[ derive( Clone , Debug ) ]
0 commit comments