powers.rs
1 // Copyright (c) 2025-2026 ACDC Network 2 // This file is part of the alphavm library. 3 // 4 // Alpha Chain | Delta Chain Protocol 5 // International Monetary Graphite. 6 // 7 // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com). 8 // They built world-class ZK infrastructure. We installed the EASY button. 9 // Their cryptography: elegant. Our modifications: bureaucracy-compatible. 10 // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours. 11 // 12 // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0 13 // All modifications and new work: CC0 1.0 Universal Public Domain Dedication. 14 // No rights reserved. No permission required. No warranty. No refunds. 15 // 16 // https://creativecommons.org/publicdomain/zero/1.0/ 17 // SPDX-License-Identifier: CC0-1.0 18 19 use super::*; 20 use alphavm_curves::traits::{PairingCurve, PairingEngine}; 21 use alphavm_utilities::{ 22 dev_println, 23 CanonicalDeserialize, 24 CanonicalSerialize, 25 Compress, 26 FromBytes, 27 Read, 28 SerializationError, 29 ToBytes, 30 Valid, 31 Validate, 32 Write, 33 }; 34 35 use anyhow::{anyhow, bail, ensure, Result}; 36 #[cfg(feature = "locktick")] 37 use locktick::parking_lot::RwLock; 38 #[cfg(not(feature = "locktick"))] 39 use parking_lot::RwLock; 40 use std::{collections::BTreeMap, ops::Range, sync::Arc}; 41 42 const NUM_POWERS_15: usize = 1 << 15; 43 const NUM_POWERS_16: usize = 1 << 16; 44 const NUM_POWERS_17: usize = 1 << 17; 45 const NUM_POWERS_18: usize = 1 << 18; 46 const NUM_POWERS_19: usize = 1 << 19; 47 const NUM_POWERS_20: usize = 1 << 20; 48 const NUM_POWERS_21: usize = 1 << 21; 49 const NUM_POWERS_22: usize = 1 << 22; 50 const NUM_POWERS_23: usize = 1 << 23; 51 const NUM_POWERS_24: usize = 1 << 24; 52 const NUM_POWERS_25: usize = 1 << 25; 53 // TODO(ACDC): Powers 26-27 (64M/128M elements) disabled in CI for performance. 54 // Trade-off: Enabling `large_params` feature would add ~10-30min CI time and require 16GB+ RAM. 55 // These powers are only needed for very large circuits not currently in use. 56 // To test: `cargo test --features large_params` (locally, not CI). 57 #[cfg(feature = "large_params")] 58 const NUM_POWERS_26: usize = 1 << 26; 59 #[cfg(feature = "large_params")] 60 const NUM_POWERS_27: usize = 1 << 27; 61 const NUM_POWERS_28: usize = 1 << 28; 62 63 /// The maximum degree supported by the SRS. 64 pub const MAX_NUM_POWERS: usize = NUM_POWERS_28; 65 66 lazy_static::lazy_static! { 67 static ref POWERS_OF_BETA_G_15: Vec<u8> = Degree15::load_bytes().expect("Failed to load powers of beta in universal SRS"); 68 static ref SHIFTED_POWERS_OF_BETA_G_15: Vec<u8> = ShiftedDegree15::load_bytes().expect("Failed to load powers of beta in universal SRS"); 69 static ref POWERS_OF_BETA_GAMMA_G: Vec<u8> = Gamma::load_bytes().expect("Failed to load powers of beta wrt gamma * G in universal SRS"); 70 static ref NEG_POWERS_OF_BETA_H: Vec<u8> = NegBeta::load_bytes().expect("Failed to load negative powers of beta in universal SRS"); 71 static ref BETA_H: Vec<u8> = BetaH::load_bytes().expect("Failed to load negative powers of beta in universal SRS"); 72 } 73 74 /// A vector of powers of beta G. 75 #[derive(Debug)] 76 pub struct PowersOfG<E: PairingEngine> { 77 /// The powers of beta G. 78 powers_of_beta_g: RwLock<PowersOfBetaG<E>>, 79 /// Group elements of form `{ \beta^i \gamma G }`, where `i` is from 0 to `degree`, 80 /// This is used for hiding. 81 powers_of_beta_times_gamma_g: BTreeMap<usize, E::G1Affine>, 82 /// Group elements of form `{ \beta^{max_degree - i} H }`, where `i` 83 /// is of the form `2^k - 1` for `k` in `1` to `log_2(max_degree)`. 84 negative_powers_of_beta_h: BTreeMap<usize, E::G2Affine>, 85 /// Information required to enforce degree bounds. Each pair is of the form `(degree_bound, shifting_advice)`. 86 /// Each pair is in the form `(degree_bound, \beta^{max_degree - i} H),` where `H` is the generator of G2, 87 /// and `i` is of the form `2^k - 1` for `k` in `1` to `log_2(max_degree)`. 88 prepared_negative_powers_of_beta_h: Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>>, 89 /// beta * h 90 beta_h: E::G2Affine, 91 } 92 93 impl<E: PairingEngine> PowersOfG<E> { 94 /// Initializes the hard-coded instance of the powers. 95 pub fn load() -> Result<Self> { 96 let powers_of_beta_g = RwLock::new(PowersOfBetaG::load()?); 97 98 // Reconstruct powers of beta_times_gamma_g. 99 let powers_of_beta_times_gamma_g = BTreeMap::deserialize_uncompressed_unchecked(&**POWERS_OF_BETA_GAMMA_G)?; 100 101 // Reconstruct negative powers of beta_h. 102 let negative_powers_of_beta_h: BTreeMap<usize, E::G2Affine> = 103 BTreeMap::deserialize_uncompressed_unchecked(&**NEG_POWERS_OF_BETA_H)?; 104 105 // Compute the prepared negative powers of beta_h. 106 let prepared_negative_powers_of_beta_h: Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>> = 107 Arc::new(negative_powers_of_beta_h.iter().map(|(d, affine)| (*d, affine.prepare())).collect()); 108 109 let beta_h = E::G2Affine::deserialize_uncompressed_unchecked(&**BETA_H)?; 110 111 // Return the powers. 112 Ok(Self { 113 powers_of_beta_g, 114 powers_of_beta_times_gamma_g, 115 negative_powers_of_beta_h, 116 prepared_negative_powers_of_beta_h, 117 beta_h, 118 }) 119 } 120 121 /// Download the powers of beta G specified by `range`. 122 pub fn download_powers_for(&self, range: Range<usize>) -> Result<()> { 123 self.powers_of_beta_g.write().download_powers_for(&range) 124 } 125 126 /// Returns the number of contiguous powers of beta G starting from the 0-th power. 127 pub fn num_powers(&self) -> usize { 128 self.powers_of_beta_g.read().num_powers() 129 } 130 131 /// Returns the maximum possible number of contiguous powers of beta G starting from the 0-th power. 132 pub fn max_num_powers(&self) -> usize { 133 MAX_NUM_POWERS 134 } 135 136 /// Returns the powers of beta * gamma G. 137 pub fn powers_of_beta_gamma_g(&self) -> &BTreeMap<usize, E::G1Affine> { 138 &self.powers_of_beta_times_gamma_g 139 } 140 141 /// Returns the `index`-th power of beta * G. 142 pub fn power_of_beta_g(&self, index: usize) -> Result<E::G1Affine> { 143 self.powers_of_beta_g.write().power(index) 144 } 145 146 /// Returns the powers of `beta * G` that lie within `range`. 147 pub fn powers_of_beta_g(&self, range: Range<usize>) -> Result<Vec<E::G1Affine>> { 148 Ok(self.powers_of_beta_g.write().powers(range)?.to_vec()) 149 } 150 151 pub fn negative_powers_of_beta_h(&self) -> &BTreeMap<usize, E::G2Affine> { 152 &self.negative_powers_of_beta_h 153 } 154 155 pub fn prepared_negative_powers_of_beta_h(&self) -> Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>> { 156 self.prepared_negative_powers_of_beta_h.clone() 157 } 158 159 pub fn beta_h(&self) -> E::G2Affine { 160 self.beta_h 161 } 162 } 163 164 impl<E: PairingEngine> CanonicalSerialize for PowersOfG<E> { 165 fn serialize_with_mode<W: Write>(&self, mut writer: W, mode: Compress) -> Result<(), SerializationError> { 166 self.powers_of_beta_g.read().serialize_with_mode(&mut writer, mode)?; 167 self.powers_of_beta_times_gamma_g.serialize_with_mode(&mut writer, mode)?; 168 self.negative_powers_of_beta_h.serialize_with_mode(&mut writer, mode)?; 169 self.beta_h.serialize_with_mode(&mut writer, mode)?; 170 Ok(()) 171 } 172 173 fn serialized_size(&self, mode: Compress) -> usize { 174 self.powers_of_beta_g.read().serialized_size(mode) 175 + self.powers_of_beta_times_gamma_g.serialized_size(mode) 176 + self.negative_powers_of_beta_h.serialized_size(mode) 177 + self.beta_h.serialized_size(mode) 178 } 179 } 180 181 impl<E: PairingEngine> CanonicalDeserialize for PowersOfG<E> { 182 fn deserialize_with_mode<R: Read>(mut reader: R, compress: Compress, validate: Validate) -> Result<Self, SerializationError> { 183 let powers_of_beta_g = RwLock::new(PowersOfBetaG::deserialize_with_mode(&mut reader, compress, Validate::No)?); 184 185 // Reconstruct powers of beta_times_gamma_g. 186 let powers_of_beta_times_gamma_g = BTreeMap::deserialize_with_mode(&mut reader, compress, Validate::No)?; 187 188 // Reconstruct negative powers of beta_h. 189 let negative_powers_of_beta_h: BTreeMap<usize, E::G2Affine> = 190 BTreeMap::deserialize_with_mode(&mut reader, compress, Validate::No)?; 191 192 // Compute the prepared negative powers of beta_h. 193 let prepared_negative_powers_of_beta_h: Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>> = 194 Arc::new(negative_powers_of_beta_h.iter().map(|(d, affine)| (*d, affine.prepare())).collect()); 195 196 let beta_h = E::G2Affine::deserialize_with_mode(&mut reader, compress, Validate::No)?; 197 198 let powers = Self { 199 powers_of_beta_g, 200 powers_of_beta_times_gamma_g, 201 negative_powers_of_beta_h, 202 prepared_negative_powers_of_beta_h, 203 beta_h, 204 }; 205 if let Validate::Yes = validate { 206 powers.check()?; 207 } 208 Ok(powers) 209 } 210 } 211 212 impl<E: PairingEngine> Valid for PowersOfG<E> { 213 fn check(&self) -> Result<(), SerializationError> { 214 self.powers_of_beta_g.read().check()?; 215 self.powers_of_beta_times_gamma_g.check()?; 216 self.negative_powers_of_beta_h.check()?; 217 self.prepared_negative_powers_of_beta_h.check()?; 218 self.beta_h.check() 219 } 220 } 221 222 impl<E: PairingEngine> FromBytes for PowersOfG<E> { 223 /// Reads the powers from the buffer. 224 fn read_le<R: Read>(reader: R) -> std::io::Result<Self> { 225 Self::deserialize_with_mode(reader, Compress::No, Validate::No).map_err(|e| e.into()) 226 } 227 } 228 229 impl<E: PairingEngine> ToBytes for PowersOfG<E> { 230 /// Writes the powers to the buffer. 231 fn write_le<W: Write>(&self, writer: W) -> std::io::Result<()> { 232 self.serialize_with_mode(writer, Compress::No).map_err(|e| e.into()) 233 } 234 } 235 236 #[derive(Debug, CanonicalSerialize, CanonicalDeserialize)] 237 pub struct PowersOfBetaG<E: PairingEngine> { 238 /// Group elements of form `[G, \beta * G, \beta^2 * G, ..., \beta^d G]`. 239 powers_of_beta_g: Vec<E::G1Affine>, 240 /// Group elements of form `[\beta^i * G, \beta^2 * G, ..., \beta^D G]`. 241 /// where D is the maximum degree supported by the SRS. 242 shifted_powers_of_beta_g: Vec<E::G1Affine>, 243 } 244 245 impl<E: PairingEngine> PowersOfBetaG<E> { 246 /// Returns the number of contiguous powers of beta G starting from the 0-th power. 247 pub fn num_powers(&self) -> usize { 248 self.powers_of_beta_g.len() 249 } 250 251 /// Initializes the hard-coded instance of the powers. 252 fn load() -> Result<Self> { 253 // Deserialize the group elements. 254 let powers_of_beta_g = Vec::deserialize_uncompressed_unchecked(&**POWERS_OF_BETA_G_15)?; 255 256 // Ensure the number of elements is correct. 257 ensure!(powers_of_beta_g.len() == NUM_POWERS_15, "Incorrect number of powers in the recovered SRS"); 258 259 let shifted_powers_of_beta_g = Vec::deserialize_uncompressed_unchecked(&**SHIFTED_POWERS_OF_BETA_G_15)?; 260 ensure!(shifted_powers_of_beta_g.len() == NUM_POWERS_15, "Incorrect number of powers in the recovered SRS"); 261 Ok(PowersOfBetaG { powers_of_beta_g, shifted_powers_of_beta_g }) 262 } 263 264 /// Returns the range of powers of beta G. 265 /// In detail, it returns the range of the available "normal" powers of beta G, i.e. the 266 /// contiguous range of powers of beta G starting from G, and, the range of shifted_powers. 267 /// 268 /// For example, if the output of this function is `(0..8, 24..32)`, then `self` 269 /// contains the powers 270 /// * `beta^0 * G, beta^1 * G, ..., beta^7 * G`, and 271 /// * `beta^24 * G, ..., beta^31 * G`. 272 pub fn available_powers(&self) -> (Range<usize>, Range<usize>) { 273 if !self.shifted_powers_of_beta_g.is_empty() { 274 let lower_shifted_bound = MAX_NUM_POWERS - self.shifted_powers_of_beta_g.len(); 275 ((0..self.powers_of_beta_g.len()), (lower_shifted_bound..MAX_NUM_POWERS)) 276 } else { 277 // We can only be in this case if have downloaded all possible powers. 278 assert_eq!(self.powers_of_beta_g.len(), MAX_NUM_POWERS, "Incorrect number of powers in the recovered SRS"); 279 ((0..MAX_NUM_POWERS), (0..MAX_NUM_POWERS)) 280 } 281 } 282 283 fn contains_in_normal_powers(&self, range: &Range<usize>) -> bool { 284 let (normal, _) = self.available_powers(); 285 normal.contains(&range.start) && (normal.end >= range.end) 286 } 287 288 fn contains_in_shifted_powers(&self, range: &Range<usize>) -> bool { 289 let (_, shifted) = self.available_powers(); 290 shifted.contains(&range.start) && (shifted.end >= range.end) 291 } 292 293 fn contains_powers(&self, range: &Range<usize>) -> bool { 294 self.contains_in_normal_powers(range) || self.contains_in_shifted_powers(range) 295 } 296 297 fn distance_from_normal_of(&self, range: &Range<usize>) -> usize { 298 (range.end as isize - self.available_powers().0.end as isize).unsigned_abs() 299 } 300 301 fn distance_from_shifted_of(&self, range: &Range<usize>) -> usize { 302 (range.start as isize - self.available_powers().1.start as isize).unsigned_abs() 303 } 304 305 /// Assumes that we have the requisite powers. 306 fn shifted_powers(&self, range: Range<usize>) -> Result<&[E::G1Affine]> { 307 ensure!(self.contains_in_shifted_powers(&range), "Requested range is not contained in the available shifted powers"); 308 309 if range.start < MAX_NUM_POWERS / 2 { 310 ensure!(self.shifted_powers_of_beta_g.is_empty()); 311 // In this case, we have downloaded all the powers, and so 312 // all the powers reside in self.powers_of_beta_g. 313 Ok(&self.powers_of_beta_g[range]) 314 } else { 315 // In this case, the shifted powers still reside in self.shifted_powers_of_beta_g. 316 let lower = self.shifted_powers_of_beta_g.len() - (MAX_NUM_POWERS - range.start); 317 let upper = self.shifted_powers_of_beta_g.len() - (MAX_NUM_POWERS - range.end); 318 Ok(&self.shifted_powers_of_beta_g[lower..upper]) 319 } 320 } 321 322 /// Assumes that we have the requisite powers. 323 fn normal_powers(&self, range: Range<usize>) -> Result<&[E::G1Affine]> { 324 ensure!(self.contains_in_normal_powers(&range), "Requested range is not contained in the available powers"); 325 Ok(&self.powers_of_beta_g[range]) 326 } 327 328 /// Returns the power of beta times G specified by `target`. 329 fn power(&mut self, target: usize) -> Result<E::G1Affine> { 330 self.powers(target..(target + 1)).map(|s| s[0]) 331 } 332 333 /// Slices the underlying file to return a vector of affine elements between `lower` and `upper`. 334 fn powers(&mut self, range: Range<usize>) -> Result<&[E::G1Affine]> { 335 if range.is_empty() { 336 return Ok(&self.powers_of_beta_g[0..0]); 337 } 338 ensure!(range.start < range.end, "Lower power must be less than upper power"); 339 ensure!(range.end <= MAX_NUM_POWERS, "Upper bound must be less than the maximum number of powers"); 340 if !self.contains_powers(&range) { 341 // We must download the powers. 342 self.download_powers_for(&range)?; 343 } 344 match self.contains_in_normal_powers(&range) { 345 true => self.normal_powers(range), 346 false => self.shifted_powers(range), 347 } 348 } 349 350 pub fn download_powers_for(&mut self, range: &Range<usize>) -> Result<()> { 351 if self.contains_in_normal_powers(range) || self.contains_in_shifted_powers(range) { 352 return Ok(()); 353 } 354 let half_max = MAX_NUM_POWERS / 2; 355 if (range.start <= half_max) && (range.end > half_max) { 356 // If the range contains the midpoint, then we must download all the powers. 357 // (because we round up to the next power of two). 358 self.download_powers_up_to(range.end)?; 359 self.shifted_powers_of_beta_g = Vec::new(); 360 } else if self.distance_from_shifted_of(range) < self.distance_from_normal_of(range) { 361 // If the range is closer to the shifted powers, then we download the shifted powers. 362 self.download_shifted_powers_from(range.start)?; 363 } else { 364 // Otherwise, we download the normal powers. 365 self.download_powers_up_to(range.end)?; 366 } 367 Ok(()) 368 } 369 370 /// This method downloads the universal SRS powers up to the `next_power_of_two(target_degree)`, 371 /// and updates `Self` in place with the new powers. 372 fn download_powers_up_to(&mut self, end: usize) -> Result<()> { 373 // Determine the new power of two. 374 let final_power_of_two = end.checked_next_power_of_two().ok_or_else(|| anyhow!("Requesting too many powers"))?; 375 // Ensure the total number of powers is less than the maximum number of powers. 376 ensure!(final_power_of_two <= MAX_NUM_POWERS, "Requesting more powers than exist in the SRS"); 377 378 // Retrieve the current power of two. 379 let current_power_of_two = 380 self.powers_of_beta_g.len().checked_next_power_of_two().ok_or_else(|| anyhow!("The current degree is too large"))?; 381 382 // Initialize a vector for the powers of two to be downloaded. 383 let mut download_queue = Vec::with_capacity(14); 384 385 // Initialize the first degree to download. 386 let mut accumulator = current_power_of_two * 2; 387 // Determine the powers of two to download. 388 while accumulator <= final_power_of_two { 389 download_queue.push(accumulator); 390 accumulator = accumulator.checked_mul(2).ok_or_else(|| anyhow!("Overflowed while requesting a larger degree"))?; 391 } 392 ensure!(final_power_of_two * 2 == accumulator, "Ensure the loop terminates at the right power of two"); 393 394 // Reserve capacity for the new powers of two. 395 let additional_size = final_power_of_two 396 .checked_sub(self.powers_of_beta_g.len()) 397 .ok_or_else(|| anyhow!("final_power_of_two is smaller than existing powers"))?; 398 self.powers_of_beta_g.reserve(additional_size); 399 400 // Download the powers of two. 401 for num_powers in &download_queue { 402 dev_println!("Loading {num_powers} powers"); 403 404 // Download the universal SRS powers if they're not already on disk. 405 let additional_bytes = match *num_powers { 406 NUM_POWERS_16 => Degree16::load_bytes()?, 407 NUM_POWERS_17 => Degree17::load_bytes()?, 408 NUM_POWERS_18 => Degree18::load_bytes()?, 409 NUM_POWERS_19 => Degree19::load_bytes()?, 410 NUM_POWERS_20 => Degree20::load_bytes()?, 411 NUM_POWERS_21 => Degree21::load_bytes()?, 412 NUM_POWERS_22 => Degree22::load_bytes()?, 413 NUM_POWERS_23 => Degree23::load_bytes()?, 414 NUM_POWERS_24 => Degree24::load_bytes()?, 415 NUM_POWERS_25 => Degree25::load_bytes()?, 416 // TODO(ACDC): Degree 26-28 gated behind large_params feature for CI performance. 417 #[cfg(feature = "large_params")] 418 NUM_POWERS_26 => Degree26::load_bytes()?, 419 #[cfg(feature = "large_params")] 420 NUM_POWERS_27 => Degree27::load_bytes()?, 421 #[cfg(feature = "large_params")] 422 NUM_POWERS_28 => Degree28::load_bytes()?, 423 _ => bail!("Cannot download an invalid degree of '{num_powers}'"), 424 }; 425 426 // Deserialize the group elements. 427 let additional_powers = Vec::deserialize_uncompressed_unchecked(&*additional_bytes)?; 428 // Extend the powers. 429 self.powers_of_beta_g.extend(&additional_powers); 430 } 431 ensure!(self.powers_of_beta_g.len() == final_power_of_two, "Loaded an incorrect number of powers"); 432 Ok(()) 433 } 434 435 /// This method downloads the universal SRS powers from 436 /// `start` up to `MAXIMUM_NUM_POWERS - self.shifted_powers_of_beta_g.len()`, 437 /// and updates `Self` in place with the new powers. 438 fn download_shifted_powers_from(&mut self, start: usize) -> Result<()> { 439 // Ensure the total number of powers is less than the maximum number of powers. 440 ensure!(start <= MAX_NUM_POWERS, "Requesting more powers than exist in the SRS"); 441 442 // The possible powers are: 443 // (2^28 - 2^15)..=(2^28) = 2^15 powers 444 // (2^28 - 2^16)..(2^28 - 2^15) = 2^15 powers 445 // (2^28 - 2^17)..(2^28 - 2^16) = 2^16 powers 446 // (2^28 - 2^18)..(2^28 - 2^17) = 2^17 powers 447 // (2^28 - 2^19)..(2^28 - 2^18) = 2^18 powers 448 // (2^28 - 2^20)..(2^28 - 2^19) = 2^19 powers 449 // (2^28 - 2^21)..(2^28 - 2^20) = 2^20 powers 450 // (2^28 - 2^22)..(2^28 - 2^21) = 2^21 powers 451 // (2^28 - 2^23)..(2^28 - 2^22) = 2^22 powers 452 // (2^28 - 2^24)..(2^28 - 2^23) = 2^23 powers 453 // (2^28 - 2^25)..(2^28 - 2^24) = 2^24 powers 454 // (2^28 - 2^26)..(2^28 - 2^25) = 2^25 powers 455 // (2^28 - 2^27)..(2^28 - 2^26) = 2^26 powers 456 457 // Figure out the number of powers to download, as follows: 458 // Let `start := 2^28 - k`. 459 // We know that `shifted_powers_of_beta_g.len() = 2^s` such that `2^s < k`. 460 // That is, we have already downloaded the powers `2^28 - 2^s` up to `2^28`. 461 // Then, we have to download the powers 2^s..k.next_power_of_two(). 462 let final_num_powers = MAX_NUM_POWERS 463 .checked_sub(start) 464 .ok_or_else(|| anyhow!("Requesting too many powers: `start ({start}) > MAX_NUM_POWERS ({MAX_NUM_POWERS})`"))? 465 .checked_next_power_of_two() 466 .ok_or_else(|| anyhow!("Requesting too many powers"))?; // Calculated k.next_power_of_two(). 467 468 let mut download_queue = Vec::with_capacity(14); 469 let mut existing_num_powers = self.shifted_powers_of_beta_g.len(); 470 while existing_num_powers < final_num_powers { 471 existing_num_powers = 472 existing_num_powers.checked_mul(2).ok_or_else(|| anyhow!("Overflowed while requesting additional powers"))?; 473 download_queue.push(existing_num_powers); 474 } 475 download_queue.reverse(); // We want to download starting from the smallest power. 476 477 let mut final_powers = Vec::with_capacity(final_num_powers); 478 // If the `target_degree` exceeds the current `degree`, proceed to download the new powers. 479 for num_powers in &download_queue { 480 dev_println!("Loading {num_powers} shifted powers"); 481 482 // Download the universal SRS powers if they're not already on disk. 483 let additional_bytes = match *num_powers { 484 NUM_POWERS_16 => ShiftedDegree16::load_bytes()?, 485 NUM_POWERS_17 => ShiftedDegree17::load_bytes()?, 486 NUM_POWERS_18 => ShiftedDegree18::load_bytes()?, 487 NUM_POWERS_19 => ShiftedDegree19::load_bytes()?, 488 NUM_POWERS_20 => ShiftedDegree20::load_bytes()?, 489 NUM_POWERS_21 => ShiftedDegree21::load_bytes()?, 490 NUM_POWERS_22 => ShiftedDegree22::load_bytes()?, 491 NUM_POWERS_23 => ShiftedDegree23::load_bytes()?, 492 NUM_POWERS_24 => ShiftedDegree24::load_bytes()?, 493 NUM_POWERS_25 => ShiftedDegree25::load_bytes()?, 494 // TODO(ACDC): ShiftedDegree 26-27 gated behind large_params feature for CI performance. 495 #[cfg(feature = "large_params")] 496 NUM_POWERS_26 => ShiftedDegree26::load_bytes()?, 497 #[cfg(feature = "large_params")] 498 NUM_POWERS_27 => ShiftedDegree27::load_bytes()?, 499 _ => bail!("Cannot download an invalid degree of '{num_powers}'"), 500 }; 501 502 // Deserialize the group elements. 503 let additional_powers = Vec::deserialize_uncompressed_unchecked(&*additional_bytes)?; 504 505 final_powers.extend(additional_powers.iter()); 506 } 507 final_powers.extend(self.shifted_powers_of_beta_g.iter()); 508 self.shifted_powers_of_beta_g = final_powers; 509 510 ensure!(self.shifted_powers_of_beta_g.len() == final_num_powers, "Loaded an incorrect number of shifted powers"); 511 Ok(()) 512 } 513 } 514 515 impl<E: PairingEngine> FromBytes for PowersOfBetaG<E> { 516 /// Reads the powers from the buffer. 517 fn read_le<R: Read>(reader: R) -> std::io::Result<Self> { 518 Self::deserialize_with_mode(reader, Compress::No, Validate::No).map_err(|e| e.into()) 519 } 520 } 521 522 impl<E: PairingEngine> ToBytes for PowersOfBetaG<E> { 523 /// Writes the powers to the buffer. 524 fn write_le<W: Write>(&self, writer: W) -> std::io::Result<()> { 525 self.serialize_with_mode(writer, Compress::No).map_err(|e| e.into()) 526 } 527 }