halo2_axiom/plonk/vanishing/
prover.rs
1use std::iter;
2
3use ff::Field;
4use group::Curve;
5use rand_core::RngCore;
6
7use super::Argument;
8use crate::{
9 arithmetic::{eval_polynomial, parallelize, CurveAffine},
10 plonk::{ChallengeX, Error},
11 poly::{
12 commitment::{Blind, ParamsProver},
13 Coeff, EvaluationDomain, ExtendedLagrangeCoeff, Polynomial, ProverQuery,
14 },
15 transcript::{EncodedChallenge, TranscriptWrite},
16};
17
18pub(in crate::plonk) struct Committed<C: CurveAffine> {
19 random_poly: Polynomial<C::Scalar, Coeff>,
20 random_blind: Blind<C::Scalar>,
21}
22
23pub(in crate::plonk) struct Constructed<C: CurveAffine> {
24 h_pieces: Vec<Polynomial<C::Scalar, Coeff>>,
25 h_blinds: Vec<Blind<C::Scalar>>,
26 committed: Committed<C>,
27}
28
29pub(in crate::plonk) struct Evaluated<C: CurveAffine> {
30 h_poly: Polynomial<C::Scalar, Coeff>,
31 h_blind: Blind<C::Scalar>,
32 committed: Committed<C>,
33}
34
35impl<C: CurveAffine> Argument<C> {
36 pub(in crate::plonk) fn commit<
37 'params,
38 P: ParamsProver<'params, C>,
39 E: EncodedChallenge<C>,
40 R: RngCore, T: TranscriptWrite<C, E>,
42 >(
43 params: &P,
44 domain: &EvaluationDomain<C::Scalar>,
45 rng: R,
46 transcript: &mut T,
47 ) -> Result<Committed<C>, Error> {
48 let mut random_poly = domain.empty_coeff();
50 parallelize(&mut random_poly, |random_poly, _| {
51 let mut rng = rand::thread_rng();
52 for coeff in random_poly.iter_mut() {
53 *coeff = C::Scalar::random(&mut rng);
54 }
55 });
56 let random_blind = Blind(C::Scalar::random(rng));
58
59 let c = params.commit(&random_poly, random_blind).to_affine();
61 transcript.write_point(c)?;
62
63 Ok(Committed {
64 random_poly,
65 random_blind,
66 })
67 }
68}
69
70impl<C: CurveAffine> Committed<C> {
71 pub(in crate::plonk) fn construct<
72 'params,
73 P: ParamsProver<'params, C>,
74 E: EncodedChallenge<C>,
75 R: RngCore,
76 T: TranscriptWrite<C, E>,
77 >(
78 self,
79 params: &P,
80 domain: &EvaluationDomain<C::Scalar>,
81 h_poly: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
82 mut rng: R,
83 transcript: &mut T,
84 ) -> Result<Constructed<C>, Error> {
85 let h_poly = domain.divide_by_vanishing_poly(h_poly);
87
88 let h_poly = domain.extended_to_coeff(h_poly);
90
91 let h_pieces = h_poly
93 .chunks_exact(params.n() as usize)
94 .map(|v| domain.coeff_from_vec(v.to_vec()))
95 .collect::<Vec<_>>();
96 drop(h_poly);
97 let h_blinds: Vec<_> = h_pieces
98 .iter()
99 .map(|_| Blind(C::Scalar::random(&mut rng)))
100 .collect();
101
102 let h_commitments_projective: Vec<_> = h_pieces
104 .iter()
105 .zip(h_blinds.iter())
106 .map(|(h_piece, blind)| params.commit(h_piece, *blind))
107 .collect();
108 let mut h_commitments = vec![C::identity(); h_commitments_projective.len()];
109 C::Curve::batch_normalize(&h_commitments_projective, &mut h_commitments);
110 let h_commitments = h_commitments;
111
112 for c in h_commitments.iter() {
114 transcript.write_point(*c)?;
115 }
116
117 Ok(Constructed {
118 h_pieces,
119 h_blinds,
120 committed: self,
121 })
122 }
123}
124
125impl<C: CurveAffine> Constructed<C> {
126 pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
127 self,
128 x: ChallengeX<C>,
129 xn: C::Scalar,
130 domain: &EvaluationDomain<C::Scalar>,
131 transcript: &mut T,
132 ) -> Result<Evaluated<C>, Error> {
133 let h_poly = self
134 .h_pieces
135 .iter()
136 .rev()
137 .fold(domain.empty_coeff(), |acc, eval| acc * xn + eval);
138
139 let h_blind = self
140 .h_blinds
141 .iter()
142 .rev()
143 .fold(Blind(C::Scalar::ZERO), |acc, eval| acc * Blind(xn) + *eval);
144
145 let random_eval = eval_polynomial(&self.committed.random_poly, *x);
146 transcript.write_scalar(random_eval)?;
147
148 Ok(Evaluated {
149 h_poly,
150 h_blind,
151 committed: self.committed,
152 })
153 }
154}
155
156impl<C: CurveAffine> Evaluated<C> {
157 pub(in crate::plonk) fn open(
158 &self,
159 x: ChallengeX<C>,
160 ) -> impl Iterator<Item = ProverQuery<'_, C>> + Clone {
161 iter::empty()
162 .chain(Some(ProverQuery {
163 point: *x,
164 poly: &self.h_poly,
165 blind: self.h_blind,
166 }))
167 .chain(Some(ProverQuery {
168 point: *x,
169 poly: &self.committed.random_poly,
170 blind: self.committed.random_blind,
171 }))
172 }
173}