Check that each `proof_i` in `proofs` is a valid proof of evaluation for `commitment_i` at `point_i`.
(
vk: &VerifierKey<E>,
commitments: &[Commitment<E>],
points: &[E::ScalarField],
values: &[E::ScalarField],
proofs: &[Proof<E>],
rng: &mut R,
)
| 335 | /// Check that each `proof_i` in `proofs` is a valid proof of evaluation for |
| 336 | /// `commitment_i` at `point_i`. |
| 337 | pub fn batch_check<R: RngCore>( |
| 338 | vk: &VerifierKey<E>, |
| 339 | commitments: &[Commitment<E>], |
| 340 | points: &[E::ScalarField], |
| 341 | values: &[E::ScalarField], |
| 342 | proofs: &[Proof<E>], |
| 343 | rng: &mut R, |
| 344 | ) -> Result<bool, Error> { |
| 345 | let check_time = |
| 346 | start_timer!(|| format!("Checking {} evaluation proofs", commitments.len())); |
| 347 | |
| 348 | let mut total_c = <E::G1>::zero(); |
| 349 | let mut total_w = <E::G1>::zero(); |
| 350 | |
| 351 | let combination_time = start_timer!(|| "Combining commitments and proofs"); |
| 352 | let mut randomizer = E::ScalarField::one(); |
| 353 | // Instead of multiplying g and gamma_g in each turn, we simply accumulate |
| 354 | // their coefficients and perform a final multiplication at the end. |
| 355 | let mut g_multiplier = E::ScalarField::zero(); |
| 356 | let mut gamma_g_multiplier = E::ScalarField::zero(); |
| 357 | for (((c, z), v), proof) in commitments.iter().zip(points).zip(values).zip(proofs) { |
| 358 | let w = proof.w; |
| 359 | let mut temp = w.mul(*z); |
| 360 | temp += &c.0; |
| 361 | let c = temp; |
| 362 | g_multiplier += &(randomizer * v); |
| 363 | if let Some(random_v) = proof.random_v { |
| 364 | gamma_g_multiplier += &(randomizer * &random_v); |
| 365 | } |
| 366 | total_c += &c.mul(randomizer); |
| 367 | total_w += &w.mul(randomizer); |
| 368 | // We don't need to sample randomizers from the full field, |
| 369 | // only from 128-bit strings. |
| 370 | randomizer = u128::rand(rng).into(); |
| 371 | } |
| 372 | total_c -= &vk.g.mul(g_multiplier); |
| 373 | total_c -= &vk.gamma_g.mul(gamma_g_multiplier); |
| 374 | end_timer!(combination_time); |
| 375 | |
| 376 | let to_affine_time = start_timer!(|| "Converting results to affine for pairing"); |
| 377 | let affine_points = E::G1::normalize_batch(&[-total_w, total_c]); |
| 378 | let (total_w, total_c) = (affine_points[0], affine_points[1]); |
| 379 | end_timer!(to_affine_time); |
| 380 | |
| 381 | let pairing_time = start_timer!(|| "Performing product of pairings"); |
| 382 | let result = E::multi_pairing( |
| 383 | [total_w, total_c], |
| 384 | [vk.prepared_beta_h.clone(), vk.prepared_h.clone()], |
| 385 | ) |
| 386 | .0 |
| 387 | .is_one(); |
| 388 | end_timer!(pairing_time); |
| 389 | end_timer!(check_time, || format!("Result: {}", result)); |
| 390 | Ok(result) |
| 391 | } |
| 392 | |
| 393 | pub(crate) fn check_degree_is_too_large(degree: usize, num_powers: usize) -> Result<(), Error> { |
| 394 | let num_coefficients = degree + 1; |