binius_core/protocols/greedy_evalcheck/
verify.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use binius_field::TowerField;
4use binius_math::EvaluationOrder;
5use binius_utils::bail;
6use itertools::izip;
7
8use super::error::Error;
9use crate::{
10	fiat_shamir::Challenger,
11	oracle::MultilinearOracleSet,
12	protocols::{
13		evalcheck::{ConstraintSetsEqIndPoints, EvalcheckMultilinearClaim, EvalcheckVerifier},
14		sumcheck::{
15			self, MLEcheckClaimsWithMeta, SumcheckClaimsWithMeta, constraint_set_mlecheck_claims,
16			constraint_set_sumcheck_claims,
17			eq_ind::{self, ClaimsSortingOrder, reduce_to_regular_sumchecks},
18			front_loaded,
19		},
20	},
21	transcript::VerifierTranscript,
22};
23
24pub fn verify<F, Challenger_>(
25	oracles: &mut MultilinearOracleSet<F>,
26	claims: impl IntoIterator<Item = EvalcheckMultilinearClaim<F>>,
27	transcript: &mut VerifierTranscript<Challenger_>,
28) -> Result<Vec<EvalcheckMultilinearClaim<F>>, Error>
29where
30	F: TowerField,
31	Challenger_: Challenger,
32{
33	let mut evalcheck_verifier = EvalcheckVerifier::new(oracles);
34
35	// Verify the initial evalcheck claims
36	evalcheck_verifier.verify(claims, transcript)?;
37
38	loop {
39		let mut new_evalcheck_claims = Vec::new();
40
41		let SumcheckClaimsWithMeta {
42			claims: new_bivariate_sumchecks_claims,
43			metas,
44		} = constraint_set_sumcheck_claims(evalcheck_verifier.take_new_sumcheck_constraints()?)?;
45
46		if !new_bivariate_sumchecks_claims.is_empty() {
47			// Reduce the new sumcheck claims for virtual polynomial openings to new evalcheck
48			// claims.
49			let batch_sumcheck_verifier =
50				front_loaded::BatchVerifier::new(&new_bivariate_sumchecks_claims, transcript)?;
51			let mut sumcheck_output = batch_sumcheck_verifier.run(transcript)?;
52
53			// Reverse challenges since folding high-to-low
54			sumcheck_output.challenges.reverse();
55
56			let evalcheck_claims =
57				sumcheck::make_eval_claims(EvaluationOrder::HighToLow, metas, sumcheck_output)?;
58			new_evalcheck_claims.extend(evalcheck_claims)
59		}
60
61		let ConstraintSetsEqIndPoints {
62			eq_ind_challenges,
63			constraint_sets,
64		} = evalcheck_verifier.take_new_mlechecks_constraints()?;
65
66		let MLEcheckClaimsWithMeta {
67			claims: mlecheck_claims,
68			metas,
69		} = constraint_set_mlecheck_claims(constraint_sets)?;
70
71		if !mlecheck_claims.is_empty() {
72			// Reduce the new mlecheck claims for virtual polynomial openings to new evalcheck
73			// claims.
74			for (eq_ind_challenges, mlecheck_claim, meta) in
75				izip!(eq_ind_challenges, mlecheck_claims, metas)
76			{
77				let mlecheck_claim = vec![mlecheck_claim];
78
79				let batch_sumcheck_verifier = front_loaded::BatchVerifier::new(
80					&reduce_to_regular_sumchecks(&mlecheck_claim)?,
81					transcript,
82				)?;
83				let mut sumcheck_output = batch_sumcheck_verifier.run(transcript)?;
84
85				// Reverse challenges since foldling high-to-low
86				sumcheck_output.challenges.reverse();
87
88				let eq_ind_output = eq_ind::verify_sumcheck_outputs(
89					ClaimsSortingOrder::AscendingVars,
90					&mlecheck_claim,
91					&eq_ind_challenges,
92					sumcheck_output,
93				)?;
94
95				let evalcheck_claims = sumcheck::make_eval_claims(
96					EvaluationOrder::HighToLow,
97					vec![meta],
98					eq_ind_output,
99				)?;
100				new_evalcheck_claims.extend(evalcheck_claims)
101			}
102		}
103
104		if new_evalcheck_claims.is_empty() {
105			break;
106		}
107
108		evalcheck_verifier.verify(new_evalcheck_claims, transcript)?;
109	}
110
111	let new_sumchecks = evalcheck_verifier.take_new_sumcheck_constraints()?;
112	if !new_sumchecks.is_empty() {
113		bail!(Error::MissingVirtualOpeningProof);
114	}
115
116	let committed_claims = evalcheck_verifier
117		.committed_eval_claims_mut()
118		.drain(..)
119		.collect::<Vec<_>>();
120	Ok(committed_claims)
121}