use crate::{
AlgebraicSponge,
fft::{DensePolynomial, EvaluationDomain},
};
use snarkvm_curves::{AffineCurve, PairingCurve, PairingEngine, ProjectiveCurve};
use snarkvm_fields::{ConstraintFieldError, ToConstraintField, Zero};
use snarkvm_parameters::mainnet::PowersOfG;
use snarkvm_utilities::{
FromBytes,
ToBytes,
borrow::Cow,
error,
io::{Read, Write},
serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate},
};
use crate::srs::{UniversalProver, UniversalVerifier};
use anyhow::Result;
use core::ops::{Add, AddAssign};
use rand_core::RngCore;
use std::{collections::BTreeMap, io, ops::Range, sync::Arc};
#[derive(Clone, Debug)]
pub struct UniversalParams<E: PairingEngine> {
powers: Arc<PowersOfG<E>>,
pub h: E::G2Affine,
pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
}
impl<E: PairingEngine> UniversalParams<E> {
pub fn load() -> Result<Self> {
let powers = Arc::new(PowersOfG::<E>::load()?);
let h = E::G2Affine::prime_subgroup_generator();
let prepared_h = h.prepare();
let prepared_beta_h = powers.beta_h().prepare();
Ok(Self { powers, h, prepared_h, prepared_beta_h })
}
pub fn download_powers_for(&self, range: Range<usize>) -> Result<()> {
self.powers.download_powers_for(range)
}
pub fn lagrange_basis(&self, domain: EvaluationDomain<E::Fr>) -> Result<Vec<E::G1Affine>> {
let basis = domain
.ifft(&self.powers_of_beta_g(0, domain.size())?.iter().map(|e| (*e).to_projective()).collect::<Vec<_>>());
Ok(E::G1Projective::batch_normalization_into_affine(basis))
}
pub fn power_of_beta_g(&self, index: usize) -> Result<E::G1Affine> {
self.powers.power_of_beta_g(index)
}
pub fn powers_of_beta_g(&self, lower: usize, upper: usize) -> Result<Vec<E::G1Affine>> {
self.powers.powers_of_beta_g(lower..upper)
}
pub fn powers_of_beta_times_gamma_g(&self) -> &BTreeMap<usize, E::G1Affine> {
self.powers.powers_of_beta_gamma_g()
}
pub fn beta_h(&self) -> E::G2Affine {
self.powers.beta_h()
}
pub fn max_degree(&self) -> usize {
self.powers.max_num_powers() - 1
}
pub fn to_universal_prover(&self) -> Result<UniversalProver<E>> {
Ok(UniversalProver::<E> { max_degree: self.max_degree(), _unused: None })
}
pub fn to_universal_verifier(&self) -> Result<UniversalVerifier<E>> {
let g = self.power_of_beta_g(0)?;
let h = self.h;
let beta_h = self.beta_h();
let gamma_g = self.powers_of_beta_times_gamma_g()[&0];
let prepared_h = self.prepared_h.clone();
let prepared_beta_h = self.prepared_beta_h.clone();
Ok(UniversalVerifier {
vk: VerifierKey::<E> { g, gamma_g, h, beta_h, prepared_h, prepared_beta_h },
prepared_negative_powers_of_beta_h: self.powers.prepared_negative_powers_of_beta_h(),
})
}
}
impl<E: PairingEngine> FromBytes for UniversalParams<E> {
fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
let powers = Arc::new(PowersOfG::read_le(&mut reader)?);
let h: E::G2Affine = FromBytes::read_le(&mut reader)?;
let prepared_h: <E::G2Affine as PairingCurve>::Prepared = FromBytes::read_le(&mut reader)?;
let prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared = FromBytes::read_le(&mut reader)?;
Ok(Self { powers, h, prepared_h, prepared_beta_h })
}
}
impl<E: PairingEngine> ToBytes for UniversalParams<E> {
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
self.powers.write_le(&mut writer)?;
self.h.write_le(&mut writer)?;
self.prepared_h.write_le(&mut writer)?;
self.prepared_beta_h.write_le(&mut writer)?;
Ok(())
}
}
#[derive(Clone, Debug, Default, Hash)]
pub struct Powers<'a, E: PairingEngine> {
pub powers_of_beta_g: Cow<'a, [E::G1Affine]>,
pub powers_of_beta_times_gamma_g: Cow<'a, [E::G1Affine]>,
}
impl<E: PairingEngine> Powers<'_, E> {
pub fn size(&self) -> usize {
self.powers_of_beta_g.len()
}
}
#[derive(Clone, Debug, Hash)]
pub struct LagrangeBasis<'a, E: PairingEngine> {
pub lagrange_basis_at_beta_g: Cow<'a, [E::G1Affine]>,
pub powers_of_beta_times_gamma_g: Cow<'a, [E::G1Affine]>,
pub domain: EvaluationDomain<E::Fr>,
}
impl<E: PairingEngine> LagrangeBasis<'_, E> {
pub fn size(&self) -> usize {
self.lagrange_basis_at_beta_g.len()
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct VerifierKey<E: PairingEngine> {
pub g: E::G1Affine,
pub gamma_g: E::G1Affine,
pub h: E::G2Affine,
pub beta_h: E::G2Affine,
pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
}
impl<E: PairingEngine> CanonicalSerialize for VerifierKey<E> {
fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
self.g.serialize_with_mode(&mut writer, compress)?;
self.gamma_g.serialize_with_mode(&mut writer, compress)?;
self.h.serialize_with_mode(&mut writer, compress)?;
self.beta_h.serialize_with_mode(&mut writer, compress)?;
Ok(())
}
fn serialized_size(&self, compress: Compress) -> usize {
self.g.serialized_size(compress)
+ self.gamma_g.serialized_size(compress)
+ self.h.serialized_size(compress)
+ self.beta_h.serialized_size(compress)
}
}
impl<E: PairingEngine> CanonicalDeserialize for VerifierKey<E> {
fn deserialize_with_mode<R: Read>(
mut reader: R,
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError> {
let g = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
let gamma_g = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
let h: E::G2Affine = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
let beta_h: E::G2Affine = CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
let prepared_h = h.prepare();
let prepared_beta_h = beta_h.prepare();
Ok(VerifierKey { g, gamma_g, h, beta_h, prepared_h, prepared_beta_h })
}
}
impl<E: PairingEngine> Valid for VerifierKey<E> {
fn check(&self) -> Result<(), SerializationError> {
Valid::check(&self.g)?;
Valid::check(&self.gamma_g)?;
Valid::check(&self.h)?;
Valid::check(&self.beta_h)?;
Ok(())
}
fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
where
Self: 'a,
{
let batch: Vec<_> = batch.collect();
Valid::batch_check(batch.iter().map(|v| &v.g))?;
Valid::batch_check(batch.iter().map(|v| &v.gamma_g))?;
Valid::batch_check(batch.iter().map(|v| &v.h))?;
Valid::batch_check(batch.iter().map(|v| &v.beta_h))?;
Ok(())
}
}
impl<E: PairingEngine> FromBytes for VerifierKey<E> {
fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
CanonicalDeserialize::deserialize_compressed(&mut reader)
.map_err(|_| error("could not deserialize VerifierKey"))
}
}
impl<E: PairingEngine> ToBytes for VerifierKey<E> {
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
CanonicalSerialize::serialize_compressed(self, &mut writer)
.map_err(|_| error("could not serialize VerifierKey"))
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
pub struct KZGCommitment<E: PairingEngine>(
pub E::G1Affine,
);
impl<E: PairingEngine> FromBytes for KZGCommitment<E> {
fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
CanonicalDeserialize::deserialize_compressed(&mut reader)
.map_err(|_| error("could not deserialize KZGCommitment"))
}
}
impl<E: PairingEngine> ToBytes for KZGCommitment<E> {
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
CanonicalSerialize::serialize_compressed(self, &mut writer)
.map_err(|_| error("could not serialize KZGCommitment"))
}
}
impl<E: PairingEngine> KZGCommitment<E> {
#[inline]
pub fn empty() -> Self {
KZGCommitment(E::G1Affine::zero())
}
pub fn has_degree_bound(&self) -> bool {
false
}
pub fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool {
self.0.is_in_correct_subgroup_assuming_on_curve()
}
}
impl<E: PairingEngine> ToConstraintField<E::Fq> for KZGCommitment<E> {
fn to_field_elements(&self) -> Result<Vec<E::Fq>, ConstraintFieldError> {
self.0.to_field_elements()
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
pub struct KZGRandomness<E: PairingEngine> {
pub blinding_polynomial: DensePolynomial<E::Fr>,
}
impl<E: PairingEngine> FromBytes for KZGRandomness<E> {
fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
CanonicalDeserialize::deserialize_compressed(&mut reader)
.map_err(|_| error("could not deserialize KZGRandomness"))
}
}
impl<E: PairingEngine> ToBytes for KZGRandomness<E> {
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
CanonicalSerialize::serialize_compressed(self, &mut writer)
.map_err(|_| error("could not serialize KZGRandomness"))
}
}
impl<E: PairingEngine> KZGRandomness<E> {
#[inline]
pub fn is_hiding(&self) -> bool {
!self.blinding_polynomial.is_zero()
}
#[inline]
pub fn calculate_hiding_polynomial_degree(hiding_bound: usize) -> usize {
hiding_bound + 1
}
}
impl<E: PairingEngine> KZGRandomness<E> {
pub fn empty() -> Self {
Self { blinding_polynomial: DensePolynomial::zero() }
}
pub fn rand<R: RngCore>(hiding_bound: usize, _: bool, rng: &mut R) -> Self {
let mut randomness = KZGRandomness::empty();
let hiding_poly_degree = Self::calculate_hiding_polynomial_degree(hiding_bound);
randomness.blinding_polynomial = DensePolynomial::rand(hiding_poly_degree, rng);
randomness
}
}
impl<'a, E: PairingEngine> Add<&'a KZGRandomness<E>> for KZGRandomness<E> {
type Output = Self;
#[inline]
fn add(mut self, other: &'a Self) -> Self {
self.blinding_polynomial += &other.blinding_polynomial;
self
}
}
impl<'a, E: PairingEngine> Add<(E::Fr, &'a KZGRandomness<E>)> for KZGRandomness<E> {
type Output = Self;
#[inline]
fn add(mut self, other: (E::Fr, &'a KZGRandomness<E>)) -> Self {
self += other;
self
}
}
impl<'a, E: PairingEngine> AddAssign<&'a KZGRandomness<E>> for KZGRandomness<E> {
#[inline]
fn add_assign(&mut self, other: &'a Self) {
self.blinding_polynomial += &other.blinding_polynomial;
}
}
impl<'a, E: PairingEngine> AddAssign<(E::Fr, &'a KZGRandomness<E>)> for KZGRandomness<E> {
#[inline]
fn add_assign(&mut self, (f, other): (E::Fr, &'a KZGRandomness<E>)) {
self.blinding_polynomial += (f, &other.blinding_polynomial);
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
pub struct KZGProof<E: PairingEngine> {
pub w: E::G1Affine,
pub random_v: Option<E::Fr>,
}
impl<E: PairingEngine> KZGProof<E> {
pub fn absorb_into_sponge(&self, sponge: &mut impl AlgebraicSponge<E::Fq, 2>) {
sponge.absorb_native_field_elements(&self.w.to_field_elements().unwrap());
if let Some(random_v) = self.random_v {
sponge.absorb_nonnative_field_elements([random_v]);
}
}
}
impl<E: PairingEngine> FromBytes for KZGProof<E> {
fn read_le<R: Read>(mut reader: R) -> io::Result<Self> {
CanonicalDeserialize::deserialize_compressed(&mut reader).map_err(|_| error("could not deserialize KZG proof"))
}
}
impl<E: PairingEngine> ToBytes for KZGProof<E> {
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
CanonicalSerialize::serialize_compressed(self, &mut writer).map_err(|_| error("could not serialize KZG proof"))
}
}
impl<E: PairingEngine> KZGProof<E> {
pub fn is_hiding(&self) -> bool {
self.random_v.is_some()
}
}