use crate::{impl_bytes, BTreeMap, *};
use core::ops::{Add, AddAssign};
use snarkvm_curves::traits::{AffineCurve, PairingCurve, PairingEngine, ProjectiveCurve};
use snarkvm_fields::{ConstraintFieldError, PrimeField, ToConstraintField, Zero};
use snarkvm_utilities::{
bytes::ToBytes,
error,
errors::SerializationError,
serialize::{CanonicalDeserialize, CanonicalSerialize},
};
#[derive(Derivative)]
#[derivative(Default(bound = ""), Clone(bound = ""), Debug(bound = ""))]
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct UniversalParams<E: PairingEngine> {
pub powers_of_g: Vec<E::G1Affine>,
pub powers_of_gamma_g: BTreeMap<usize, E::G1Affine>,
pub h: E::G2Affine,
pub beta_h: E::G2Affine,
pub prepared_neg_powers_of_h: BTreeMap<usize, <E::G2Affine as PairingCurve>::Prepared>,
#[derivative(Debug = "ignore")]
pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
#[derivative(Debug = "ignore")]
pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
}
impl_bytes!(UniversalParams);
impl<E: PairingEngine> PCUniversalParams for UniversalParams<E> {
fn max_degree(&self) -> usize {
self.powers_of_g.len() - 1
}
}
#[derive(Derivative)]
#[derivative(Default(bound = ""), Hash(bound = ""), Clone(bound = ""), Debug(bound = ""))]
pub struct Powers<'a, E: PairingEngine> {
pub powers_of_g: Cow<'a, [E::G1Affine]>,
pub powers_of_gamma_g: Cow<'a, [E::G1Affine]>,
}
impl<E: PairingEngine> Powers<'_, E> {
pub fn size(&self) -> usize {
self.powers_of_g.len()
}
}
#[derive(Derivative)]
#[derivative(Default(bound = ""), Clone(bound = ""), Debug(bound = ""))]
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct VerifierKey<E: PairingEngine> {
pub g: E::G1Affine,
pub gamma_g: E::G1Affine,
pub h: E::G2Affine,
pub beta_h: E::G2Affine,
#[derivative(Debug = "ignore")]
pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
#[derivative(Debug = "ignore")]
pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
}
impl_bytes!(VerifierKey);
impl<E: PairingEngine> ToConstraintField<E::Fq> for VerifierKey<E>
where
E::G1Affine: ToConstraintField<E::Fq>,
E::G2Affine: ToConstraintField<E::Fq>,
{
fn to_field_elements(&self) -> Result<Vec<E::Fq>, ConstraintFieldError> {
let mut res = Vec::new();
res.extend_from_slice(&self.g.to_field_elements().unwrap());
res.extend_from_slice(&self.gamma_g.to_field_elements().unwrap());
res.extend_from_slice(&self.h.to_field_elements().unwrap());
res.extend_from_slice(&self.beta_h.to_field_elements().unwrap());
Ok(res)
}
}
#[derive(Derivative)]
#[derivative(Default(bound = ""), Clone(bound = ""), Debug(bound = ""))]
pub struct PreparedVerifierKey<E: PairingEngine> {
pub prepared_g: Vec<E::G1Affine>,
pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
}
impl<E: PairingEngine> PreparedVerifierKey<E> {
pub fn prepare(vk: &VerifierKey<E>) -> Self {
let supported_bits = E::Fr::size_in_bits();
let mut prepared_g = Vec::<E::G1Affine>::new();
let mut g = E::G1Projective::from(vk.g.clone());
for _ in 0..supported_bits {
prepared_g.push(g.clone().into());
g.double_in_place();
}
Self {
prepared_g,
prepared_h: vk.prepared_h.clone(),
prepared_beta_h: vk.prepared_beta_h.clone(),
}
}
}
#[derive(Derivative)]
#[derivative(
Default(bound = ""),
Hash(bound = ""),
Clone(bound = ""),
Copy(bound = ""),
Debug(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct Commitment<E: PairingEngine>(
pub E::G1Affine,
);
impl_bytes!(Commitment);
impl<E: PairingEngine> PCCommitment for Commitment<E> {
#[inline]
fn empty() -> Self {
Commitment(E::G1Affine::zero())
}
fn has_degree_bound(&self) -> bool {
false
}
fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool {
self.0.is_in_correct_subgroup_assuming_on_curve()
}
}
impl<'a, E: PairingEngine> AddAssign<(E::Fr, &'a Commitment<E>)> for Commitment<E> {
#[inline]
fn add_assign(&mut self, (f, other): (E::Fr, &'a Commitment<E>)) {
let mut other = other.0.mul(f.into_repr());
other.add_assign_mixed(&self.0);
self.0 = other.into();
}
}
impl<E: PairingEngine> ToConstraintField<E::Fq> for Commitment<E>
where
E::G1Affine: ToConstraintField<E::Fq>,
{
fn to_field_elements(&self) -> Result<Vec<E::Fq>, ConstraintFieldError> {
self.0.to_field_elements()
}
}
#[derive(Derivative)]
#[derivative(
Default(bound = ""),
Hash(bound = ""),
Clone(bound = ""),
Debug(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
pub struct PreparedCommitment<E: PairingEngine>(
pub Vec<E::G1Affine>,
);
impl<E: PairingEngine> PreparedCommitment<E> {
pub fn prepare(comm: &Commitment<E>) -> Self {
let mut prepared_comm = Vec::<E::G1Affine>::new();
let mut cur = E::G1Projective::from(comm.0.clone());
let supported_bits = E::Fr::size_in_bits();
for _ in 0..supported_bits {
prepared_comm.push(cur.clone().into());
cur.double_in_place();
}
Self { 0: prepared_comm }
}
}
#[derive(Derivative)]
#[derivative(
Default(bound = ""),
Hash(bound = ""),
Clone(bound = ""),
Debug(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct Randomness<E: PairingEngine> {
pub blinding_polynomial: Polynomial<E::Fr>,
}
impl_bytes!(Randomness);
impl<E: PairingEngine> Randomness<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> PCRandomness for Randomness<E> {
fn empty() -> Self {
Self {
blinding_polynomial: Polynomial::zero(),
}
}
fn rand<R: RngCore>(hiding_bound: usize, _: bool, rng: &mut R) -> Self {
let mut randomness = Randomness::empty();
let hiding_poly_degree = Self::calculate_hiding_polynomial_degree(hiding_bound);
randomness.blinding_polynomial = Polynomial::rand(hiding_poly_degree, rng);
randomness
}
}
impl<'a, E: PairingEngine> Add<&'a Randomness<E>> for Randomness<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 Randomness<E>)> for Randomness<E> {
type Output = Self;
#[inline]
fn add(mut self, other: (E::Fr, &'a Randomness<E>)) -> Self {
self += other;
self
}
}
impl<'a, E: PairingEngine> AddAssign<&'a Randomness<E>> for Randomness<E> {
#[inline]
fn add_assign(&mut self, other: &'a Self) {
self.blinding_polynomial += &other.blinding_polynomial;
}
}
impl<'a, E: PairingEngine> AddAssign<(E::Fr, &'a Randomness<E>)> for Randomness<E> {
#[inline]
fn add_assign(&mut self, (f, other): (E::Fr, &'a Randomness<E>)) {
self.blinding_polynomial += (f, &other.blinding_polynomial);
}
}
#[derive(Derivative)]
#[derivative(
Default(bound = ""),
Hash(bound = ""),
Clone(bound = ""),
Copy(bound = ""),
Debug(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct Proof<E: PairingEngine> {
pub w: E::G1Affine,
pub random_v: Option<E::Fr>,
}
impl_bytes!(Proof);
impl<E: PairingEngine> PCProof for Proof<E> {}