use super::{
errors::KZG10Errors,
key::{CommitKey, OpeningKey},
};
use crate::util;
use anyhow::{Error, Result};
use dusk_bls12_381::{G1Affine, G1Projective, G2Affine};
use rand_core::RngCore;
use serde::de::Visitor;
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug)]
pub struct PublicParameters {
pub commit_key: CommitKey,
pub opening_key: OpeningKey,
}
impl_serde!(PublicParameters);
impl PublicParameters {
pub fn setup<R: RngCore>(
max_degree: usize,
mut rng: &mut R,
) -> Result<PublicParameters, Error> {
if max_degree < 1 {
return Err(KZG10Errors::DegreeIsZero.into());
}
let beta = util::random_scalar(&mut rng);
let powers_of_beta = util::powers_of(&beta, max_degree);
let g = util::random_g1_point(&mut rng);
let powers_of_g: Vec<G1Projective> =
util::slow_multiscalar_mul_single_base(&powers_of_beta, g);
assert_eq!(powers_of_g.len(), max_degree + 1);
let mut normalised_g = vec![G1Affine::identity(); max_degree + 1];
G1Projective::batch_normalize(&powers_of_g, &mut normalised_g);
let h: G2Affine = util::random_g2_point(&mut rng).into();
let beta_h: G2Affine = (h * beta).into();
Ok(PublicParameters {
commit_key: CommitKey {
powers_of_g: normalised_g,
},
opening_key: OpeningKey::new(g.into(), h, beta_h),
})
}
pub fn from_bytes(bytes: &[u8]) -> Result<PublicParameters, Error> {
let opening_key_bytes = &bytes[0..OpeningKey::serialised_size()];
let commit_key_bytes = &bytes[OpeningKey::serialised_size()..];
let opening_key = OpeningKey::from_bytes(opening_key_bytes)?;
let commit_key = CommitKey::from_bytes(commit_key_bytes)?;
let pp = PublicParameters {
opening_key,
commit_key,
};
Ok(pp)
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = self.opening_key.to_bytes();
bytes.extend(self.commit_key.to_bytes());
bytes
}
pub fn trim(&self, truncated_degree: usize) -> Result<(CommitKey, OpeningKey), Error> {
let truncated_prover_key = self.commit_key.truncate(truncated_degree)?;
let opening_key = self.opening_key.clone();
Ok((truncated_prover_key, opening_key))
}
pub fn max_degree(&self) -> usize {
self.commit_key.max_degree()
}
}
#[cfg(test)]
mod test {
use super::*;
use dusk_bls12_381::Scalar;
#[test]
fn test_powers_of() {
let x = Scalar::from(10u64);
let degree = 100u64;
let powers_of_x = util::powers_of(&x, degree as usize);
for (i, x_i) in powers_of_x.iter().enumerate() {
assert_eq!(*x_i, x.pow(&[i as u64, 0, 0, 0]))
}
let last_element = powers_of_x.last().unwrap();
assert_eq!(*last_element, x.pow(&[degree, 0, 0, 0]))
}
#[test]
fn test_serialise_deserialise_public_parameter() {
let pp = PublicParameters::setup(100, &mut rand::thread_rng()).unwrap();
let got_pp = PublicParameters::from_bytes(&pp.to_bytes()).unwrap();
assert_eq!(got_pp.commit_key.powers_of_g, pp.commit_key.powers_of_g);
assert_eq!(got_pp.opening_key.g, pp.opening_key.g);
assert_eq!(got_pp.opening_key.h, pp.opening_key.h);
assert_eq!(got_pp.opening_key.beta_h, pp.opening_key.beta_h);
}
}