Skip to content

Commit

Permalink
Remove/best {fft/multiexp} & other unused arithmetic functions (#288)
Browse files Browse the repository at this point in the history
* remove: best_{fft/multiexp} and use halo2curves

We remove duplicated code from `halo2` which now is externalized (and
more optimal) in `halo2curves`.

This is a followup of #282

* remove: Unused functions from arithmetic

* remove: FFT & MSM benches

As these are now handled by halo2curves.  There's no need to bench here.
  • Loading branch information
CPerezz authored Feb 27, 2024
1 parent e892c86 commit 06d7007
Show file tree
Hide file tree
Showing 12 changed files with 16 additions and 274 deletions.
189 changes: 2 additions & 187 deletions halo2_backend/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

use group::{
ff::{BatchInvert, PrimeField},
Curve, Group, GroupOpsOwned, ScalarMulOwned,
Curve, GroupOpsOwned, ScalarMulOwned,
};
use halo2_common::multicore;
pub use halo2_middleware::ff::Field;

use halo2curves::msm::multiexp_serial;
use halo2curves::fft::best_fft;
pub use halo2curves::{CurveAffine, CurveExt};

/// This represents an element of a group with basic operations that can be
Expand All @@ -26,179 +26,6 @@ where
{
}

/// Performs a small multi-exponentiation operation.
/// Uses the double-and-add algorithm with doublings shared across points.
pub fn small_multiexp<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve {
let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect();
let mut acc = C::Curve::identity();

// for byte idx
for byte_idx in (0..((C::Scalar::NUM_BITS as usize + 7) / 8)).rev() {
// for bit idx
for bit_idx in (0..8).rev() {
acc = acc.double();
// for each coeff
for coeff_idx in 0..coeffs.len() {
let byte = coeffs[coeff_idx].as_ref()[byte_idx];
if ((byte >> bit_idx) & 1) != 0 {
acc += bases[coeff_idx];
}
}
}
}

acc
}

/// Performs a multi-exponentiation operation.
///
/// This function will panic if coeffs and bases have a different length.
///
/// This will use multithreading if beneficial.
pub fn best_multiexp<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve {
assert_eq!(coeffs.len(), bases.len());

let num_threads = multicore::current_num_threads();
if coeffs.len() > num_threads {
let chunk = coeffs.len() / num_threads;
let num_chunks = coeffs.chunks(chunk).len();
let mut results = vec![C::Curve::identity(); num_chunks];
multicore::scope(|scope| {
let chunk = coeffs.len() / num_threads;

for ((coeffs, bases), acc) in coeffs
.chunks(chunk)
.zip(bases.chunks(chunk))
.zip(results.iter_mut())
{
scope.spawn(move |_| {
multiexp_serial(coeffs, bases, acc);
});
}
});
results.iter().fold(C::Curve::identity(), |a, b| a + b)
} else {
let mut acc = C::Curve::identity();
multiexp_serial(coeffs, bases, &mut acc);
acc
}
}

/// Performs a radix-$2$ Fast-Fourier Transformation (FFT) on a vector of size
/// $n = 2^k$, when provided `log_n` = $k$ and an element of multiplicative
/// order $n$ called `omega` ($\omega$). The result is that the vector `a`, when
/// interpreted as the coefficients of a polynomial of degree $n - 1$, is
/// transformed into the evaluations of this polynomial at each of the $n$
/// distinct powers of $\omega$. This transformation is invertible by providing
/// $\omega^{-1}$ in place of $\omega$ and dividing each resulting field element
/// by $n$.
///
/// This will use multithreading if beneficial.
pub fn best_fft<Scalar: Field, G: FftGroup<Scalar>>(a: &mut [G], omega: Scalar, log_n: u32) {
fn bitreverse(mut n: usize, l: usize) -> usize {
let mut r = 0;
for _ in 0..l {
r = (r << 1) | (n & 1);
n >>= 1;
}
r
}

let threads = multicore::current_num_threads();
let log_threads = log2_floor(threads);
let n = a.len();
assert_eq!(n, 1 << log_n);

for k in 0..n {
let rk = bitreverse(k, log_n as usize);
if k < rk {
a.swap(rk, k);
}
}

// precompute twiddle factors
let twiddles: Vec<_> = (0..(n / 2))
.scan(Scalar::ONE, |w, _| {
let tw = *w;
*w *= &omega;
Some(tw)
})
.collect();

if log_n <= log_threads {
let mut chunk = 2_usize;
let mut twiddle_chunk = n / 2;
for _ in 0..log_n {
a.chunks_mut(chunk).for_each(|coeffs| {
let (left, right) = coeffs.split_at_mut(chunk / 2);

// case when twiddle factor is one
let (a, left) = left.split_at_mut(1);
let (b, right) = right.split_at_mut(1);
let t = b[0];
b[0] = a[0];
a[0] += &t;
b[0] -= &t;

left.iter_mut()
.zip(right.iter_mut())
.enumerate()
.for_each(|(i, (a, b))| {
let mut t = *b;
t *= &twiddles[(i + 1) * twiddle_chunk];
*b = *a;
*a += &t;
*b -= &t;
});
});
chunk *= 2;
twiddle_chunk /= 2;
}
} else {
recursive_butterfly_arithmetic(a, n, 1, &twiddles)
}
}

/// This perform recursive butterfly arithmetic
pub fn recursive_butterfly_arithmetic<Scalar: Field, G: FftGroup<Scalar>>(
a: &mut [G],
n: usize,
twiddle_chunk: usize,
twiddles: &[Scalar],
) {
if n == 2 {
let t = a[1];
a[1] = a[0];
a[0] += &t;
a[1] -= &t;
} else {
let (left, right) = a.split_at_mut(n / 2);
multicore::join(
|| recursive_butterfly_arithmetic(left, n / 2, twiddle_chunk * 2, twiddles),
|| recursive_butterfly_arithmetic(right, n / 2, twiddle_chunk * 2, twiddles),
);

// case when twiddle factor is one
let (a, left) = left.split_at_mut(1);
let (b, right) = right.split_at_mut(1);
let t = b[0];
b[0] = a[0];
a[0] += &t;
b[0] -= &t;

left.iter_mut()
.zip(right.iter_mut())
.enumerate()
.for_each(|(i, (a, b))| {
let mut t = *b;
t *= &twiddles[(i + 1) * twiddle_chunk];
*b = *a;
*a += &t;
*b -= &t;
});
}
}

/// Convert coefficient bases group elements to lagrange basis by inverse FFT.
pub fn g_to_lagrange<C: CurveAffine>(g_projective: Vec<C::Curve>, k: u32) -> Vec<C> {
let n_inv = C::Scalar::TWO_INV.pow_vartime([k as u64, 0, 0, 0]);
Expand Down Expand Up @@ -344,18 +171,6 @@ pub fn parallelize<T: Send, F: Fn(&mut [T], usize) + Send + Sync + Clone>(v: &mu
});
}

