Skip to main content

snarkvm_parameters/mainnet/
powers.rs

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