binius_core/protocols/greedy_evalcheck/
prove.rs1use binius_field::{
4 ExtensionField, Field, PackedExtension, PackedField, PackedFieldIndexable, TowerField,
5};
6use binius_hal::ComputationBackend;
7use binius_math::EvaluationDomainFactory;
8use tracing::instrument;
9
10use super::error::Error;
11use crate::{
12 fiat_shamir::Challenger,
13 oracle::MultilinearOracleSet,
14 protocols::evalcheck::{
15 serialize_evalcheck_proof,
16 subclaims::{prove_bivariate_sumchecks_with_switchover, MemoizedData},
17 EvalcheckMultilinearClaim, EvalcheckProver,
18 },
19 transcript::{write_u64, ProverTranscript},
20 witness::MultilinearExtensionIndex,
21};
22
23pub struct GreedyEvalcheckProveOutput<'a, F: Field, P: PackedField, Backend: ComputationBackend> {
24 pub eval_claims: Vec<EvalcheckMultilinearClaim<F>>,
25 pub memoized_data: MemoizedData<'a, P, Backend>,
26}
27
28#[allow(clippy::too_many_arguments)]
29#[instrument(skip_all, name = "greedy_evalcheck::prove")]
30pub fn prove<'a, F, P, DomainField, Challenger_, Backend>(
31 oracles: &mut MultilinearOracleSet<F>,
32 witness_index: &'a mut MultilinearExtensionIndex<P>,
33 claims: impl IntoIterator<Item = EvalcheckMultilinearClaim<F>>,
34 switchover_fn: impl Fn(usize) -> usize + Clone + 'static,
35 transcript: &mut ProverTranscript<Challenger_>,
36 domain_factory: impl EvaluationDomainFactory<DomainField>,
37 backend: &Backend,
38) -> Result<GreedyEvalcheckProveOutput<'a, F, P, Backend>, Error>
39where
40 F: TowerField + ExtensionField<DomainField>,
41 P: PackedFieldIndexable<Scalar = F>
42 + PackedExtension<F, PackedSubfield = P>
43 + PackedExtension<DomainField>,
44 DomainField: TowerField,
45 Challenger_: Challenger,
46 Backend: ComputationBackend,
47{
48 let mut evalcheck_prover =
49 EvalcheckProver::<F, P, Backend>::new(oracles, witness_index, backend);
50
51 let claims: Vec<_> = claims.into_iter().collect();
52
53 let evalcheck_proofs = evalcheck_prover.prove(claims)?;
55 write_u64(&mut transcript.decommitment(), evalcheck_proofs.len() as u64);
56 let mut writer = transcript.message();
57 for evalcheck_proof in &evalcheck_proofs {
58 serialize_evalcheck_proof(&mut writer, evalcheck_proof)
59 }
60
61 loop {
62 let new_sumchecks = evalcheck_prover.take_new_sumchecks_constraints().unwrap();
63 if new_sumchecks.is_empty() {
64 break;
65 }
66
67 let new_evalcheck_claims =
69 prove_bivariate_sumchecks_with_switchover::<_, _, DomainField, _, _>(
70 evalcheck_prover.witness_index,
71 new_sumchecks,
72 transcript,
73 switchover_fn.clone(),
74 domain_factory.clone(),
75 backend,
76 )?;
77
78 let new_evalcheck_proofs = evalcheck_prover.prove(new_evalcheck_claims)?;
79
80 let mut writer = transcript.message();
81 for evalcheck_proof in &new_evalcheck_proofs {
82 serialize_evalcheck_proof(&mut writer, evalcheck_proof);
83 }
84 }
85
86 let committed_claims = evalcheck_prover
87 .committed_eval_claims_mut()
88 .drain(..)
89 .collect::<Vec<_>>();
90
91 Ok(GreedyEvalcheckProveOutput {
92 eval_claims: committed_claims,
93 memoized_data: evalcheck_prover.memoized_data,
94 })
95}