fn log2_floor(num: usize) -> u32 {
assert!(num > 0);

let mut pow = 0;

while (1 << (pow + 1)) <= num {
pow += 1;
}

pow
}

/// Returns coefficients of an n - 1 degree polynomial given a set of n points
/// and their evaluations. This function will panic if two values in `points`
/// are the same.
Expand Down
3 changes: 2 additions & 1 deletion halo2_backend/src/poly/domain.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! Contains utilities for performing polynomial arithmetic over an evaluation
//! domain that is of a suitable size for the application.

use crate::arithmetic::{best_fft, parallelize};
use crate::arithmetic::parallelize;

use super::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial};
use group::ff::{BatchInvert, Field};
use halo2_middleware::ff::WithSmallOrderMulGroup;
use halo2_middleware::poly::Rotation;
use halo2curves::fft::best_fft;

use std::marker::PhantomData;

Expand Down
3 changes: 2 additions & 1 deletion halo2_backend/src/poly/ipa/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
//!
//! [halo]: https://eprint.iacr.org/2019/1021

use crate::arithmetic::{best_multiexp, g_to_lagrange, parallelize, CurveAffine, CurveExt};
use crate::arithmetic::{g_to_lagrange, parallelize, CurveAffine, CurveExt};
use crate::helpers::CurveRead;
use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier};
use crate::poly::ipa::msm::MSMIPA;
use crate::poly::{Coeff, LagrangeCoeff, Polynomial};

