Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Shplonk prover/verifier implementation #301

Merged
merged 9 commits into from
Feb 13, 2024
17 changes: 9 additions & 8 deletions benches/pcs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use arecibo::provider::{
hyperkzg::EvaluationEngine as MLEvaluationEngine,
ipa_pc::EvaluationEngine as IPAEvaluationEngine, non_hiding_zeromorph::ZMPCS, Bn256Engine,
Bn256EngineKZG, Bn256EngineZM,
ipa_pc::EvaluationEngine as IPAEvaluationEngine, non_hiding_zeromorph::ZMPCS,
shplonk::EvaluationEngine as Shplonk, Bn256Engine, Bn256EngineKZG, Bn256EngineZM,
};
use arecibo::spartan::polys::multilinear::MultilinearPolynomial;
use arecibo::traits::{
Expand Down Expand Up @@ -41,7 +41,7 @@ criterion_main!(pcs);

const NUM_VARS_TEST_VECTOR: [usize; 6] = [10, 12, 14, 16, 18, 20];

struct BenchAssests<E: Engine, EE: EvaluationEngineTrait<E>> {
struct BenchAssets<E: Engine, EE: EvaluationEngineTrait<E>> {
poly: MultilinearPolynomial<<E as Engine>::Scalar>,
point: Vec<<E as Engine>::Scalar>,
eval: <E as Engine>::Scalar,
Expand Down Expand Up @@ -73,7 +73,7 @@ pub fn random_poly_with_eval<E: Engine, R: RngCore + CryptoRng>(
(poly, point, eval)
}

impl<E: Engine, EE: EvaluationEngineTrait<E>> BenchAssests<E, EE> {
impl<E: Engine, EE: EvaluationEngineTrait<E>> BenchAssets<E, EE> {
pub(crate) fn from_num_vars<R: CryptoRng + RngCore>(num_vars: usize, rng: &mut R) -> Self {
let (poly, point, eval) = random_poly_with_eval::<E, R>(num_vars, rng);

Expand Down Expand Up @@ -117,7 +117,7 @@ macro_rules! benchmark_all_engines {
let mut rng = rand::rngs::StdRng::seed_from_u64(*num_vars as u64);

$(
let $assets: BenchAssests<_, $eval_engine> = BenchAssests::from_num_vars::<StdRng>(*num_vars, &mut rng);
let $assets: BenchAssets<_, $eval_engine> = BenchAssets::from_num_vars::<StdRng>(*num_vars, &mut rng);
)*

// Proving group
Expand Down Expand Up @@ -159,13 +159,14 @@ fn bench_pcs(c: &mut Criterion) {
bench_pcs_verifying_internal,
(ipa_assets, IPAEvaluationEngine<Bn256Engine>),
(hyperkzg_assets, MLEvaluationEngine<Bn256, Bn256EngineKZG>),
(zm_assets, ZMPCS<Bn256, Bn256EngineZM>)
(zm_assets, ZMPCS<Bn256, Bn256EngineZM>),
(shplonk_assets, Shplonk<Bn256, Bn256EngineKZG>)
);
}

fn bench_pcs_proving_internal<E: Engine, EE: EvaluationEngineTrait<E>>(
b: &mut Bencher<'_>,
bench_assets: &BenchAssests<E, EE>,
bench_assets: &BenchAssets<E, EE>,
) {
// Bench generate proof.
b.iter(|| {
Expand All @@ -184,7 +185,7 @@ fn bench_pcs_proving_internal<E: Engine, EE: EvaluationEngineTrait<E>>(

fn bench_pcs_verifying_internal<E: Engine, EE: EvaluationEngineTrait<E>>(
b: &mut Bencher<'_>,
bench_assets: &BenchAssests<E, EE>,
bench_assets: &BenchAssets<E, EE>,
) {
// Bench verify proof.
b.iter(|| {
Expand Down
15 changes: 9 additions & 6 deletions src/provider/hyperkzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,20 @@ where
E::Fr: TranscriptReprTrait<E::G1>,
E::G1Affine: TranscriptReprTrait<E::G1>, // TODO: this bound on DlogGroup is really unusable!
{
fn compute_challenge(
/// TODO: write doc
pub fn compute_challenge(
com: &[E::G1Affine],
transcript: &mut impl TranscriptEngineTrait<NE>,
) -> E::Fr {
transcript.absorb(b"c", &com.to_vec().as_slice());
transcript.absorb(b"c", &com);
transcript.squeeze(b"c").unwrap()
}

/// TODO: write doc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the existing comment already :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, so I do not focus on this only because we are going to merge Shplonk with HyperKZG eventually. The followup PR or "final" commit that you mentioned will for sure include these TODO resolvings

// Compute challenge q = Hash(vk, C0, ..., C_{k-1}, u0, ...., u_{t-1},
// (f_i(u_j))_{i=0..k-1,j=0..t-1})
// It is assumed that both 'C' and 'u' are already absorbed by the transcript
fn get_batch_challenge(
pub fn get_batch_challenge(
v: &[Vec<E::Fr>],
transcript: &mut impl TranscriptEngineTrait<NE>,
) -> E::Fr {
Expand All @@ -88,14 +90,15 @@ where
transcript.squeeze(b"r").unwrap()
}

fn batch_challenge_powers(q: E::Fr, k: usize) -> Vec<E::Fr> {
// Compute powers of q : (1, q, q^2, ..., q^(k-1))
/// Compute powers of q : (1, q, q^2, ..., q^(k-1))
pub fn batch_challenge_powers(q: E::Fr, k: usize) -> Vec<E::Fr> {
std::iter::successors(Some(E::Fr::ONE), |&x| Some(x * q))
.take(k)
.collect()
}

fn verifier_second_challenge(
/// TODO: write doc
pub fn verifier_second_challenge(
W: &[E::G1Affine],
transcript: &mut impl TranscriptEngineTrait<NE>,
) -> E::Fr {
Expand Down
1 change: 1 addition & 0 deletions src/provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
pub mod hyperkzg;
pub mod ipa_pc;
pub mod non_hiding_zeromorph;
pub mod shplonk;

// crate-public modules, made crate-public mostly for tests
pub(crate) mod bn256_grumpkin;
Expand Down
2 changes: 1 addition & 1 deletion src/provider/non_hiding_kzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ pub struct UVKZGProof<E: Engine> {
}

/// Polynomial and its associated types
pub type UVKZGPoly<F> = crate::spartan::polys::univariate::UniPoly<F>;
type UVKZGPoly<F> = crate::spartan::polys::univariate::UniPoly<F>;

#[derive(Debug, Eq, PartialEq, Default)]
/// KZG Polynomial Commitment Scheme on univariate polynomial.
Expand Down
53 changes: 22 additions & 31 deletions src/provider/non_hiding_zeromorph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
errors::{NovaError, PCSError},
provider::{
non_hiding_kzg::{
KZGProverKey, KZGVerifierKey, UVKZGCommitment, UVKZGEvaluation, UVKZGPoly, UVKZGProof,
KZGProverKey, KZGVerifierKey, UVKZGCommitment, UVKZGEvaluation, UVKZGProof,
UniversalKZGParam, UVKZGPCS,
},
traits::DlogGroup,
Expand All @@ -33,6 +33,7 @@ use std::sync::Arc;
use std::{borrow::Borrow, iter, marker::PhantomData};

use crate::provider::kzg_commitment::KZGCommitmentEngine;
use crate::spartan::polys::univariate::UniPoly;

/// `ZMProverKey` is used to generate a proof
#[derive(Clone, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -156,7 +157,7 @@ where
if pp.commit_pp.powers_of_g().len() < poly.Z.len() {
return Err(PCSError::LengthError.into());
}
UVKZGPCS::commit(&pp.commit_pp, UVKZGPoly::ref_cast(&poly.Z)).map(|c| c.into())
UVKZGPCS::commit(&pp.commit_pp, UniPoly::ref_cast(&poly.Z)).map(|c| c.into())
}

/// On input a polynomial `poly` and a point `point`, outputs a proof for the
Expand Down Expand Up @@ -184,10 +185,7 @@ where
debug_assert_eq!(remainder, eval.0);

// Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1})
let quotients_polys = quotients
.into_iter()
.map(UVKZGPoly::new)
.collect::<Vec<_>>();
let quotients_polys = quotients.into_iter().map(UniPoly::new).collect::<Vec<_>>();

// Compute and absorb commitments C_{q_k} = [q_k], k = 0,...,d-1
let q_comms = quotients_polys
Expand Down Expand Up @@ -215,7 +213,7 @@ where
let (eval_scalar, (degree_check_q_scalars, zmpoly_q_scalars)) =
eval_and_quotient_scalars(y, x, z, point);
// f = z * poly.Z + q_hat + (-z * Φ_n(x) * e) + ∑_k (q_scalars_k * q_k)
let mut f = UVKZGPoly::new(poly.Z.clone());
let mut f = UniPoly::new(poly.Z.clone());
f *= &z;
f += &q_hat;
f[0] += eval_scalar * eval.0;
Expand Down Expand Up @@ -360,8 +358,8 @@ fn quotients<F: PrimeField>(poly: &MultilinearPolynomial<F>, point: &[F]) -> (Ve
// Compute the batched, lifted-degree quotient `\hat{q}`
fn batched_lifted_degree_quotient<F: PrimeField>(
y: F,
quotients_polys: &[UVKZGPoly<F>],
) -> (UVKZGPoly<F>, usize) {
quotients_polys: &[UniPoly<F>],
) -> (UniPoly<F>, usize) {
let num_vars = quotients_polys.len();

let powers_of_y = (0..num_vars)
Expand Down Expand Up @@ -390,7 +388,7 @@ fn batched_lifted_degree_quotient<F: PrimeField>(
},
);

(UVKZGPoly::new(q_hat), 1 << (num_vars - 1))
(UniPoly::new(q_hat), 1 << (num_vars - 1))
}

/// Computes some key terms necessary for computing the partially evaluated univariate ZM polynomial
Expand Down Expand Up @@ -523,12 +521,11 @@ mod test {

use super::quotients;

use crate::spartan::polys::univariate::UniPoly;
use crate::{
errors::PCSError,
provider::{
non_hiding_kzg::{
trim, KZGProverKey, UVKZGCommitment, UVKZGPoly, UniversalKZGParam, UVKZGPCS,
},
non_hiding_kzg::{trim, KZGProverKey, UVKZGCommitment, UniversalKZGParam, UVKZGPCS},
non_hiding_zeromorph::{batched_lifted_degree_quotient, eval_and_quotient_scalars, ZMPCS},
traits::DlogGroup,
util::test_utils::prove_verify_from_num_vars,
Expand Down Expand Up @@ -598,9 +595,9 @@ mod test {
let n = 1 << num_vars; // Assuming N = 2^num_vars

// Define mock q_k with deg(q_k) = 2^k - 1
let q_0 = UVKZGPoly::new(vec![Scalar::one()]);
let q_1 = UVKZGPoly::new(vec![Scalar::from(2), Scalar::from(3)]);
let q_2 = UVKZGPoly::new(vec![
let q_0 = UniPoly::new(vec![Scalar::one()]);
let q_1 = UniPoly::new(vec![Scalar::from(2), Scalar::from(3)]);
let q_2 = UniPoly::new(vec![
Scalar::from(4),
Scalar::from(5),
Scalar::from(6),
Expand Down Expand Up @@ -644,10 +641,7 @@ mod test {
});

// Compare the computed and expected batched quotients
assert_eq!(
batched_quotient.0,
UVKZGPoly::new(batched_quotient_expected)
);
assert_eq!(batched_quotient.0, UniPoly::new(batched_quotient_expected));
}

#[test]
Expand All @@ -657,9 +651,9 @@ mod test {
let num_vars = 3;

// Define some mock q_k with deg(q_k) = 2^k - 1
let _q_0 = UVKZGPoly::new(vec![Scalar::one()]);
let _q_1 = UVKZGPoly::new(vec![Scalar::from(2), Scalar::from(3)]);
let _q_2 = UVKZGPoly::new(vec![
let _q_0 = UniPoly::new(vec![Scalar::one()]);
let _q_1 = UniPoly::new(vec![Scalar::from(2), Scalar::from(3)]);
let _q_2 = UniPoly::new(vec![
Scalar::from(4),
Scalar::from(5),
Scalar::from(6),
Expand Down Expand Up @@ -713,9 +707,9 @@ mod test {
let mut rng = ChaCha20Rng::from_seed([0u8; 32]);

// Define some mock q_k with deg(q_k) = 2^k - 1
let _q_0 = UVKZGPoly::new(vec![Scalar::one()]);
let _q_1 = UVKZGPoly::new(vec![Scalar::from(2), Scalar::from(3)]);
let _q_2 = UVKZGPoly::new(vec![
let _q_0 = UniPoly::new(vec![Scalar::one()]);
let _q_1 = UniPoly::new(vec![Scalar::from(2), Scalar::from(3)]);
let _q_2 = UniPoly::new(vec![
Scalar::from(4),
Scalar::from(5),
Scalar::from(6),
Expand Down Expand Up @@ -755,7 +749,7 @@ mod test {

fn commit_filtered<E>(
prover_param: impl Borrow<KZGProverKey<E>>,
poly: &UVKZGPoly<E::Fr>,
poly: &UniPoly<E::Fr>,
) -> Result<UVKZGCommitment<E>, NovaError>
where
E: MultiMillerLoop,
Expand Down Expand Up @@ -802,10 +796,7 @@ mod test {
}

let (quotients, _remainder) = quotients(&multilinear_poly, random_points.as_slice());
let quotients_polys = quotients
.into_iter()
.map(UVKZGPoly::new)
.collect::<Vec<_>>();
let quotients_polys = quotients.into_iter().map(UniPoly::new).collect::<Vec<_>>();

let (q_hat, offset) = batched_lifted_degree_quotient(E::Fr::random(&mut rng), &quotients_polys);

Expand Down
Loading