pub fn round(
        &mut self,
        r_prev: Option<&FieldElement<F>>,
    ) -> Result<Polynomial<FieldElement<F>>, ProverError> {
        // Store the challenge from the previous round
        if let Some(r) = r_prev {
            if self.challenges.len() >= self.num_vars {
                return Err(ProverError::InvalidState(
                    "Received challenge when all variables are already fixed.".to_string(),
                ));
            }
            self.challenges.push(r.clone());
        }

        // Check if all rounds are completed
        let current_round_idx = self.challenges.len();
        if current_round_idx >= self.num_vars {
            return Err(ProverError::InvalidState(
                "All variables already fixed, no more rounds to run.".to_string(),
            ));
        }

        // Calculate the polynomial g_j(X_j) by interpolation.
        // The degree of g_j is at most the number of factors.
        let num_eval_points = self.factors.len() + 1;
        let mut evaluation_points_x = Vec::with_capacity(num_eval_points);
        let mut evaluations_y = Vec::with_capacity(num_eval_points);

        // Prefix for evaluation points: (r1, r2, ..., r_{j-1}, eval_point_x)
        let mut current_point_prefix = self.challenges.clone();
        current_point_prefix.push(FieldElement::zero());

        for i in 0..num_eval_points {
            // Point at which to evaluate X_j
            let eval_point_x = FieldElement::from(i as u64);
            evaluation_points_x.push(eval_point_x.clone());

            // Set the actual value for X_j in the prefix
            *current_point_prefix.last_mut().unwrap() = eval_point_x;

            let g_j_at_eval_point = sum_product_over_suffix(&self.factors, &current_point_prefix)
                .map_err(|e| {
                ProverError::RoundError(format!("Error in sum for g_j({}): {}", i, e))
            })?;
            evaluations_y.push(g_j_at_eval_point);
        }

        let poly_g_j = Polynomial::interpolate(&evaluation_points_x, &evaluations_y)?;

        Ok(poly_g_j)
    }
Executes a round of the Sum-Check protocol.

Given the challenge `r_prev` from the previous round (if any), this function
computes the round polynomial \( g_j(X_j) \).
\( g_j(X_j) = \\sum_{x_{j+1}, ..., x_n \\in \\{0,1\\}} \\prod_i P_i(r_1, ..., r_{j-1}, X_j, x_{j+1}, ..., x_n) \)
This is achieved by evaluating the sum at `deg(g_j) + 1` points and interpolating.
crates/provers/sumcheck/src/prover.rs