Skip to content

Commit

Permalink
clean up and start abstracting hyrax
Browse files Browse the repository at this point in the history
  • Loading branch information
PatStiles committed Jan 16, 2024
1 parent f4e3bb5 commit 9aaf168
Show file tree
Hide file tree
Showing 8 changed files with 522 additions and 299 deletions.
79 changes: 79 additions & 0 deletions src/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,96 @@ macro_rules! single_pass_lasso {
pub enum BenchType {
JoltDemo,
Halo2Comparison,
Zeromorph,
}

#[allow(unreachable_patterns)] // good errors on new BenchTypes
pub fn benchmarks(bench_type: BenchType) -> Vec<(tracing::Span, fn())> {
match bench_type {
BenchType::JoltDemo => jolt_demo_benchmarks(),
BenchType::Halo2Comparison => halo2_comparison_benchmarks(),
BenchType::Zeromorph => zeromorph(),
_ => panic!("BenchType does not have a mapping"),
}
}

fn zeromorph() -> Vec<(tracing::Span, fn())> {
vec![
single_pass_lasso!(
"And(2^10)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 10
),
single_pass_lasso!(
"And(2^12)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 12
),
single_pass_lasso!(
"And(2^14)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 14
),
single_pass_lasso!(
"And(2^16)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 16
),
single_pass_lasso!(
"And(2^18)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 18
),
single_pass_lasso!(
"And(2^20)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 20
),
single_pass_lasso!(
"And(2^22)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 22
),
single_pass_lasso!(
"And(2^24)",
Fr,
EdwardsProjective,
AndSubtableStrategy,
/* C= */ 1,
/* M= */ 1 << 16,
/* S= */ 1 << 24
),
]
}

fn jolt_demo_benchmarks() -> Vec<(tracing::Span, fn())> {
vec![
single_pass_lasso!(
Expand Down
40 changes: 39 additions & 1 deletion src/poly/dense_mlpoly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use ark_ff::PrimeField;
use ark_serialize::*;
use ark_std::Zero;
use core::ops::Index;
use std::cmp::Ordering;
use merlin::Transcript;
use std::ops::IndexMut;
use std::ops::{AddAssign, IndexMut, Mul};

#[cfg(feature = "ark-msm")]
use ark_ec::VariableBaseMSM;
Expand Down Expand Up @@ -409,6 +410,43 @@ impl<G: CurveGroup> PolyEvalProof<G> {
}
}

impl<F: PrimeField> AddAssign<Self> for DensePolynomial<F> {
fn add_assign(&mut self, rhs: Self) {
let ordering = self.Z.len().cmp(&rhs.Z.len());
#[allow(clippy::disallowed_methods)]
for (lhs, rhs) in self.Z.iter_mut().zip(&rhs.Z) {
*lhs += rhs;
}
if matches!(ordering, Ordering::Less) {
self
.Z
.extend(rhs.Z[self.Z.len()..].iter().cloned());
}
}
}

impl<F: PrimeField> AddAssign<&F> for DensePolynomial<F> {
fn add_assign(&mut self, rhs: &F) {
#[cfg(feature = "multicore")]
let iter = self.Z.par_iter_mut();
#[cfg(not(feature = "multicore"))]
let iter = self.Z.iter_mut();
iter.for_each(|c| *c += rhs);
}
}

impl<F: PrimeField> Mul<F> for DensePolynomial<F> {
type Output = Self;

fn mul(self, rhs: F) -> Self {
#[cfg(feature = "multicore")]
let iter = self.Z.into_par_iter();
#[cfg(not(feature = "multicore"))]
let iter = self.Z.iter();
Self::new(iter.map(|c| c * rhs).collect::<Vec<_>>())
}
}

#[cfg(test)]
mod tests {

Expand Down
33 changes: 21 additions & 12 deletions src/poly/unipoly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::utils::transcript::{AppendToTranscript, ProofTranscript};
use ark_ec::CurveGroup;
use ark_ff::PrimeField;
use ark_serialize::*;
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator, IntoParallelIterator};

// ax^2 + bx + c stored as vec![c,b,a]
// ax^3 + bx^2 + cx + d stored as vec![d,c,b,a]
Expand Down Expand Up @@ -150,33 +151,45 @@ impl<F: PrimeField> UniPoly<F> {

impl<F: PrimeField> AddAssign<&F> for UniPoly<F> {
fn add_assign(&mut self, rhs: &F) {
//TODO: feature gate parallel
self.coeffs.iter_mut().for_each(|c| *c += rhs);
#[cfg(feature = "multicore")]
let iter = self.coeffs.par_iter_mut();
#[cfg(not(feature = "multicore"))]
let iter = self.coeffs.iter_mut();
iter.for_each(|c| *c += rhs);
}
}

impl<F: PrimeField> MulAssign<&F> for UniPoly<F> {
fn mul_assign(&mut self, rhs: &F) {
//TODO: feature gate parallel
self.coeffs.iter_mut().for_each(|c| *c *= rhs);
#[cfg(feature = "multicore")]
let iter = self.coeffs.par_iter_mut();
#[cfg(not(feature = "multicore"))]
let iter = self.coeffs.iter_mut();
iter.for_each(|c| *c *= rhs);
}
}

impl<F: PrimeField> Mul<F> for UniPoly<F> {
type Output = Self;

fn mul(self, rhs: F) -> Self {
//TODO: feature gate parallel
Self::from_coeff(self.coeffs.into_iter().map(|c| c * rhs).collect::<Vec<_>>())
#[cfg(feature = "multicore")]
let iter = self.coeffs.into_par_iter();
#[cfg(not(feature = "multicore"))]
let iter = self.coeffs.iter();
Self::from_coeff(iter.map(|c| c * rhs).collect::<Vec<_>>())
}
}

impl<F: PrimeField> Mul<&F> for UniPoly<F> {
type Output = Self;

fn mul(self, rhs: &F) -> Self {
//TODO: feature gate parallel
Self::from_coeff(self.coeffs.into_iter().map(|c| c * rhs).collect::<Vec<_>>())
#[cfg(feature = "multicore")]
let iter = self.coeffs.into_par_iter();
#[cfg(not(feature = "multicore"))]
let iter = self.coeffs.iter();
Self::from_coeff(iter.map(|c| c * rhs).collect::<Vec<_>>())
}
}

Expand All @@ -192,10 +205,6 @@ impl<F: PrimeField> AddAssign<&Self> for UniPoly<F> {
.coeffs
.extend(rhs.coeffs[self.coeffs.len()..].iter().cloned());
}
if matches!(ordering, Ordering::Equal) {
//TODO: truncate leading zeros
self;
}
}
}

Expand Down
140 changes: 140 additions & 0 deletions src/subprotocols/hyrax.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use super::traits::PCS;


#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
pub struct PolyEvalProof<G: CurveGroup> {
proof: DotProductProofLog<G>,
}

impl<G: CurveGroup> PolyEvalProof<G> {
fn protocol_name() -> &'static [u8] {
b"polynomial evaluation proof"
}
}

impl<G: CurveGroup> PCS for PolyEvalProof<G> {
type Commitment;
type Evaluation;
type Challenge;
type Proof;
type Error;

type ProverKey;
type VerifierKey;

#[tracing::instrument(skip_all, name = "DensePolynomial.commit")]
fn commit<G>(
&self,
gens: &PolyCommitmentGens<G>,
random_tape: Option<&mut RandomTape<G>>,
) -> (PolyCommitment<G>, PolyCommitmentBlinds<F>)
where
G: CurveGroup<ScalarField = F>,
{
let n = self.Z.len();
let ell = self.get_num_vars();
assert_eq!(n, ell.pow2());

let (left_num_vars, right_num_vars) = EqPolynomial::<F>::compute_factored_lens(ell);
let L_size = left_num_vars.pow2();
let R_size = right_num_vars.pow2();
assert_eq!(L_size * R_size, n);

let blinds = if let Some(t) = random_tape {
PolyCommitmentBlinds {
blinds: t.random_vector(b"poly_blinds", L_size),
}
} else {
PolyCommitmentBlinds {
blinds: vec![F::zero(); L_size],
}
};


#[tracing::instrument(skip_all, name = "DensePolyEval.prove")]
fn prove(
poly: &DensePolynomial<G::ScalarField>,
blinds_opt: Option<&PolyCommitmentBlinds<G::ScalarField>>,
r: &[G::ScalarField], // point at which the polynomial is evaluated
Zr: &G::ScalarField, // evaluation of \widetilde{Z}(r)
blind_Zr_opt: Option<&G::ScalarField>, // specifies a blind for Zr
gens: &PolyCommitmentGens<G>,
transcript: &mut Transcript,
random_tape: &mut RandomTape<G>,
) -> (PolyEvalProof<G>, G) {
<Transcript as ProofTranscript<G>>::append_protocol_name(
transcript,
PolyEvalProof::<G>::protocol_name(),
);

// assert vectors are of the right size
assert_eq!(poly.get_num_vars(), r.len());

let (left_num_vars, right_num_vars) =
EqPolynomial::<G::ScalarField>::compute_factored_lens(r.len());
let L_size = left_num_vars.pow2();
let R_size = right_num_vars.pow2();

let default_blinds = PolyCommitmentBlinds {
blinds: vec![G::ScalarField::zero(); L_size],
};
let blinds = blinds_opt.map_or(&default_blinds, |p| p);

assert_eq!(blinds.blinds.len(), L_size);

let zero = G::ScalarField::zero();
let blind_Zr = blind_Zr_opt.map_or(&zero, |p| p);

// compute the L and R vectors
let eq = EqPolynomial::new(r.to_vec());
let (L, R) = eq.compute_factored_evals();
assert_eq!(L.len(), L_size);
assert_eq!(R.len(), R_size);

// compute the vector underneath L*Z and the L*blinds
// compute vector-matrix product between L and Z viewed as a matrix
let LZ = poly.bound(&L);
let LZ_blind: G::ScalarField = (0..L.len()).map(|i| blinds.blinds[i] * L[i]).sum();

// a dot product proof of size R_size
let (proof, _C_LR, C_Zr_prime) = DotProductProofLog::prove(
&gens.gens,
transcript,
random_tape,
&LZ,
&LZ_blind,
&R,
Zr,
blind_Zr,
);

(PolyEvalProof { proof }, C_Zr_prime)
}

fn verify(
&self,
gens: &PolyCommitmentGens<G>,
transcript: &mut Transcript,
r: &[G::ScalarField], // point at which the polynomial is evaluated
C_Zr: &G, // commitment to \widetilde{Z}(r)
comm: &PolyCommitment<G>,
) -> Result<(), ProofVerifyError> {
<Transcript as ProofTranscript<G>>::append_protocol_name(
transcript,
PolyEvalProof::<G>::protocol_name(),
);

// compute L and R
let eq = EqPolynomial::new(r.to_vec());
let (L, R) = eq.compute_factored_evals();

// compute a weighted sum of commitments and L
let C_affine = G::normalize_batch(&comm.C);

let C_LZ = VariableBaseMSM::msm(C_affine.as_ref(), L.as_ref()).unwrap();

self
.proof
.verify(R.len(), &gens.gens, transcript, &R, &C_LZ, C_Zr)
}
}
1 change: 1 addition & 0 deletions src/subprotocols/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ pub mod grand_product;
pub mod sumcheck;
pub mod traits;
pub mod zeromorph;
pub mod hyrax;
9 changes: 1 addition & 8 deletions src/subprotocols/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,7 @@ pub trait PCS<F: Field> {
polys: &[DensePolynomial<F>],
evals: &[Self::Evaluation],
challenges: &[Self::Challenge],
pk: impl Borrow<Self::ProverKey>,
transcript: &mut Transcript,
) -> Result<Self::Proof, Self::Error>;

fn open(
polys: &[DensePolynomial<F>],
evals: &[Self::Evaluation],
challenges: &[Self::Challenge],
commitments: &[Self::Commitment],
pk: impl Borrow<Self::ProverKey>,
transcript: &mut Transcript,
) -> Result<Self::Proof, Self::Error>;
Expand Down
Loading

0 comments on commit 9aaf168

Please sign in to comment.