use crate::link::error::LinkError;
use crate::link::utils::*;
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup};
use ark_ff::{UniformRand, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{
cfg_iter,
marker::PhantomData,
ops::{Mul, Neg},
rand::Rng,
vec::Vec,
};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
#[derive(Clone, Default, PartialEq, Debug, CanonicalSerialize, CanonicalDeserialize)]
pub struct PP<
G1: Clone + Default + CanonicalSerialize + CanonicalDeserialize,
G2: Clone + Default + CanonicalSerialize + CanonicalDeserialize,
> {
pub l: usize, pub t: usize, pub g1: G1,
pub g2: G2,
}
impl<
G1: Clone + Default + CanonicalSerialize + CanonicalDeserialize,
G2: Clone + Default + CanonicalSerialize + CanonicalDeserialize,
> PP<G1, G2>
{
pub fn new(l: usize, t: usize, g1: G1, g2: G2) -> PP<G1, G2> {
PP { l, t, g1, g2 }
}
}
#[derive(Clone, Default, PartialEq, Debug, CanonicalSerialize, CanonicalDeserialize)]
pub struct EK<G1: Clone + Default + CanonicalSerialize + CanonicalDeserialize> {
pub p: Vec<G1>,
}
#[derive(Clone, Default, PartialEq, Debug, CanonicalSerialize, CanonicalDeserialize)]
pub struct VK<G2: Clone + Default + CanonicalSerialize + CanonicalDeserialize> {
pub c: Vec<G2>,
pub a: G2,
}
pub trait SubspaceSnark {
type KMtx;
type InVec;
type OutVec;
type PP;
type EK;
type VK;
type Proof;
fn keygen<R: Rng>(
rng: &mut R,
pp: &Self::PP,
m: &Self::KMtx,
) -> Result<(Self::EK, Self::VK), LinkError>;
fn prove(pp: &Self::PP, ek: &Self::EK, w: &[Self::InVec]) -> Result<Self::Proof, LinkError>;
fn verify(
pp: &Self::PP,
vk: &Self::VK,
y: &[Self::OutVec],
pi: &Self::Proof,
) -> Result<(), LinkError>;
}
pub struct PESubspaceSnark<PE: Pairing> {
pairing_engine_type: PhantomData<PE>,
}
impl<PE: Pairing> SubspaceSnark for PESubspaceSnark<PE> {
type KMtx = SparseMatrix<PE::G1Affine>;
type InVec = PE::ScalarField;
type OutVec = PE::G1Affine;
type PP = PP<PE::G1Affine, PE::G2Affine>;
type EK = EK<PE::G1Affine>;
type VK = VK<PE::G2Affine>;
type Proof = PE::G1Affine;
fn keygen<R: Rng>(
rng: &mut R,
pp: &Self::PP,
m: &Self::KMtx,
) -> Result<(Self::EK, Self::VK), LinkError> {
let mut k: Vec<PE::ScalarField> = Vec::with_capacity(pp.l);
for _ in 0..pp.l {
k.push(PE::ScalarField::rand(rng));
}
let a = PE::ScalarField::rand(rng);
let p = SparseLinAlgebra::<PE>::sparse_vector_matrix_mult(&k, m)?;
let c = scale_vector::<PE>(&a, &k);
let ek = EK::<PE::G1Affine> { p };
let vk = VK::<PE::G2Affine> {
c: multiples_of_g::<PE::G2Affine>(&pp.g2, &c),
a: pp.g2.mul(a).into_affine(),
};
Ok((ek, vk))
}
fn prove(pp: &Self::PP, ek: &Self::EK, w: &[Self::InVec]) -> Result<Self::Proof, LinkError> {
if pp.t < w.len() {
return Err(LinkError::VectorLongerThanExpected(w.len(), pp.t));
}
Ok(inner_product::<PE>(w, &ek.p))
}
fn verify(
pp: &Self::PP,
vk: &Self::VK,
x: &[Self::OutVec],
pi: &Self::Proof,
) -> Result<(), LinkError> {
if pp.l != x.len() {
return Err(LinkError::VectorWithUnexpectedLength(x.len(), pp.l));
}
if vk.c.len() < x.len() {
return Err(LinkError::VectorLongerThanExpected(x.len(), vk.c.len()));
}
let mut a = x.to_vec();
let mut b = cfg_iter!(vk.c[0..x.len()])
.map(|b| PE::G2Prepared::from(*b))
.collect::<Vec<_>>();
a.push(*pi);
b.push(PE::G2Prepared::from(vk.a.into_group().neg()));
if !PE::multi_pairing(a, b).is_zero() {
return Err(LinkError::InvalidProof);
}
Ok(())
}
}