halo2_proofs/poly/commitment/
verifier.rsuse group::{
ff::{BatchInvert, Field},
Curve,
};
use super::super::Error;
use super::{Params, MSM};
use crate::transcript::{EncodedChallenge, TranscriptRead};
use crate::arithmetic::{best_multiexp, CurveAffine};
#[derive(Debug, Clone)]
pub struct Guard<'a, C: CurveAffine, E: EncodedChallenge<C>> {
msm: MSM<'a, C>,
neg_c: C::Scalar,
u: Vec<C::Scalar>,
u_packed: Vec<E>,
}
#[derive(Debug, Clone)]
pub struct Accumulator<C: CurveAffine, E: EncodedChallenge<C>> {
pub g: C,
pub u_packed: Vec<E>,
}
impl<'a, C: CurveAffine, E: EncodedChallenge<C>> Guard<'a, C, E> {
pub fn use_challenges(mut self) -> MSM<'a, C> {
let s = compute_s(&self.u, self.neg_c);
self.msm.add_to_g_scalars(&s);
self.msm
}
pub fn use_g(mut self, g: C) -> (MSM<'a, C>, Accumulator<C, E>) {
self.msm.append_term(self.neg_c, g);
let accumulator = Accumulator {
g,
u_packed: self.u_packed,
};
(self.msm, accumulator)
}
pub fn compute_g(&self) -> C {
let s = compute_s(&self.u, C::Scalar::one());
best_multiexp(&s, &self.msm.params.g).to_affine()
}
}
pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
params: &'a Params<C>,
mut msm: MSM<'a, C>,
transcript: &mut T,
x: C::Scalar,
v: C::Scalar,
) -> Result<Guard<'a, C, E>, Error> {
let k = params.k as usize;
msm.add_constant_term(-v); let s_poly_commitment = transcript.read_point().map_err(|_| Error::OpeningError)?;
let xi = *transcript.squeeze_challenge_scalar::<()>();
msm.append_term(xi, s_poly_commitment);
let z = *transcript.squeeze_challenge_scalar::<()>();
let mut rounds = vec![];
for _ in 0..k {
let l = transcript.read_point().map_err(|_| Error::OpeningError)?;
let r = transcript.read_point().map_err(|_| Error::OpeningError)?;
let u_j_packed = transcript.squeeze_challenge();
let u_j = *u_j_packed.as_challenge_scalar::<()>();
rounds.push((l, r, u_j, u_j, u_j_packed));
}
rounds
.iter_mut()
.map(|&mut (_, _, _, ref mut u_j, _)| u_j)
.batch_invert();
let mut u = Vec::with_capacity(k);
let mut u_packed: Vec<E> = Vec::with_capacity(k);
for (l, r, u_j, u_j_inv, u_j_packed) in rounds {
msm.append_term(u_j_inv, l);
msm.append_term(u_j, r);
u.push(u_j);
u_packed.push(u_j_packed);
}
let c = transcript.read_scalar().map_err(|_| Error::SamplingError)?;
let neg_c = -c;
let f = transcript.read_scalar().map_err(|_| Error::SamplingError)?;
let b = compute_b(x, &u);
msm.add_to_u_scalar(neg_c * &b * &z);
msm.add_to_w_scalar(-f);
let guard = Guard {
msm,
neg_c,
u,
u_packed,
};
Ok(guard)
}
fn compute_b<F: Field>(x: F, u: &[F]) -> F {
let mut tmp = F::one();
let mut cur = x;
for u_j in u.iter().rev() {
tmp *= F::one() + &(*u_j * &cur);
cur *= cur;
}
tmp
}
fn compute_s<F: Field>(u: &[F], init: F) -> Vec<F> {
assert!(!u.is_empty());
let mut v = vec![F::zero(); 1 << u.len()];
v[0] = init;
for (len, u_j) in u.iter().rev().enumerate().map(|(i, u_j)| (1 << i, u_j)) {
let (left, right) = v.split_at_mut(len);
let right = &mut right[0..len];
right.copy_from_slice(left);
for v in right {
*v *= u_j;
}
}
v
}