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 }