/ algorithms / src / polycommit / kzg10 / data_structures.rs
data_structures.rs
  1  // Copyright (c) 2025 ADnet Contributors
  2  // This file is part of the AlphaVM library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use crate::{
 17      AlgebraicSponge,
 18      fft::{DensePolynomial, EvaluationDomain},
 19  };
 20  use alphavm_curves::{AffineCurve, PairingCurve, PairingEngine, ProjectiveCurve};
 21  use alphavm_fields::{ConstraintFieldError, ToConstraintField, Zero};
 22  use alphavm_parameters::mainnet::PowersOfG;
 23  use alphavm_utilities::{
 24      FromBytes,
 25      ToBytes,
 26      error,
 27      into_io_error,
 28      serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate},
 29  };
 30  
 31  use crate::srs::{UniversalProver, UniversalVerifier};
 32  use anyhow::Result;
 33  use core::ops::{Add, AddAssign};
 34  use rand::RngCore;
 35  use std::{
 36      borrow::Cow,
 37      collections::BTreeMap,
 38      io,
 39      io::{Read, Write},
 40      ops::Range,
 41      sync::Arc,
 42  };
 43  
 44  /// `UniversalParams` are the universal parameters for the KZG10 scheme.
 45  #[derive(Clone, Debug)]
 46  pub struct UniversalParams<E: PairingEngine> {
 47      /// Group elements of the form `{ \beta^i G }`, where `i` ranges from 0 to
 48      /// `degree`, and group elements of the form `{ \beta^i \gamma G }`,
 49      /// where `i` ranges from 0 to `degree`. This struct provides an
 50      /// abstraction over the powers which are located on-disk
 51      /// to reduce memory usage.
 52      powers: Arc<PowersOfG<E>>,
 53      /// The generator of G2.
 54      pub h: E::G2Affine,
 55      /// The generator of G2, prepared for use in pairings.
 56      pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
 57      /// \beta times the above generator of G2, prepared for use in pairings.
 58      pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
 59  }
 60  
 61  impl<E: PairingEngine> UniversalParams<E> {
 62      pub fn load() -> Result<Self> {
 63          let powers = Arc::new(PowersOfG::<E>::load()?);
 64          let h = E::G2Affine::prime_subgroup_generator();
 65          let prepared_h = h.prepare();
 66          let prepared_beta_h = powers.beta_h().prepare();
 67  
 68          Ok(Self { powers, h, prepared_h, prepared_beta_h })
 69      }
 70  
 71      pub fn download_powers_for(&self, range: Range<usize>) -> Result<()> {
 72          self.powers.download_powers_for(range)
 73      }
 74  
 75      pub fn lagrange_basis(&self, domain: EvaluationDomain<E::Fr>) -> Result<Vec<E::G1Affine>> {
 76          let basis = domain
 77              .ifft(&self.powers_of_beta_g(0, domain.size())?.iter().map(|e| (*e).to_projective()).collect::<Vec<_>>());
 78          Ok(E::G1Projective::batch_normalization_into_affine(basis))
 79      }
 80  
 81      pub fn power_of_beta_g(&self, index: usize) -> Result<E::G1Affine> {
 82          self.powers.power_of_beta_g(index)
 83      }
 84  
 85      pub fn powers_of_beta_g(&self, lower: usize, upper: usize) -> Result<Vec<E::G1Affine>> {
 86          self.powers.powers_of_beta_g(lower..upper)
 87      }
 88  
 89      pub fn powers_of_beta_times_gamma_g(&self) -> &BTreeMap<usize, E::G1Affine> {
 90          self.powers.powers_of_beta_gamma_g()
 91      }
 92  
 93      pub fn beta_h(&self) -> E::G2Affine {
 94          self.powers.beta_h()
 95      }
 96  
 97      pub fn max_degree(&self) -> usize {
 98          self.powers.max_num_powers() - 1
 99      }
100  
101      pub fn to_universal_prover(&self) -> Result<UniversalProver<E>> {
102          Ok(UniversalProver::<E> { max_degree: self.max_degree(), _unused: None })
103      }
104  
105      pub fn to_universal_verifier(&self) -> Result<UniversalVerifier<E>> {
106          let g = self.power_of_beta_g(0)?;
107          let h = self.h;
108          let beta_h = self.beta_h();
109          let gamma_g = self.powers_of_beta_times_gamma_g()[&0];
110          let prepared_h = self.prepared_h.clone();
111          let prepared_beta_h = self.prepared_beta_h.clone();
112  
113          Ok(UniversalVerifier {
114              vk: VerifierKey::<E> { g, gamma_g, h, beta_h, prepared_h, prepared_beta_h },
115              prepared_negative_powers_of_beta_h: self.powers.prepared_negative_powers_of_beta_h(),
116          })
117      }
118  }
119  
120  impl<E: PairingEngine> FromBytes for UniversalParams<E> {
121      fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
122          // Deserialize `powers`.
123          let powers = Arc::new(PowersOfG::read_le(&mut reader)?);
124  
125          // Deserialize `h`.
126          let h: E::G2Affine = FromBytes::read_le(&mut reader)?;
127  
128          // Deserialize `prepared_h`.
129          let prepared_h: <E::G2Affine as PairingCurve>::Prepared = FromBytes::read_le(&mut reader)?;
130  
131          // Deserialize `prepared_beta_h`.
132          let prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared = FromBytes::read_le(&mut reader)?;
133  
134          Ok(Self { powers, h, prepared_h, prepared_beta_h })
135      }
136  }
137  
138  impl<E: PairingEngine> ToBytes for UniversalParams<E> {
139      fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
140          // Serialize powers.
141          self.powers.write_le(&mut writer)?;
142  
143          // Serialize `h`.
144          self.h.write_le(&mut writer)?;
145  
146          // Serialize `prepared_h`.
147          self.prepared_h.write_le(&mut writer)?;
148  
149          // Serialize `prepared_beta_h`.
150          self.prepared_beta_h.write_le(&mut writer)?;
151  
152          Ok(())
153      }
154  }
155  
156  /// `Powers` is used to commit to and create evaluation proofs for a given
157  /// polynomial.
158  #[derive(Clone, Debug, Default, Hash)]
159  pub struct Powers<'a, E: PairingEngine> {
160      /// Group elements of the form `β^i G`, for different values of `i`.
161      pub powers_of_beta_g: Cow<'a, [E::G1Affine]>,
162      /// Group elements of the form `β^i γG`, for different values of `i`.
163      pub powers_of_beta_times_gamma_g: Cow<'a, [E::G1Affine]>,
164  }
165  
166  impl<E: PairingEngine> Powers<'_, E> {
167      /// The number of powers in `self`.
168      pub fn size(&self) -> usize {
169          self.powers_of_beta_g.len()
170      }
171  }
172  /// `LagrangeBasis` is used to commit to and create evaluation proofs for a
173  /// given polynomial.
174  #[derive(Clone, Debug, Hash)]
175  pub struct LagrangeBasis<'a, E: PairingEngine> {
176      /// Group elements of the form `β^i G`, for different values of `i`.
177      pub lagrange_basis_at_beta_g: Cow<'a, [E::G1Affine]>,
178      /// Group elements of the form `β^i γG`, for different values of `i`.
179      pub powers_of_beta_times_gamma_g: Cow<'a, [E::G1Affine]>,
180      /// Domain representing the multiplicative subgroup the powers
181      /// in `self.lagrange_basis_at_beta_g` are defined over.
182      pub domain: EvaluationDomain<E::Fr>,
183  }
184  
185  impl<E: PairingEngine> LagrangeBasis<'_, E> {
186      /// The number of powers in `self`.
187      pub fn size(&self) -> usize {
188          self.lagrange_basis_at_beta_g.len()
189      }
190  }
191  
192  /// `VerifierKey` is used to check evaluation proofs for a given commitment.
193  #[derive(Clone, Debug, Default, PartialEq, Eq)]
194  pub struct VerifierKey<E: PairingEngine> {
195      /// The generator of G1.
196      pub g: E::G1Affine,
197      /// The generator of G1 that is used for making a commitment hiding.
198      pub gamma_g: E::G1Affine,
199      /// The generator of G2.
200      pub h: E::G2Affine,
201      /// \beta times the above generator of G2.
202      pub beta_h: E::G2Affine,
203      /// The generator of G2, prepared for use in pairings.
204      pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
205      /// \beta times the above generator of G2, prepared for use in pairings.
206      pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
207  }
208  
209  impl<E: PairingEngine> CanonicalSerialize for VerifierKey<E> {
210      fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
211          self.g.serialize_with_mode(&mut writer, compress)?;
212          self.gamma_g.serialize_with_mode(&mut writer, compress)?;
213          self.h.serialize_with_mode(&mut writer, compress)?;
214          self.beta_h.serialize_with_mode(&mut writer, compress)?;
215          Ok(())
216      }
217  
218      fn serialized_size(&self, compress: Compress) -> usize {
219          self.g.serialized_size(compress)
220              + self.gamma_g.serialized_size(compress)
221              + self.h.serialized_size(compress)
222              + self.beta_h.serialized_size(compress)
223      }
224  }
225  
226  impl<E: PairingEngine> CanonicalDeserialize for VerifierKey<E> {
227      fn deserialize_with_mode<R: Read>(
228          mut reader: R,
229          compress: Compress,
230          validate: Validate,
231      ) -> Result<Self, SerializationError> {
232          let g = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
233          let gamma_g = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
234          let h: E::G2Affine = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
235          let beta_h: E::G2Affine = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
236          let prepared_h = h.prepare();
237          let prepared_beta_h = beta_h.prepare();
238          Ok(VerifierKey { g, gamma_g, h, beta_h, prepared_h, prepared_beta_h })
239      }
240  }
241  
242  impl<E: PairingEngine> Valid for VerifierKey<E> {
243      fn check(&self) -> Result<(), SerializationError> {
244          Valid::check(&self.g)?;
245          Valid::check(&self.gamma_g)?;
246          Valid::check(&self.h)?;
247          Valid::check(&self.beta_h)?;
248          Ok(())
249      }
250  
251      fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
252      where
253          Self: 'a,
254      {
255          let batch: Vec<_> = batch.collect();
256          Valid::batch_check(batch.iter().map(|v| &v.g))?;
257          Valid::batch_check(batch.iter().map(|v| &v.gamma_g))?;
258          Valid::batch_check(batch.iter().map(|v| &v.h))?;
259          Valid::batch_check(batch.iter().map(|v| &v.beta_h))?;
260          Ok(())
261      }
262  }
263  
264  impl<E: PairingEngine> FromBytes for VerifierKey<E> {
265      fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
266          CanonicalDeserialize::deserialize_compressed(&mut reader)
267              .map_err(|_| error("could not deserialize VerifierKey"))
268      }
269  }
270  
271  impl<E: PairingEngine> ToBytes for VerifierKey<E> {
272      fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
273          CanonicalSerialize::serialize_compressed(self, &mut writer)
274              .map_err(|_| error("could not serialize VerifierKey"))
275      }
276  }
277  
278  /// `KZGCommitment` commits to a polynomial. It is output by `KZG10::commit`.
279  #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
280  pub struct KZGCommitment<E: PairingEngine>(
281      /// The commitment is a group element.
282      pub E::G1Affine,
283  );
284  
285  impl<E: PairingEngine> FromBytes for KZGCommitment<E> {
286      fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
287          CanonicalDeserialize::deserialize_compressed(&mut reader)
288              .map_err(|_| error("could not deserialize KZGCommitment"))
289      }
290  }
291  
292  impl<E: PairingEngine> ToBytes for KZGCommitment<E> {
293      fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
294          CanonicalSerialize::serialize_compressed(self, &mut writer)
295              .map_err(|_| error("could not serialize KZGCommitment"))
296      }
297  }
298  
299  impl<E: PairingEngine> KZGCommitment<E> {
300      #[inline]
301      pub fn empty() -> Self {
302          KZGCommitment(E::G1Affine::zero())
303      }
304  
305      pub fn has_degree_bound(&self) -> bool {
306          false
307      }
308  
309      pub fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool {
310          self.0.is_in_correct_subgroup_assuming_on_curve()
311      }
312  }
313  
314  impl<E: PairingEngine> ToConstraintField<E::Fq> for KZGCommitment<E> {
315      fn to_field_elements(&self) -> Result<Vec<E::Fq>, ConstraintFieldError> {
316          self.0.to_field_elements()
317      }
318  }
319  
320  /// `KZGRandomness` hides the polynomial inside a commitment. It is output by
321  /// `KZG10::commit`.
322  #[derive(Clone, Debug, Default, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
323  pub struct KZGRandomness<E: PairingEngine> {
324      /// For KZG10, the commitment randomness is a random polynomial.
325      pub blinding_polynomial: DensePolynomial<E::Fr>,
326  }
327  impl<E: PairingEngine> FromBytes for KZGRandomness<E> {
328      fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
329          CanonicalDeserialize::deserialize_compressed(&mut reader)
330              .map_err(|_| error("could not deserialize KZGRandomness"))
331      }
332  }
333  
334  impl<E: PairingEngine> ToBytes for KZGRandomness<E> {
335      fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
336          CanonicalSerialize::serialize_compressed(self, &mut writer)
337              .map_err(|_| error("could not serialize KZGRandomness"))
338      }
339  }
340  
341  impl<E: PairingEngine> KZGRandomness<E> {
342      /// Does `self` provide any hiding properties to the corresponding
343      /// commitment? `self.is_hiding() == true` only if the underlying
344      /// polynomial is non-zero.
345      #[inline]
346      pub fn is_hiding(&self) -> bool {
347          !self.blinding_polynomial.is_zero()
348      }
349  
350      /// What is the degree of the hiding polynomial for a given hiding bound?
351      #[inline]
352      pub fn calculate_hiding_polynomial_degree(hiding_bound: usize) -> usize {
353          hiding_bound + 1
354      }
355  }
356  
357  impl<E: PairingEngine> KZGRandomness<E> {
358      pub fn empty() -> Self {
359          Self { blinding_polynomial: DensePolynomial::zero() }
360      }
361  
362      pub fn rand<R: RngCore>(hiding_bound: usize, _: bool, rng: &mut R) -> Self {
363          let mut randomness = KZGRandomness::empty();
364          let hiding_poly_degree = Self::calculate_hiding_polynomial_degree(hiding_bound);
365          randomness.blinding_polynomial = DensePolynomial::rand(hiding_poly_degree, rng);
366          randomness
367      }
368  }
369  
370  impl<'a, E: PairingEngine> Add<&'a KZGRandomness<E>> for KZGRandomness<E> {
371      type Output = Self;
372  
373      #[inline]
374      fn add(mut self, other: &'a Self) -> Self {
375          self.blinding_polynomial += &other.blinding_polynomial;
376          self
377      }
378  }
379  
380  impl<'a, E: PairingEngine> Add<(E::Fr, &'a KZGRandomness<E>)> for KZGRandomness<E> {
381      type Output = Self;
382  
383      #[inline]
384      fn add(mut self, other: (E::Fr, &'a KZGRandomness<E>)) -> Self {
385          self += other;
386          self
387      }
388  }
389  
390  impl<'a, E: PairingEngine> AddAssign<&'a KZGRandomness<E>> for KZGRandomness<E> {
391      #[inline]
392      fn add_assign(&mut self, other: &'a Self) {
393          self.blinding_polynomial += &other.blinding_polynomial;
394      }
395  }
396  
397  impl<'a, E: PairingEngine> AddAssign<(E::Fr, &'a KZGRandomness<E>)> for KZGRandomness<E> {
398      #[inline]
399      fn add_assign(&mut self, (f, other): (E::Fr, &'a KZGRandomness<E>)) {
400          self.blinding_polynomial += (f, &other.blinding_polynomial);
401      }
402  }
403  
404  /// `KZGProof` is an evaluation proof that is output by `KZG10::open`.
405  #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
406  pub struct KZGProof<E: PairingEngine> {
407      /// This is a commitment to the witness polynomial; see [\[KZG10\]][kzg] for
408      /// more details.
409      ///
410      /// [kzg]: http://cacr.uwaterloo.ca/techreports/2010/cacr2010-10.pdf
411      pub w: E::G1Affine,
412      /// This is the evaluation of the random polynomial at the point for which
413      /// the evaluation proof was produced.
414      pub random_v: Option<E::Fr>,
415  }
416  
417  impl<E: PairingEngine> KZGProof<E> {
418      pub fn absorb_into_sponge(&self, sponge: &mut impl AlgebraicSponge<E::Fq, 2>) {
419          sponge.absorb_native_field_elements(&self.w.to_field_elements().unwrap());
420          if let Some(random_v) = self.random_v {
421              sponge.absorb_nonnative_field_elements([random_v]);
422          }
423      }
424  }
425  
426  impl<E: PairingEngine> FromBytes for KZGProof<E> {
427      fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
428          CanonicalDeserialize::deserialize_compressed(&mut reader)
429              .map_err(|err| into_io_error(anyhow::Error::from(err).context("could not deserialize KZG proof")))
430      }
431  }
432  
433  impl<E: PairingEngine> ToBytes for KZGProof<E> {
434      fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
435          CanonicalSerialize::serialize_compressed(self, &mut writer)
436              .map_err(|err| into_io_error(anyhow::Error::from(err).context("could not serialize KZG proof")))
437      }
438  }
439  
440  impl<E: PairingEngine> KZGProof<E> {
441      pub fn is_hiding(&self) -> bool {
442          self.random_v.is_some()
443      }
444  }