binius_core/protocols/sumcheck/prove/
front_loaded.rsuse std::{collections::VecDeque, iter};
use binius_field::{Field, TowerField};
use binius_utils::sorting::is_sorted_ascending;
use super::batch_prove::SumcheckProver;
use crate::{
fiat_shamir::CanSample,
protocols::sumcheck::{Error, RoundCoeffs},
transcript::CanWrite,
};
#[derive(Debug)]
pub struct BatchProver<F: Field, Prover> {
provers: VecDeque<(Prover, F)>,
round: usize,
}
impl<F, Prover> BatchProver<F, Prover>
where
F: TowerField,
Prover: SumcheckProver<F>,
{
pub fn new<Transcript>(provers: Vec<Prover>, transcript: &mut Transcript) -> Result<Self, Error>
where
Transcript: CanSample<F>,
{
if !is_sorted_ascending(provers.iter().map(|prover| prover.n_vars())) {
return Err(Error::ClaimsOutOfOrder);
}
let batch_coeffs = transcript.sample_vec(provers.len());
let provers = iter::zip(provers, batch_coeffs).collect();
Ok(Self { provers, round: 0 })
}
fn finish_claim_provers<Transcript>(&mut self, transcript: &mut Transcript) -> Result<(), Error>
where
Transcript: CanWrite,
{
while let Some((prover, _)) = self.provers.front() {
if prover.n_vars() != self.round {
break;
}
let (prover, _) = self.provers.pop_front().expect("front returned Some");
let multilinear_evals = prover.finish()?;
transcript.write_scalar_slice(&multilinear_evals);
}
Ok(())
}
pub fn send_round_proof<Transcript>(&mut self, transcript: &mut Transcript) -> Result<(), Error>
where
Transcript: CanWrite,
{
self.finish_claim_provers(transcript)?;
let mut round_coeffs = RoundCoeffs::default();
for (prover, batch_coeff) in &mut self.provers {
let prover_coeffs = prover.execute(*batch_coeff)?;
round_coeffs += &(prover_coeffs * *batch_coeff);
}
let round_proof = round_coeffs.truncate();
transcript.write_scalar_slice(round_proof.coeffs());
Ok(())
}
pub fn receive_challenge(&mut self, challenge: F) -> Result<(), Error> {
for (prover, _) in &mut self.provers {
prover.fold(challenge)?;
}
self.round += 1;
Ok(())
}
pub fn finish<Transcript>(mut self, transcript: &mut Transcript) -> Result<(), Error>
where
Transcript: CanWrite,
{
self.finish_claim_provers(transcript)?;
if !self.provers.is_empty() {
return Err(Error::ExpectedFold);
}
Ok(())
}
}