snarkvm_parameters/mainnet/
powers.rs

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