use group::{Curve, Group};
use halo2curves::msm::best_multiexp;
use std::marker::PhantomData;

mod prover;
Expand Down
5 changes: 2 additions & 3 deletions halo2_backend/src/poly/ipa/commitment/prover.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use halo2_middleware::ff::Field;
use halo2curves::msm::best_multiexp;
use rand_core::RngCore;

use super::ParamsIPA;
use crate::arithmetic::{
best_multiexp, compute_inner_product, eval_polynomial, parallelize, CurveAffine,
};
use crate::arithmetic::{compute_inner_product, eval_polynomial, parallelize, CurveAffine};

use crate::poly::commitment::ParamsProver;
use crate::poly::{commitment::Blind, Coeff, Polynomial};
Expand Down
3 changes: 2 additions & 1 deletion halo2_backend/src/poly/ipa/msm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::arithmetic::{best_multiexp, CurveAffine};
use crate::arithmetic::CurveAffine;
use crate::poly::{commitment::MSM, ipa::commitment::ParamsVerifierIPA};
use group::Group;
use halo2_middleware::ff::Field;
use halo2curves::msm::best_multiexp;
use std::collections::BTreeMap;

/// A multiscalar multiplication in the polynomial commitment scheme
Expand Down
2 changes: 1 addition & 1 deletion halo2_backend/src/poly/ipa/strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use super::commitment::{IPACommitmentScheme, ParamsIPA};
use super::msm::MSMIPA;
use super::multiopen::VerifierIPA;
use crate::{
arithmetic::best_multiexp,
plonk::Error,
poly::{
commitment::MSM,
Expand All @@ -11,6 +10,7 @@ use crate::{
};
use group::Curve;
use halo2_middleware::ff::Field;
use halo2curves::msm::best_multiexp;
use halo2curves::CurveAffine;
use rand_core::OsRng;

Expand Down
3 changes: 2 additions & 1 deletion halo2_backend/src/poly/kzg/commitment.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::arithmetic::{best_multiexp, g_to_lagrange, parallelize};
use crate::arithmetic::{g_to_lagrange, parallelize};
use crate::helpers::SerdeCurveAffine;
use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier};
use crate::poly::{Coeff, LagrangeCoeff, Polynomial};
use crate::SerdeFormat;

use group::{prime::PrimeCurveAffine, Curve, Group};
use halo2_middleware::ff::{Field, PrimeField};
use halo2curves::msm::best_multiexp;
use halo2curves::pairing::Engine;
use halo2curves::CurveExt;
use rand_core::{OsRng, RngCore};
Expand Down
6 changes: 2 additions & 4 deletions halo2_backend/src/poly/kzg/msm.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use std::fmt::Debug;

use super::commitment::ParamsKZG;
use crate::{
arithmetic::{best_multiexp, parallelize},
poly::commitment::MSM,
};
use crate::{arithmetic::parallelize, poly::commitment::MSM};
use group::{Curve, Group};
use halo2curves::{
msm::best_multiexp,
pairing::{Engine, MillerLoopResult, MultiMillerLoop},
CurveAffine, CurveExt,
};
Expand Down
8 changes: 0 additions & 8 deletions halo2_proofs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ keywords = ["halo", "proofs", "zkp", "zkSNARKs"]
all-features = true
rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"]

[[bench]]
name = "arithmetic"
harness = false

[[bench]]
name = "commit_zk"
harness = false
Expand All @@ -44,10 +40,6 @@ harness = false
name = "dev_lookup"
harness = false

[[bench]]
name = "fft"
harness = false

[dependencies]
halo2_middleware = { path = "../halo2_middleware" }
halo2_common = { path = "../halo2_common" }
Expand Down
38 changes: 0 additions & 38 deletions halo2_proofs/benches/arithmetic.rs

This file was deleted.

Loading

0 comments on commit 06d7007

Please sign in to comment.