Skip to content

Commit

Permalink
refactor: Implement and integrate rlc function for simplified lin. …
Browse files Browse the repository at this point in the history
…combination (#260)

* refactor: Implement and integrate `rlc` function for simplified combination semantics

- Introduced a new function `rlc`, which implements Horner's scheme,
- Applied traits `Borrow`, `MulAssign`, and `AddAssign` to define it, which exist on `UniPoly`,
- Used `rlc` function in `evaluate` method and `kzg_compute_batch_polynomial`,
- Updated closures in `mlkzg.rs` file to directly handle vector arguments, simplifying the overall operations.
- Streamlined the code by eliminating unnecessary assertions in `kzg_verify_batch` closure and redundant inner function in `kzg_compute_batch_polynomial`.

* feat: change to an Iterator extension trait
  • Loading branch information
huitseeker authored Jan 16, 2024
1 parent 87327fd commit def59e2
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 32 deletions.
31 changes: 8 additions & 23 deletions src/provider/mlkzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
non_hiding_kzg::{KZGProverKey, KZGVerifierKey, UniversalKZGParam},
pedersen::Commitment,
traits::DlogGroup,
util::iterators::DoubleEndedIteratorExt as _,
},
spartan::polys::univariate::UniPoly,
traits::{
Expand Down Expand Up @@ -164,30 +165,14 @@ where
.to_affine()
};

let kzg_open_batch = |f: &[Vec<E::Fr>],
let kzg_open_batch = |f: Vec<Vec<E::Fr>>,
u: &[E::Fr],
transcript: &mut <NE as NovaEngine>::TE|
-> (Vec<E::G1Affine>, Vec<Vec<E::Fr>>) {
let scalar_vector_muladd = |a: &mut Vec<E::Fr>, v: &Vec<E::Fr>, s: E::Fr| {
assert!(a.len() >= v.len());
#[allow(clippy::disallowed_methods)]
a.par_iter_mut()
.zip(v.par_iter())
.for_each(|(c, v)| *c += s * v);
};

let kzg_compute_batch_polynomial = |f: &[Vec<E::Fr>], q: E::Fr| -> Vec<E::Fr> {
let k = f.len(); // Number of polynomials we're batching

let q_powers = Self::batch_challenge_powers(q, k);

// Compute B(x) = f[0] + q*f[1] + q^2 * f[2] + ... q^(k-1) * f[k-1]
let mut B = f[0].clone();
for i in 1..k {
scalar_vector_muladd(&mut B, &f[i], q_powers[i]); // B += q_powers[i] * f[i]
}

B
let kzg_compute_batch_polynomial = |f: Vec<Vec<E::Fr>>, q: E::Fr| -> Vec<E::Fr> {
// Compute B(x) = f_0(x) + q * f_1(x) + ... + q^(k-1) * f_{k-1}(x)
let B: UniPoly<E::Fr> = f.into_iter().map(UniPoly::new).rlc(&q);
B.coeffs
};
///////// END kzg_open_batch closure helpers

Expand All @@ -199,7 +184,7 @@ where
let mut v = vec![vec!(E::Fr::ZERO; k); t];
v.par_iter_mut().enumerate().for_each(|(i, v_i)| {
// for each point u
v_i.par_iter_mut().zip_eq(f).for_each(|(v_ij, f)| {
v_i.par_iter_mut().zip_eq(&f).for_each(|(v_ij, f)| {
// for each poly f (except the last one - since it is constant)
*v_ij = UniPoly::ref_cast(f).evaluate(&u[i]);
});
Expand Down Expand Up @@ -259,7 +244,7 @@ where
let u = vec![r, -r, r * r];

// Phase 3 -- create response
let (w, evals) = kzg_open_batch(&polys, &u, transcript);
let (w, evals) = kzg_open_batch(polys, &u, transcript);

Ok(EvaluationArgument { comms, w, evals })
}
Expand Down
2 changes: 1 addition & 1 deletion src/provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) mod traits;
// a non-hiding variant of {kzg, zeromorph}
mod kzg_commitment;
mod non_hiding_kzg;
mod util;
pub(crate) mod util;

// crate-private modules
mod keccak;
Expand Down
29 changes: 29 additions & 0 deletions src/provider/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,35 @@ pub mod msm {
}
}

pub mod iterators {
use std::borrow::Borrow;
use std::iter::DoubleEndedIterator;
use std::ops::{AddAssign, MulAssign};

pub trait DoubleEndedIteratorExt: DoubleEndedIterator {
/// This function employs Horner's scheme and core traits to create a combination of an iterator input with the powers
/// of a provided coefficient.
fn rlc<T, F>(&mut self, coefficient: &F) -> T
where
T: Clone + for<'a> MulAssign<&'a F> + for<'r> AddAssign<&'r T>,
Self::Item: Borrow<T>,
{
let mut iter = self.rev();
let Some(fst) = iter.next() else {
panic!("input iterator should not be empty")
};

iter.fold(fst.borrow().clone(), |mut acc, item| {
acc *= coefficient;
acc += item.borrow();
acc
})
}
}

impl<I: DoubleEndedIterator> DoubleEndedIteratorExt for I {}
}

#[cfg(test)]
pub mod test_utils {
//! Contains utilities for testing and benchmarking.
Expand Down
13 changes: 5 additions & 8 deletions src/spartan/polys/univariate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use rayon::prelude::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelI
use ref_cast::RefCast;
use serde::{Deserialize, Serialize};

use crate::traits::{Group, TranscriptReprTrait};
use crate::{
provider::util::iterators::DoubleEndedIteratorExt as _,
traits::{Group, TranscriptReprTrait},
};

// 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 @@ -131,13 +134,7 @@ impl<Scalar: PrimeField> UniPoly<Scalar> {
}

pub fn evaluate(&self, r: &Scalar) -> Scalar {
let mut eval = self.coeffs[0];
let mut power = *r;
for coeff in self.coeffs.iter().skip(1) {
eval += power * coeff;
power *= r;
}
eval
self.coeffs.iter().rlc(r)
}

pub fn compress(&self) -> CompressedUniPoly<Scalar> {
Expand Down

1 comment on commit def59e2

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

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

Benchmarks

Table of Contents

Overview

This benchmark report shows the Arecibo GPU benchmarks.
NVIDIA L4
Intel(R) Xeon(R) CPU @ 2.20GHz
32 vCPUs
125 GB RAM
Workflow run: https://github.com/lurk-lab/arecibo/actions/runs/7547732801

Benchmark Results

RecursiveSNARKSuperNova-2circuit

ref=87327fdb9cc47fe3261dfb51c867c79c1d9eb0c7
Prove-StepCircuitSize-... 54.99 ms (✅ 1.00x)
Verify-StepCircuitSize... 32.99 ms (✅ 1.00x)
Prove-StepCircuitSize-... #2 348.28 ms (✅ 1.00x)
Verify-StepCircuitSize... #2 260.01 ms (✅ 1.00x)

CompressedSNARKSuperNova-Commitments-2circuit

ref=87327fdb9cc47fe3261dfb51c867c79c1d9eb0c7
Prove-Ste... 14.11 s (✅ 1.00x)
Verify-St... 79.07 ms (✅ 1.00x)
Prove-Ste... #2 113.41 s (✅ 1.00x)
Verify-St... #2 771.24 ms (✅ 1.00x)

Made with criterion-table

Please sign in to comment.