1use super::{Coeff, LagrangeCoeff, Polynomial};
7use crate::arithmetic::{
8 best_fft, best_multiexp, parallelize, CurveAffine, CurveExt, FieldExt, Group,
9};
10use crate::helpers::CurveRead;
11
12use ff::{Field, PrimeField};
13use group::{prime::PrimeCurveAffine, Curve, Group as _};
14use std::ops::{Add, AddAssign, Mul, MulAssign};
15
16mod msm;
17mod prover;
18mod verifier;
19
20pub use msm::MSM;
21pub use prover::create_proof;
22pub use verifier::{verify_proof, Accumulator, Guard};
23
24use std::io;
25
26#[derive(Clone, Debug)]
28pub struct Params<C: CurveAffine> {
29 pub(crate) k: u32,
30 pub(crate) n: u64,
31 pub(crate) g: Vec<C>,
32 pub(crate) g_lagrange: Vec<C>,
33 pub(crate) w: C,
34 pub(crate) u: C,
35}
36
37impl<C: CurveAffine> Params<C> {
38 pub fn new(k: u32) -> Self {
41 assert!(k < 32);
44
45 let n: u64 = 1 << k;
48
49 let g_projective = {
50 let mut g = Vec::with_capacity(n as usize);
51 g.resize(n as usize, C::Curve::identity());
52
53 parallelize(&mut g, move |g, start| {
54 let hasher = C::CurveExt::hash_to_curve("Halo2-Parameters");
55
56 for (i, g) in g.iter_mut().enumerate() {
57 let i = (i + start) as u32;
58
59 let mut message = [0u8; 5];
60 message[1..5].copy_from_slice(&i.to_le_bytes());
61
62 *g = hasher(&message);
63 }
64 });
65
66 g
67 };
68
69 let g = {
70 let mut g = vec![C::identity(); n as usize];
71 parallelize(&mut g, |g, starts| {
72 C::Curve::batch_normalize(&g_projective[starts..(starts + g.len())], g);
73 });
74 g
75 };
76
77 let mut alpha_inv = <<C as PrimeCurveAffine>::Curve as Group>::Scalar::ROOT_OF_UNITY_INV;
80 for _ in k..C::Scalar::S {
81 alpha_inv = alpha_inv.square();
82 }
83 let mut g_lagrange_projective = g_projective;
84 best_fft(&mut g_lagrange_projective, alpha_inv, k);
85 let minv = C::Scalar::TWO_INV.pow_vartime(&[k as u64, 0, 0, 0]);
86 parallelize(&mut g_lagrange_projective, |g, _| {
87 for g in g.iter_mut() {
88 *g *= minv;
89 }
90 });
91
92 let g_lagrange = {
93 let mut g_lagrange = vec![C::identity(); n as usize];
94 parallelize(&mut g_lagrange, |g_lagrange, starts| {
95 C::Curve::batch_normalize(
96 &g_lagrange_projective[starts..(starts + g_lagrange.len())],
97 g_lagrange,
98 );
99 });
100 drop(g_lagrange_projective);
101 g_lagrange
102 };
103
104 let hasher = C::CurveExt::hash_to_curve("Halo2-Parameters");
105 let w = hasher(&[1]).to_affine();
106 let u = hasher(&[2]).to_affine();
107
108 Params {
109 k,
110 n,
111 g,
112 g_lagrange,
113 w,
114 u,
115 }
116 }
117
118 pub fn commit(&self, poly: &Polynomial<C::Scalar, Coeff>, r: Blind<C::Scalar>) -> C::Curve {
122 let mut tmp_scalars = Vec::with_capacity(poly.len() + 1);
123 let mut tmp_bases = Vec::with_capacity(poly.len() + 1);
124
125 tmp_scalars.extend(poly.iter());
126 tmp_scalars.push(r.0);
127
128 tmp_bases.extend(self.g.iter());
129 tmp_bases.push(self.w);
130
131 best_multiexp::<C>(&tmp_scalars, &tmp_bases)
132 }
133
134 pub fn commit_lagrange(
138 &self,
139 poly: &Polynomial<C::Scalar, LagrangeCoeff>,
140 r: Blind<C::Scalar>,
141 ) -> C::Curve {
142 let mut tmp_scalars = Vec::with_capacity(poly.len() + 1);
143 let mut tmp_bases = Vec::with_capacity(poly.len() + 1);
144
145 tmp_scalars.extend(poly.iter());
146 tmp_scalars.push(r.0);
147
148 tmp_bases.extend(self.g_lagrange.iter());
149 tmp_bases.push(self.w);
150
151 best_multiexp::<C>(&tmp_scalars, &tmp_bases)
152 }
153
154 pub fn empty_msm(&self) -> MSM<C> {
157 MSM::new(self)
158 }
159
160 pub fn get_g(&self) -> Vec<C> {
162 self.g.clone()
163 }
164
165 pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
167 writer.write_all(&self.k.to_le_bytes())?;
168 for g_element in &self.g {
169 writer.write_all(g_element.to_bytes().as_ref())?;
170 }
171 for g_lagrange_element in &self.g_lagrange {
172 writer.write_all(g_lagrange_element.to_bytes().as_ref())?;
173 }
174 writer.write_all(self.w.to_bytes().as_ref())?;
175 writer.write_all(self.u.to_bytes().as_ref())?;
176
177 Ok(())
178 }
179
180 pub fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
182 let mut k = [0u8; 4];
183 reader.read_exact(&mut k[..])?;
184 let k = u32::from_le_bytes(k);
185
186 let n: u64 = 1 << k;
187
188 let g: Vec<_> = (0..n).map(|_| C::read(reader)).collect::<Result<_, _>>()?;
189 let g_lagrange: Vec<_> = (0..n).map(|_| C::read(reader)).collect::<Result<_, _>>()?;
190
191 let w = C::read(reader)?;
192 let u = C::read(reader)?;
193
194 Ok(Params {
195 k,
196 n,
197 g,
198 g_lagrange,
199 w,
200 u,
201 })
202 }
203}
204
205#[derive(Copy, Clone, Eq, PartialEq, Debug)]
207pub struct Blind<F>(pub F);
208
209impl<F: FieldExt> Default for Blind<F> {
210 fn default() -> Self {
211 Blind(F::one())
212 }
213}
214
215impl<F: FieldExt> Add for Blind<F> {
216 type Output = Self;
217
218 fn add(self, rhs: Blind<F>) -> Self {
219 Blind(self.0 + rhs.0)
220 }
221}
222
223impl<F: FieldExt> Mul for Blind<F> {
224 type Output = Self;
225
226 fn mul(self, rhs: Blind<F>) -> Self {
227 Blind(self.0 * rhs.0)
228 }
229}
230
231impl<F: FieldExt> AddAssign for Blind<F> {
232 fn add_assign(&mut self, rhs: Blind<F>) {
233 self.0 += rhs.0;
234 }
235}
236
237impl<F: FieldExt> MulAssign for Blind<F> {
238 fn mul_assign(&mut self, rhs: Blind<F>) {
239 self.0 *= rhs.0;
240 }
241}
242
243impl<F: FieldExt> AddAssign<F> for Blind<F> {
244 fn add_assign(&mut self, rhs: F) {
245 self.0 += rhs;
246 }
247}
248
249impl<F: FieldExt> MulAssign<F> for Blind<F> {
250 fn mul_assign(&mut self, rhs: F) {
251 self.0 *= rhs;
252 }
253}
254
255#[test]
256fn test_commit_lagrange_epaffine() {
257 const K: u32 = 6;
258
259 use rand_core::OsRng;
260
261 use crate::pasta::{EpAffine, Fq};
262 let params = Params::<EpAffine>::new(K);
263 let domain = super::EvaluationDomain::new(1, K);
264
265 let mut a = domain.empty_lagrange();
266
267 for (i, a) in a.iter_mut().enumerate() {
268 *a = Fq::from(i as u64);
269 }
270
271 let b = domain.lagrange_to_coeff(a.clone());
272
273 let alpha = Blind(Fq::random(OsRng));
274
275 assert_eq!(params.commit(&b, alpha), params.commit_lagrange(&a, alpha));
276}
277
278#[test]
279fn test_commit_lagrange_eqaffine() {
280 const K: u32 = 6;
281
282 use rand_core::OsRng;
283
284 use crate::pasta::{EqAffine, Fp};
285 let params = Params::<EqAffine>::new(K);
286 let domain = super::EvaluationDomain::new(1, K);
287
288 let mut a = domain.empty_lagrange();
289
290 for (i, a) in a.iter_mut().enumerate() {
291 *a = Fp::from(i as u64);
292 }
293
294 let b = domain.lagrange_to_coeff(a.clone());
295
296 let alpha = Blind(Fp::random(OsRng));
297
298 assert_eq!(params.commit(&b, alpha), params.commit_lagrange(&a, alpha));
299}
300
301#[test]
302fn test_opening_proof() {
303 const K: u32 = 6;
304
305 use ff::Field;
306 use rand_core::OsRng;
307
308 use super::{
309 commitment::{Blind, Params},
310 EvaluationDomain,
311 };
312 use crate::arithmetic::{eval_polynomial, FieldExt};
313 use crate::pasta::{EpAffine, Fq};
314 use crate::transcript::{
315 Blake2bRead, Blake2bWrite, Challenge255, Transcript, TranscriptRead, TranscriptWrite,
316 };
317
318 let rng = OsRng;
319
320 let params = Params::<EpAffine>::new(K);
321 let mut params_buffer = vec![];
322 params.write(&mut params_buffer).unwrap();
323 let params: Params<EpAffine> = Params::read::<_>(&mut ¶ms_buffer[..]).unwrap();
324
325 let domain = EvaluationDomain::new(1, K);
326
327 let mut px = domain.empty_coeff();
328
329 for (i, a) in px.iter_mut().enumerate() {
330 *a = Fq::from(i as u64);
331 }
332
333 let blind = Blind(Fq::random(rng));
334
335 let p = params.commit(&px, blind).to_affine();
336
337 let mut transcript = Blake2bWrite::<Vec<u8>, EpAffine, Challenge255<EpAffine>>::init(vec![]);
338 transcript.write_point(p).unwrap();
339 let x = transcript.squeeze_challenge_scalar::<()>();
340 let v = eval_polynomial(&px, *x);
342 transcript.write_scalar(v).unwrap();
343
344 let (proof, ch_prover) = {
345 create_proof(¶ms, rng, &mut transcript, &px, blind, *x).unwrap();
346 let ch_prover = transcript.squeeze_challenge();
347 (transcript.finalize(), ch_prover)
348 };
349
350 let mut transcript = Blake2bRead::<&[u8], EpAffine, Challenge255<EpAffine>>::init(&proof[..]);
352 let p_prime = transcript.read_point().unwrap();
353 assert_eq!(p, p_prime);
354 let x_prime = transcript.squeeze_challenge_scalar::<()>();
355 assert_eq!(*x, *x_prime);
356 let v_prime = transcript.read_scalar().unwrap();
357 assert_eq!(v, v_prime);
358
359 let mut commitment_msm = params.empty_msm();
360 commitment_msm.append_term(Field::one(), p);
361 let guard = verify_proof(¶ms, commitment_msm, &mut transcript, *x, v).unwrap();
362 let ch_verifier = transcript.squeeze_challenge();
363 assert_eq!(*ch_prover, *ch_verifier);
364
365 {
367 let msm_challenges = guard.clone().use_challenges();
369 assert!(msm_challenges.eval());
370
371 let g = guard.compute_g();
373 let (msm_g, _accumulator) = guard.clone().use_g(g);
374 assert!(msm_g.eval());
375 }
376}