use crate::{
impl_bytes,
kzg10,
BTreeMap,
PCCommitterKey,
PCPreparedCommitment,
PCPreparedVerifierKey,
PCVerifierKey,
Vec,
};
use snarkvm_curves::traits::{PairingCurve, PairingEngine, ProjectiveCurve};
use snarkvm_fields::{ConstraintFieldError, ToConstraintField};
use snarkvm_utilities::{
bytes::{FromBytes, ToBytes},
error,
errors::SerializationError,
serialize::*,
};
pub type UniversalParams<E> = kzg10::UniversalParams<E>;
pub type Randomness<E> = kzg10::Randomness<E>;
pub type Commitment<E> = kzg10::Commitment<E>;
pub type PreparedCommitment<E> = kzg10::PreparedCommitment<E>;
impl<E: PairingEngine> PCPreparedCommitment<Commitment<E>> for PreparedCommitment<E> {
fn prepare(comm: &Commitment<E>) -> Self {
let mut prepared_comm = Vec::<E::G1Affine>::new();
let mut cur = E::G1Projective::from(comm.0.clone());
for _ in 0..128 {
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 = ""))]
#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct CommitterKey<E: PairingEngine> {
pub powers_of_g: Vec<E::G1Affine>,
pub powers_of_gamma_g: Vec<E::G1Affine>,
pub shifted_powers_of_g: Option<Vec<E::G1Affine>>,
pub shifted_powers_of_gamma_g: Option<BTreeMap<usize, Vec<E::G1Affine>>>,
pub enforced_degree_bounds: Option<Vec<usize>>,
pub max_degree: usize,
}
impl_bytes!(CommitterKey);
impl<E: PairingEngine> CommitterKey<E> {
pub fn powers(&self) -> kzg10::Powers<E> {
kzg10::Powers {
powers_of_g: self.powers_of_g.as_slice().into(),
powers_of_gamma_g: self.powers_of_gamma_g.as_slice().into(),
}
}
pub fn shifted_powers(&self, degree_bound: impl Into<Option<usize>>) -> Option<kzg10::Powers<E>> {
match (&self.shifted_powers_of_g, &self.shifted_powers_of_gamma_g) {
(Some(shifted_powers_of_g), Some(shifted_powers_of_gamma_g)) => {
let max_bound = self.enforced_degree_bounds.as_ref().unwrap().last().unwrap();
let (bound, powers_range) = if let Some(degree_bound) = degree_bound.into() {
assert!(self.enforced_degree_bounds.as_ref().unwrap().contains(°ree_bound));
(degree_bound, (max_bound - degree_bound)..)
} else {
(*max_bound, 0..)
};
let ck = kzg10::Powers {
powers_of_g: shifted_powers_of_g[powers_range].into(),
powers_of_gamma_g: shifted_powers_of_gamma_g[&bound].clone().into(),
};
Some(ck)
}
(_, _) => None,
}
}
}
impl<E: PairingEngine> PCCommitterKey for CommitterKey<E> {
fn max_degree(&self) -> usize {
self.max_degree
}
fn supported_degree(&self) -> usize {
self.powers_of_g.len() - 1
}
}
#[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,
pub prepared_h: <E::G2Affine as PairingCurve>::Prepared,
pub prepared_beta_h: <E::G2Affine as PairingCurve>::Prepared,
pub degree_bounds_and_prepared_neg_powers_of_h: Option<Vec<(usize, <E::G2Affine as PairingCurve>::Prepared)>>,
pub supported_degree: usize,
pub max_degree: usize,
}
impl_bytes!(VerifierKey);
impl<E: PairingEngine> VerifierKey<E> {
pub fn get_shift_power(&self, degree_bound: usize) -> Option<<E::G2Affine as PairingCurve>::Prepared> {
self.degree_bounds_and_prepared_neg_powers_of_h.as_ref().and_then(|v| {
v.binary_search_by(|(d, _)| d.cmp(°ree_bound))
.ok()
.map(|i| v[i].1.clone())
})
}
}
impl<E: PairingEngine> PCVerifierKey for VerifierKey<E> {
fn max_degree(&self) -> usize {
self.max_degree
}
fn supported_degree(&self) -> usize {
self.supported_degree
}
}
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()?);
res.extend_from_slice(&self.gamma_g.to_field_elements()?);
res.extend_from_slice(&self.h.to_field_elements()?);
res.extend_from_slice(&self.beta_h.to_field_elements()?);
if let Some(degree_bounds_and_prepared_neg_powers_of_h) = &self.degree_bounds_and_prepared_neg_powers_of_h {
for (d, _prepared_neg_powers_of_h) in degree_bounds_and_prepared_neg_powers_of_h.iter() {
let d_elem: E::Fq = (*d as u64).into();
res.push(d_elem);
}
}
Ok(res)
}
}
pub type PreparedVerifierKey<E> = VerifierKey<E>;
impl<E: PairingEngine> PCPreparedVerifierKey<VerifierKey<E>> for PreparedVerifierKey<E> {
fn prepare(vk: &VerifierKey<E>) -> Self {
vk.clone()
}
}
#[derive(Derivative)]
#[derivative(
Default(bound = ""),
Hash(bound = ""),
Clone(bound = ""),
Debug(bound = ""),
PartialEq(bound = ""),
Eq(bound = "")
)]
pub struct BatchProof<E: PairingEngine>(pub(crate) Vec<kzg10::Proof<E>>);