1use std::{collections::HashMap, error::Error, fmt::Display, marker::PhantomData};
2
3use ark_ec::{pairing::Pairing, Group};
4use ark_ff::{Field, One, PrimeField, UniformRand, Zero};
5use ark_poly::{
6 univariate::DensePolynomial, DenseUVPolynomial, EvaluationDomain, Evaluations,
7 GeneralEvaluationDomain, Polynomial,
8};
9
10use crate::{VCPreparedData, VCUniversalParams, VectorCommitment};
11
12#[derive(Clone, Debug)]
15pub struct KZGKey<F: PrimeField, G1: Group, G2: Group> {
16 degree: usize,
18
19 ref_string_g1: Vec<G1>,
21
22 g2_secret: G2,
24
25 lagrange_commitments: Vec<G1>,
27
28 domain: GeneralEvaluationDomain<F>,
31}
32
33impl<F, G1, G2> KZGKey<F, G1, G2>
34where
35 F: PrimeField,
36 G1: Group<ScalarField = F>,
37 G2: Group<ScalarField = F>,
38{
39 fn new_from_secret(secret: F, max_degree: usize) -> Self {
40 let g1 = G1::generator();
41 let g2 = G2::generator();
42 let domain = GeneralEvaluationDomain::<F>::new(max_degree).unwrap();
43
44 let mut params: Self = Self {
45 degree: max_degree,
46 ref_string_g1: vec![],
47 g2_secret: g2 * secret,
48 lagrange_commitments: vec![], domain: domain,
50 };
51 params.ref_string_g1.push(g1);
52 let mut sec_cur: F = F::one();
53 for _i in 1..max_degree {
54 sec_cur = sec_cur * secret; params.ref_string_g1.push(g1 * sec_cur);
56 }
57 params.lagrange_commitments = domain.ifft(¶ms.ref_string_g1);
59
60 params
61 }
62
63 fn commit_g1(&self, coeffs: &[F]) -> G1 {
66 let mut sum = G1::zero();
67 for (i, c) in coeffs.iter().enumerate() {
68 sum += self.element_at_g1(i) * c;
69 }
70
71 sum
72 }
73
74 fn commit_lagrange(&self, evaluations: &[F]) -> G1 {
75 let mut sum = G1::zero();
76 for (i, e) in evaluations.iter().enumerate() {
77 sum += self.lagrange_commitments[i] * e;
78 }
79
80 sum
81 }
82
83 fn element_at_g1(&self, index: usize) -> G1 {
84 self.ref_string_g1[index]
85 }
86
87 fn get_g2(&self) -> G2 {
89 self.g2_secret
90 }
91
92 pub fn domain(&self) -> GeneralEvaluationDomain<F> {
93 self.domain
94 }
95
96 fn unity(&self) -> F {
97 self.domain.group_gen()
98 }
99}
100
101impl<F, G1, G2> VCUniversalParams for KZGKey<F, G1, G2>
102where
103 F: PrimeField,
104 G1: Group<ScalarField = F>,
105 G2: Group<ScalarField = F>,
106{
107 fn max_size(&self) -> usize {
108 self.degree
109 }
110}
111
112#[derive(Clone, PartialEq)]
116pub struct KZGPreparedData<F: PrimeField> {
117 evaluations: Evaluations<F, GeneralEvaluationDomain<F>>,
119
120 filled_index: Vec<usize>,
122
123 poly: DensePolynomial<F>,
125
126 size: usize,
128}
129
130impl<F: PrimeField> KZGPreparedData<F> {
131 pub fn from_points_and_domain(mut points: Vec<F>, domain: GeneralEvaluationDomain<F>) -> Self {
132 let len = points.len();
133 if len < domain.size() {
134 points.resize(domain.size(), F::zero());
135 }
136 let evals = Evaluations::from_vec_and_domain(points, domain);
137 let poly = evals.interpolate_by_ref();
138
139 let mut filled: Vec<usize> = Vec::new();
140 for i in 0..len {
141 filled.push(i);
142 }
143
144 Self {
145 evaluations: evals,
146 filled_index: filled,
147 poly: poly,
148 size: len,
149 }
150 }
151 fn domain_size(&self) -> usize {
152 self.evaluations.domain().size()
153 }
154
155 fn evaluate(&self, index: usize) -> F {
156 self.evaluations[index]
157 }
158
159 fn index_to_point(&self, index: usize) -> F {
161 self.evaluations.domain().element(index)
162 }
163
164 fn poly(&self) -> DensePolynomial<F> {
165 self.evaluations.clone().interpolate()
166 }
167}
168
169impl<F: PrimeField> VCPreparedData for KZGPreparedData<F> {
170 type Item = F;
171 type Error = KZGError;
172
173 fn from_vec(data: Vec<Self::Item>) -> Self {
175 let domain = GeneralEvaluationDomain::<F>::new(data.len()).unwrap();
176 Self::from_points_and_domain(data, domain)
177 }
178
179 fn set_evaluation(&mut self, index: usize, value: Self::Item) -> Result<(), Self::Error> {
180 if index > self.domain_size() {
182 return Err(KZGError::OutOfDomainBounds);
183 }
184 self.evaluations.evals[index] = value;
185 return Ok(());
186 }
187
188 fn get(&self, index: usize) -> Option<&Self::Item> {
189 self.evaluations.evals.get(index)
190 }
191
192 fn get_all(&self) -> Vec<(usize, Self::Item)> {
193 let mut res: Vec<(usize, Self::Item)> = Vec::new();
194 for i in self.filled_index.iter() {
195 res.push((*i, self.evaluations.evals[*i]));
196 }
197 res
198 }
199
200 fn max_size(&self) -> usize {
201 self.domain_size()
202 }
203}
204
205#[derive(PartialEq, Clone, Default, Debug)]
206pub struct KZGCommitment<G: Group> {
207 commit: G,
208}
209
210impl<G: Group> KZGCommitment<G> {
211 fn new(commit: G) -> Self {
212 Self { commit }
213 }
214
215 fn group_to_field(&self) -> G::ScalarField {
216 if self.commit.is_zero() {
217 <G::ScalarField as Field>::ZERO
218 } else {
219 let mut bytes: Vec<u8> = Vec::new();
220 self.commit.serialize_compressed(&mut bytes).unwrap();
222 <G::ScalarField as PrimeField>::from_le_bytes_mod_order(&bytes)
223 }
224 }
225}
226
227pub struct KZGProof<F: PrimeField, G: Group> {
228 commit: G,
229
230 index: usize,
232
233 point: F,
236
237 data: F,
238}
239
240pub struct KZGBatchProof<F: PrimeField, G: Group> {
241 proofs: HashMap<usize, (F, F, G)>,
245}
246
247impl<F: PrimeField, G: Group> Default for KZGBatchProof<F, G> {
248 fn default() -> Self {
249 Self {
250 proofs: HashMap::new(),
251 }
252 }
253}
254
255#[derive(Clone, Debug)]
256pub enum KZGError {
257 DefaultError,
258 DataExceedsMaxSize,
259 InvalidDomain,
260 OutOfDomainBounds,
261}
262
263impl KZGError {
264 fn new() -> Self {
265 Self::DefaultError
266 }
267}
268
269impl Display for KZGError {
270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271 write!(f, "{}", "")
272 }
273}
274
275impl Error for KZGError {}
276
277#[derive(PartialEq, Clone)]
279pub struct KZGAmortized<E: Pairing> {
280 _engine: PhantomData<E>,
281}
282
283impl<E: Pairing> VectorCommitment for KZGAmortized<E> {
284 type UniversalParams = KZGKey<E::ScalarField, E::G1, E::G2>;
285 type PreparedData = KZGPreparedData<E::ScalarField>;
286 type Commitment = KZGCommitment<E::G1>;
287 type Proof = KZGProof<E::ScalarField, E::G1>;
288 type BatchProof = KZGBatchProof<E::ScalarField, E::G1>;
289 type Error = KZGError;
290
291 fn setup<R: rand::RngCore>(
292 max_items: usize,
293 rng: &mut R,
294 ) -> Result<Self::UniversalParams, Self::Error> {
295 let secret = <E::ScalarField as UniformRand>::rand(rng);
296 Ok(KZGKey::new_from_secret(secret, max_items))
297 }
298
299 fn commit(
300 key: &Self::UniversalParams,
301 data: &Self::PreparedData,
302 ) -> Result<Self::Commitment, Self::Error> {
303 Ok(KZGCommitment {
304 commit: key.commit_lagrange(&data.evaluations.evals),
305 })
306 }
307
308 fn prove(
309 key: &Self::UniversalParams,
310 commitment: &Self::Commitment,
311 index: usize,
312 data: &Self::PreparedData,
313 ) -> Result<Self::Proof, Self::Error> {
314 let commit = Self::single_proof(&key, &data, index)?;
315 Ok(Self::Proof {
316 commit,
317 index,
318 data: data.evaluate(index),
319 point: data.index_to_point(index),
320 })
321 }
322
323 fn prove_all(
324 key: &Self::UniversalParams,
325 commitment: &Self::Commitment,
326 data: &Self::PreparedData,
327 ) -> Result<Self::BatchProof, Self::Error> {
328 Self::get_all_proofs(&key, &data)
329 }
330
331 fn verify(
332 key: &Self::UniversalParams,
333 commitment: &Self::Commitment,
334 proof: &Self::Proof,
335 ) -> Result<bool, Self::Error> {
336 let pairing1 = E::pairing(
338 proof.commit,
339 key.get_g2() - (E::G2::generator() * proof.point),
340 );
341 let pairing2 = E::pairing(
342 commitment.commit - E::G1::generator() * proof.data,
343 E::G2::generator(),
344 );
345
346 Ok(pairing1 == pairing2)
347 }
348
349 fn verify_batch(
350 key: &Self::UniversalParams,
351 commitment: &Self::Commitment,
352 proof: &Self::BatchProof,
353 ) -> Result<bool, Self::Error> {
354 let s = key.get_g2();
355 for (index, p) in proof.proofs.iter() {
356 let pairing1 = E::pairing(p.2, s - (E::G2::generator() * p.0));
357 let pairing2 = E::pairing(
358 commitment.commit - E::G1::generator() * p.1,
359 E::G2::generator(),
360 );
361
362 if pairing1 != pairing2 {
363 return Ok(false);
364 }
365 }
366
367 Ok(true)
368 }
369
370 fn convert_commitment_to_data(
371 commit: &Self::Commitment,
372 ) -> <Self::PreparedData as VCPreparedData>::Item {
373 commit.group_to_field()
374 }
375}
376
377impl<E: Pairing> KZGAmortized<E> {
378 fn get_all_proofs(
380 key: &KZGKey<E::ScalarField, E::G1, E::G2>,
381 data: &KZGPreparedData<E::ScalarField>,
382 ) -> Result<KZGBatchProof<E::ScalarField, E::G1>, KZGError> {
383 let all_proofs = Self::build_witness_matrix(key, data)?;
384 let mut res = KZGBatchProof::default();
385
386 let domain = data.evaluations.domain();
387 let proofs = domain.fft(&all_proofs);
388
389 for index in 0..data.size {
390 let point = data.index_to_point(index);
391 res.proofs
392 .insert(index, (point, data.evaluate(index), proofs[index]));
393 }
394
395 Ok(res)
396 }
397
398 fn build_witness_matrix(
400 key: &KZGKey<E::ScalarField, E::G1, E::G2>,
401 data: &KZGPreparedData<E::ScalarField>,
402 ) -> Result<Vec<E::G1>, KZGError> {
403 let degree = data.poly.degree();
404 let coeffs = data.poly.coeffs();
405 let domain = GeneralEvaluationDomain::<E::ScalarField>::new(degree * 2)
406 .ok_or(KZGError::InvalidDomain)?;
407 let domain_size = domain.size();
408
409 let mut c_hat: Vec<E::ScalarField> = vec![coeffs[degree]];
410 c_hat.extend(vec![E::ScalarField::zero(); degree + 1]);
411 c_hat.extend(&coeffs[0..degree]);
412
413 let mut s_hat = key.ref_string_g1[0..degree].to_vec();
414 s_hat.reverse();
415 s_hat.extend(vec![E::G1::zero(); domain_size - degree]);
416
417 let y = domain.fft(&c_hat);
418 let v = domain.fft(&s_hat);
419 let u = Self::elementwise_mul(&v, &y);
420 let h_hat = domain.ifft(&u);
421
422 Ok(h_hat[0..degree].to_vec())
423 }
424
425 fn single_proof(
426 key: &KZGKey<E::ScalarField, E::G1, E::G2>,
427 data: &KZGPreparedData<E::ScalarField>,
428 index: usize,
429 ) -> Result<E::G1, KZGError> {
430 let data_piece = data.evaluate(index);
431 let point = data.index_to_point(index);
432 let mut poly = data.poly.clone();
433 poly -= &DensePolynomial::<E::ScalarField>::from_coefficients_slice(&[data_piece]);
434
435 let divisor = DensePolynomial::<E::ScalarField>::from_coefficients_slice(&[
436 E::ScalarField::zero() - point,
437 E::ScalarField::one(),
438 ]);
439 let q = &poly / &divisor;
440
441 let commit = key.commit_g1(q.coeffs());
442
443 Ok(commit)
444 }
445
446 fn elementwise_mul<F: PrimeField, G1: Group<ScalarField = F>>(
447 g_vec: &Vec<G1>,
448 f_vec: &Vec<F>,
449 ) -> Vec<G1> {
450 let mut result: Vec<G1> = vec![];
451 for (g, f) in g_vec.iter().zip(f_vec.iter()) {
452 result.push(*g * *f);
453 }
454
455 result
456 }
457}
458
459#[cfg(test)]
460mod tests {
461 use super::*;
462 use ark_bn254::Bn254;
463
464 type F = <Bn254 as Pairing>::ScalarField;
465 type G1 = <Bn254 as Pairing>::G1;
466 type G2 = <Bn254 as Pairing>::G2;
467 type KZG = KZGAmortized<Bn254>;
468
469 const DATA_SIZE: usize = 4;
470 const MAX_CRS: usize = 32;
471
472 fn gen_data(num: usize) -> Vec<F> {
473 let mut data: Vec<F> = vec![];
474 let mut rng = rand::thread_rng();
475 for _i in 0..num {
476 data.push(F::rand(&mut rng));
477 }
478 data
479 }
480
481 fn setup(n: usize, max_degree: usize) -> (KZGPreparedData<F>, KZGKey<F, G1, G2>) {
482 let data = gen_data(n);
483 let crs = KZG::setup(max_degree, &mut rand::thread_rng()).unwrap();
485 let prep = KZGPreparedData::from_points_and_domain(data, crs.domain);
486
487 (prep, crs)
488 }
489
490 #[test]
491 fn test_single_proof() {
492 let (data, crs) = setup(DATA_SIZE, MAX_CRS);
493 let commit = KZG::commit(&crs, &data).unwrap();
494
495 for i in 0..DATA_SIZE {
496 let proof = KZG::prove(&crs, &commit, i, &data).unwrap();
497 assert!(KZG::verify(&crs, &commit, &proof).unwrap());
498 }
499 }
500
501 #[test]
502 fn test_batch_proof() {
503 let (data, crs) = setup(DATA_SIZE, MAX_CRS);
504 let commit = KZG::commit(&crs, &data).unwrap();
505
506 let proofs = KZG::prove_all(&crs, &commit, &data).unwrap();
507 assert!(KZG::verify_batch(&crs, &commit, &proofs).unwrap());
508 }
509
510 fn vec_to_str<T: Display>(v: &Vec<T>) -> String {
511 let mut s = "[\n".to_owned();
512 for e in v {
513 s.push_str(&format!("\t{}\n", e));
514 }
515 s.push_str("]");
516 s
517 }
518}