snarkvm_parameters/mainnet/
powers.rsuse super::*;
use snarkvm_curves::traits::{PairingCurve, PairingEngine};
use snarkvm_utilities::{
CanonicalDeserialize,
CanonicalSerialize,
Compress,
FromBytes,
Read,
SerializationError,
ToBytes,
Valid,
Validate,
Write,
};
use anyhow::{Result, anyhow, bail, ensure};
use parking_lot::RwLock;
use std::{collections::BTreeMap, ops::Range, sync::Arc};
const NUM_POWERS_15: usize = 1 << 15;
const NUM_POWERS_16: usize = 1 << 16;
const NUM_POWERS_17: usize = 1 << 17;
const NUM_POWERS_18: usize = 1 << 18;
const NUM_POWERS_19: usize = 1 << 19;
const NUM_POWERS_20: usize = 1 << 20;
const NUM_POWERS_21: usize = 1 << 21;
const NUM_POWERS_22: usize = 1 << 22;
const NUM_POWERS_23: usize = 1 << 23;
const NUM_POWERS_24: usize = 1 << 24;
const NUM_POWERS_25: usize = 1 << 25;
const NUM_POWERS_26: usize = 1 << 26;
const NUM_POWERS_27: usize = 1 << 27;
const NUM_POWERS_28: usize = 1 << 28;
const MAX_NUM_POWERS: usize = NUM_POWERS_28;
lazy_static::lazy_static! {
static ref POWERS_OF_BETA_G_15: Vec<u8> = Degree15::load_bytes().expect("Failed to load powers of beta in universal SRS");
static ref SHIFTED_POWERS_OF_BETA_G_15: Vec<u8> = ShiftedDegree15::load_bytes().expect("Failed to load powers of beta in universal SRS");
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");
static ref NEG_POWERS_OF_BETA_H: Vec<u8> = NegBeta::load_bytes().expect("Failed to load negative powers of beta in universal SRS");
static ref BETA_H: Vec<u8> = BetaH::load_bytes().expect("Failed to load negative powers of beta in universal SRS");
}
#[derive(Debug)]
pub struct PowersOfG<E: PairingEngine> {
powers_of_beta_g: RwLock<PowersOfBetaG<E>>,
powers_of_beta_times_gamma_g: BTreeMap<usize, E::G1Affine>,
negative_powers_of_beta_h: BTreeMap<usize, E::G2Affine>,
prepared_negative_powers_of_beta_h: Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>>,
beta_h: E::G2Affine,
}
impl<E: PairingEngine> PowersOfG<E> {
pub fn load() -> Result<Self> {
let powers_of_beta_g = RwLock::new(PowersOfBetaG::load()?);
let powers_of_beta_times_gamma_g = BTreeMap::deserialize_uncompressed_unchecked(&**POWERS_OF_BETA_GAMMA_G)?;
let negative_powers_of_beta_h: BTreeMap<usize, E::G2Affine> =
BTreeMap::deserialize_uncompressed_unchecked(&**NEG_POWERS_OF_BETA_H)?;
let prepared_negative_powers_of_beta_h: Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>> =
Arc::new(negative_powers_of_beta_h.iter().map(|(d, affine)| (*d, affine.prepare())).collect());
let beta_h = E::G2Affine::deserialize_uncompressed_unchecked(&**BETA_H)?;
Ok(Self {
powers_of_beta_g,
powers_of_beta_times_gamma_g,
negative_powers_of_beta_h,
prepared_negative_powers_of_beta_h,
beta_h,
})
}
pub fn download_powers_for(&self, range: Range<usize>) -> Result<()> {
self.powers_of_beta_g.write().download_powers_for(&range)
}
pub fn num_powers(&self) -> usize {
self.powers_of_beta_g.read().num_powers()
}
pub fn max_num_powers(&self) -> usize {
MAX_NUM_POWERS
}
pub fn powers_of_beta_gamma_g(&self) -> &BTreeMap<usize, E::G1Affine> {
&self.powers_of_beta_times_gamma_g
}
pub fn power_of_beta_g(&self, index: usize) -> Result<E::G1Affine> {
self.powers_of_beta_g.write().power(index)
}
pub fn powers_of_beta_g(&self, range: Range<usize>) -> Result<Vec<E::G1Affine>> {
Ok(self.powers_of_beta_g.write().powers(range)?.to_vec())
}
pub fn negative_powers_of_beta_h(&self) -> &BTreeMap<usize, E::G2Affine> {
&self.negative_powers_of_beta_h
}
pub fn prepared_negative_powers_of_beta_h(&self) -> Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>> {
self.prepared_negative_powers_of_beta_h.clone()
}
pub fn beta_h(&self) -> E::G2Affine {
self.beta_h
}
}
impl<E: PairingEngine> CanonicalSerialize for PowersOfG<E> {
fn serialize_with_mode<W: Write>(&self, mut writer: W, mode: Compress) -> Result<(), SerializationError> {
self.powers_of_beta_g.read().serialize_with_mode(&mut writer, mode)?;
self.powers_of_beta_times_gamma_g.serialize_with_mode(&mut writer, mode)?;
self.negative_powers_of_beta_h.serialize_with_mode(&mut writer, mode)?;
self.beta_h.serialize_with_mode(&mut writer, mode)?;
Ok(())
}
fn serialized_size(&self, mode: Compress) -> usize {
self.powers_of_beta_g.read().serialized_size(mode)
+ self.powers_of_beta_times_gamma_g.serialized_size(mode)
+ self.negative_powers_of_beta_h.serialized_size(mode)
+ self.beta_h.serialized_size(mode)
}
}
impl<E: PairingEngine> CanonicalDeserialize for PowersOfG<E> {
fn deserialize_with_mode<R: Read>(
mut reader: R,
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError> {
let powers_of_beta_g = RwLock::new(PowersOfBetaG::deserialize_with_mode(&mut reader, compress, Validate::No)?);
let powers_of_beta_times_gamma_g = BTreeMap::deserialize_with_mode(&mut reader, compress, Validate::No)?;
let negative_powers_of_beta_h: BTreeMap<usize, E::G2Affine> =
BTreeMap::deserialize_with_mode(&mut reader, compress, Validate::No)?;
let prepared_negative_powers_of_beta_h: Arc<BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>> =
Arc::new(negative_powers_of_beta_h.iter().map(|(d, affine)| (*d, affine.prepare())).collect());
let beta_h = E::G2Affine::deserialize_with_mode(&mut reader, compress, Validate::No)?;
let powers = Self {
powers_of_beta_g,
powers_of_beta_times_gamma_g,
negative_powers_of_beta_h,
prepared_negative_powers_of_beta_h,
beta_h,
};
if let Validate::Yes = validate {
powers.check()?;
}
Ok(powers)
}
}
impl<E: PairingEngine> Valid for PowersOfG<E> {
fn check(&self) -> Result<(), SerializationError> {
self.powers_of_beta_g.read().check()?;
self.powers_of_beta_times_gamma_g.check()?;
self.negative_powers_of_beta_h.check()?;
self.prepared_negative_powers_of_beta_h.check()?;
self.beta_h.check()
}
}
impl<E: PairingEngine> FromBytes for PowersOfG<E> {
fn read_le<R: Read>(reader: R) -> std::io::Result<Self> {
Self::deserialize_with_mode(reader, Compress::No, Validate::No).map_err(|e| e.into())
}
}
impl<E: PairingEngine> ToBytes for PowersOfG<E> {
fn write_le<W: Write>(&self, writer: W) -> std::io::Result<()> {
self.serialize_with_mode(writer, Compress::No).map_err(|e| e.into())
}
}
#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
pub struct PowersOfBetaG<E: PairingEngine> {
powers_of_beta_g: Vec<E::G1Affine>,
shifted_powers_of_beta_g: Vec<E::G1Affine>,
}
impl<E: PairingEngine> PowersOfBetaG<E> {
pub fn num_powers(&self) -> usize {
self.powers_of_beta_g.len()
}
fn load() -> Result<Self> {
let powers_of_beta_g = Vec::deserialize_uncompressed_unchecked(&**POWERS_OF_BETA_G_15)?;
ensure!(powers_of_beta_g.len() == NUM_POWERS_15, "Incorrect number of powers in the recovered SRS");
let shifted_powers_of_beta_g = Vec::deserialize_uncompressed_unchecked(&**SHIFTED_POWERS_OF_BETA_G_15)?;
ensure!(shifted_powers_of_beta_g.len() == NUM_POWERS_15, "Incorrect number of powers in the recovered SRS");
Ok(PowersOfBetaG { powers_of_beta_g, shifted_powers_of_beta_g })
}
pub fn available_powers(&self) -> (Range<usize>, Range<usize>) {
if !self.shifted_powers_of_beta_g.is_empty() {
let lower_shifted_bound = MAX_NUM_POWERS - self.shifted_powers_of_beta_g.len();
((0..self.powers_of_beta_g.len()), (lower_shifted_bound..MAX_NUM_POWERS))
} else {
assert_eq!(self.powers_of_beta_g.len(), MAX_NUM_POWERS, "Incorrect number of powers in the recovered SRS");
((0..MAX_NUM_POWERS), (0..MAX_NUM_POWERS))
}
}
fn contains_in_normal_powers(&self, range: &Range<usize>) -> bool {
let (normal, _) = self.available_powers();
normal.contains(&range.start) && (normal.end >= range.end)
}
fn contains_in_shifted_powers(&self, range: &Range<usize>) -> bool {
let (_, shifted) = self.available_powers();
shifted.contains(&range.start) && (shifted.end >= range.end)
}
fn contains_powers(&self, range: &Range<usize>) -> bool {
self.contains_in_normal_powers(range) || self.contains_in_shifted_powers(range)
}
fn distance_from_normal_of(&self, range: &Range<usize>) -> usize {
(range.end as isize - self.available_powers().0.end as isize).unsigned_abs()
}
fn distance_from_shifted_of(&self, range: &Range<usize>) -> usize {
(range.start as isize - self.available_powers().1.start as isize).unsigned_abs()
}
fn shifted_powers(&self, range: Range<usize>) -> Result<&[E::G1Affine]> {
ensure!(
self.contains_in_shifted_powers(&range),
"Requested range is not contained in the available shifted powers"
);
if range.start < MAX_NUM_POWERS / 2 {
ensure!(self.shifted_powers_of_beta_g.is_empty());
Ok(&self.powers_of_beta_g[range])
} else {
let lower = self.shifted_powers_of_beta_g.len() - (MAX_NUM_POWERS - range.start);
let upper = self.shifted_powers_of_beta_g.len() - (MAX_NUM_POWERS - range.end);
Ok(&self.shifted_powers_of_beta_g[lower..upper])
}
}
fn normal_powers(&self, range: Range<usize>) -> Result<&[E::G1Affine]> {
ensure!(self.contains_in_normal_powers(&range), "Requested range is not contained in the available powers");
Ok(&self.powers_of_beta_g[range])
}
fn power(&mut self, target: usize) -> Result<E::G1Affine> {
self.powers(target..(target + 1)).map(|s| s[0])
}
fn powers(&mut self, range: Range<usize>) -> Result<&[E::G1Affine]> {
if range.is_empty() {
return Ok(&self.powers_of_beta_g[0..0]);
}
ensure!(range.start < range.end, "Lower power must be less than upper power");
ensure!(range.end <= MAX_NUM_POWERS, "Upper bound must be less than the maximum number of powers");
if !self.contains_powers(&range) {
self.download_powers_for(&range)?;
}
match self.contains_in_normal_powers(&range) {
true => self.normal_powers(range),
false => self.shifted_powers(range),
}
}
pub fn download_powers_for(&mut self, range: &Range<usize>) -> Result<()> {
if self.contains_in_normal_powers(range) || self.contains_in_shifted_powers(range) {
return Ok(());
}
let half_max = MAX_NUM_POWERS / 2;
if (range.start <= half_max) && (range.end > half_max) {
self.download_powers_up_to(range.end)?;
self.shifted_powers_of_beta_g = Vec::new();
} else if self.distance_from_shifted_of(range) < self.distance_from_normal_of(range) {
self.download_shifted_powers_from(range.start)?;
} else {
self.download_powers_up_to(range.end)?;
}
Ok(())
}
fn download_powers_up_to(&mut self, end: usize) -> Result<()> {
let final_power_of_two =
end.checked_next_power_of_two().ok_or_else(|| anyhow!("Requesting too many powers"))?;
ensure!(final_power_of_two <= MAX_NUM_POWERS, "Requesting more powers than exist in the SRS");
let current_power_of_two = self
.powers_of_beta_g
.len()
.checked_next_power_of_two()
.ok_or_else(|| anyhow!("The current degree is too large"))?;
let mut download_queue = Vec::with_capacity(14);
let mut accumulator = current_power_of_two * 2;
while accumulator <= final_power_of_two {
download_queue.push(accumulator);
accumulator =
accumulator.checked_mul(2).ok_or_else(|| anyhow!("Overflowed while requesting a larger degree"))?;
}
ensure!(final_power_of_two * 2 == accumulator, "Ensure the loop terminates at the right power of two");
let additional_size = final_power_of_two
.checked_sub(self.powers_of_beta_g.len())
.ok_or_else(|| anyhow!("final_power_of_two is smaller than existing powers"))?;
self.powers_of_beta_g.reserve(additional_size);
for num_powers in &download_queue {
#[cfg(debug_assertions)]
println!("Loading {num_powers} powers");
let additional_bytes = match *num_powers {
NUM_POWERS_16 => Degree16::load_bytes()?,
NUM_POWERS_17 => Degree17::load_bytes()?,
NUM_POWERS_18 => Degree18::load_bytes()?,
NUM_POWERS_19 => Degree19::load_bytes()?,
NUM_POWERS_20 => Degree20::load_bytes()?,
NUM_POWERS_21 => Degree21::load_bytes()?,
NUM_POWERS_22 => Degree22::load_bytes()?,
NUM_POWERS_23 => Degree23::load_bytes()?,
NUM_POWERS_24 => Degree24::load_bytes()?,
NUM_POWERS_25 => Degree25::load_bytes()?,
NUM_POWERS_26 => Degree26::load_bytes()?,
NUM_POWERS_27 => Degree27::load_bytes()?,
NUM_POWERS_28 => Degree28::load_bytes()?,
_ => bail!("Cannot download an invalid degree of '{num_powers}'"),
};
let additional_powers = Vec::deserialize_uncompressed_unchecked(&*additional_bytes)?;
self.powers_of_beta_g.extend(&additional_powers);
}
ensure!(self.powers_of_beta_g.len() == final_power_of_two, "Loaded an incorrect number of powers");
Ok(())
}
fn download_shifted_powers_from(&mut self, start: usize) -> Result<()> {
ensure!(start <= MAX_NUM_POWERS, "Requesting more powers than exist in the SRS");
let final_num_powers = MAX_NUM_POWERS
.checked_sub(start)
.ok_or_else(|| {
anyhow!("Requesting too many powers: `start ({start}) > MAX_NUM_POWERS ({MAX_NUM_POWERS})`")
})?
.checked_next_power_of_two()
.ok_or_else(|| anyhow!("Requesting too many powers"))?; let mut download_queue = Vec::with_capacity(14);
let mut existing_num_powers = self.shifted_powers_of_beta_g.len();
while existing_num_powers < final_num_powers {
existing_num_powers = existing_num_powers
.checked_mul(2)
.ok_or_else(|| anyhow!("Overflowed while requesting additional powers"))?;
download_queue.push(existing_num_powers);
}
download_queue.reverse(); let mut final_powers = Vec::with_capacity(final_num_powers);
for num_powers in &download_queue {
#[cfg(debug_assertions)]
println!("Loading {num_powers} shifted powers");
let additional_bytes = match *num_powers {
NUM_POWERS_16 => ShiftedDegree16::load_bytes()?,
NUM_POWERS_17 => ShiftedDegree17::load_bytes()?,
NUM_POWERS_18 => ShiftedDegree18::load_bytes()?,
NUM_POWERS_19 => ShiftedDegree19::load_bytes()?,
NUM_POWERS_20 => ShiftedDegree20::load_bytes()?,
NUM_POWERS_21 => ShiftedDegree21::load_bytes()?,
NUM_POWERS_22 => ShiftedDegree22::load_bytes()?,
NUM_POWERS_23 => ShiftedDegree23::load_bytes()?,
NUM_POWERS_24 => ShiftedDegree24::load_bytes()?,
NUM_POWERS_25 => ShiftedDegree25::load_bytes()?,
NUM_POWERS_26 => ShiftedDegree26::load_bytes()?,
NUM_POWERS_27 => ShiftedDegree27::load_bytes()?,
_ => bail!("Cannot download an invalid degree of '{num_powers}'"),
};
let additional_powers = Vec::deserialize_uncompressed_unchecked(&*additional_bytes)?;
final_powers.extend(additional_powers.iter());
}
final_powers.extend(self.shifted_powers_of_beta_g.iter());
self.shifted_powers_of_beta_g = final_powers;
ensure!(
self.shifted_powers_of_beta_g.len() == final_num_powers,
"Loaded an incorrect number of shifted powers"
);
Ok(())
}
}
impl<E: PairingEngine> FromBytes for PowersOfBetaG<E> {
fn read_le<R: Read>(reader: R) -> std::io::Result<Self> {
Self::deserialize_with_mode(reader, Compress::No, Validate::No).map_err(|e| e.into())
}
}
impl<E: PairingEngine> ToBytes for PowersOfBetaG<E> {
fn write_le<W: Write>(&self, writer: W) -> std::io::Result<()> {
self.serialize_with_mode(writer, Compress::No).map_err(|e| e.into())
}
}