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

Iquerejeta/pruning #17

Merged
merged 20 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@

use super::multicore;
pub use ff::Field;
use group::prime::PrimeCurveAffine;
use group::{
ff::{BatchInvert, PrimeField},
Curve, Group, GroupOpsOwned, ScalarMulOwned,
};
use std::fmt::Debug;

pub use halo2curves::{CurveAffine, CurveExt};

Expand All @@ -25,7 +27,7 @@ where
{
}

fn multiexp_serial<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C], acc: &mut C::Curve) {
fn multiexp_serial<C: PrimeCurveAffine>(coeffs: &[C::Scalar], bases: &[C], acc: &mut C::Curve) {
let coeffs: Vec<_> = coeffs.iter().map(|a| a.to_repr()).collect();

let c = if bases.len() < 4 {
Expand Down Expand Up @@ -64,17 +66,17 @@ fn multiexp_serial<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C], acc: &mut
}

#[derive(Clone, Copy)]
enum Bucket<C: CurveAffine> {
enum Bucket<C: PrimeCurveAffine> {
None,
Affine(C),
Projective(C::Curve),
}

impl<C: CurveAffine> Bucket<C> {
impl<C: PrimeCurveAffine> Bucket<C> {
fn add_assign(&mut self, other: &C) {
*self = match *self {
Bucket::None => Bucket::Affine(*other),
Bucket::Affine(a) => Bucket::Projective(a + *other),
Bucket::Affine(a) => Bucket::Projective(a.to_curve() + other.to_curve()),
Bucket::Projective(mut a) => {
a += *other;
Bucket::Projective(a)
Expand Down Expand Up @@ -144,7 +146,7 @@ pub fn small_multiexp<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::C
/// 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 {
pub fn best_multiexp<C: PrimeCurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve {
assert_eq!(coeffs.len(), bases.len());

let num_threads = multicore::current_num_threads();
Expand Down Expand Up @@ -289,7 +291,7 @@ pub fn recursive_butterfly_arithmetic<Scalar: Field, G: FftGroup<Scalar>>(
}

/// 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> {
pub fn g_to_lagrange<C: PrimeCurveAffine>(g_projective: Vec<C::Curve>, k: u32) -> Vec<C> {
let n_inv = C::Scalar::TWO_INV.pow_vartime([k as u64, 0, 0, 0]);
let mut omega_inv = C::Scalar::ROOT_OF_UNITY_INV;
for _ in k..C::Scalar::S {
Expand Down Expand Up @@ -507,6 +509,32 @@ pub(crate) fn powers<F: Field>(base: F) -> impl Iterator<Item = F> {
std::iter::successors(Some(F::ONE), move |power| Some(base * power))
}

/// Multi scalar multiplication engine
pub trait MSM<C: PrimeCurveAffine>: Clone + Debug + Send + Sync {
/// Add arbitrary term (the scalar and the point)
fn append_term(&mut self, scalar: C::Scalar, point: C::Curve);

/// Add another multiexp into this one
fn add_msm(&mut self, other: &Self)
where
Self: Sized;
iquerejeta marked this conversation as resolved.
Show resolved Hide resolved

/// Scale all scalars in the MSM by some scaling factor
fn scale(&mut self, factor: C::Scalar);

/// Perform multiexp and check that it results in zero
fn check(&self) -> bool;

/// Perform multiexp and return the result
fn eval(&self) -> C::Curve;

/// Return base points
fn bases(&self) -> Vec<C::Curve>;

/// Scalars
fn scalars(&self) -> Vec<C::Scalar>;
}

#[cfg(test)]
use rand_core::OsRng;

Expand Down
11 changes: 6 additions & 5 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

use crate::poly::Polynomial;
use ff::PrimeField;
use halo2curves::{serde::SerdeObject, CurveAffine};
use group::prime::PrimeCurveAffine;
use halo2curves::serde::SerdeObject;
use std::io;

/// This enum specifies how various types are serialized and deserialized.
Expand All @@ -23,7 +24,7 @@ pub enum SerdeFormat {
}

// Keep this trait for compatibility with IPA serialization
pub(crate) trait CurveRead: CurveAffine {
pub(crate) trait CurveRead: PrimeCurveAffine {
/// Reads a compressed element from the buffer and attempts to parse it
/// using `from_bytes`.
fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
Expand All @@ -33,10 +34,10 @@ pub(crate) trait CurveRead: CurveAffine {
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid point encoding in proof"))
}
}
impl<C: CurveAffine> CurveRead for C {}
impl<C: PrimeCurveAffine> CurveRead for C {}

/// Trait for serialising SerdeObjects
pub trait SerdeCurveAffine: CurveAffine + SerdeObject {
pub trait SerdeCurveAffine: PrimeCurveAffine + SerdeObject + Default {
/// Reads an element from the buffer and parses it according to the `format`:
/// - `Processed`: Reads a compressed curve element and decompress it
/// - `RawBytes`: Reads an uncompressed curve element with coordinates in Montgomery form.
Expand Down Expand Up @@ -68,7 +69,7 @@ pub trait SerdeCurveAffine: CurveAffine + SerdeObject {
}
}
}
impl<C: CurveAffine + SerdeObject> SerdeCurveAffine for C {}
impl<C: PrimeCurveAffine + SerdeObject + Default> SerdeCurveAffine for C {}

/// Trait for implementing field SerdeObjects
pub trait SerdePrimeField: PrimeField + SerdeObject {
Expand Down
8 changes: 5 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
#![deny(unsafe_code)]

pub mod arithmetic;
pub mod circuit;
// pub mod circuit;
pub use halo2curves;
mod multicore;
pub mod plonk;
// pub mod plonk;
pub mod poly;
pub mod transcript;

pub mod dev;
pub mod rational;

// pub mod dev;
pub mod helpers;
pub use helpers::SerdeFormat;
169 changes: 114 additions & 55 deletions src/poly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,32 @@

use crate::arithmetic::parallelize;
use crate::helpers::SerdePrimeField;
use crate::plonk::Assigned;
// use crate::plonk::Assigned;
use crate::SerdeFormat;

use group::ff::{BatchInvert, Field};
use group::ff::Field;
use rand_core::RngCore;
use std::fmt::Debug;
use std::io;
use std::marker::PhantomData;
use std::ops::{Add, Deref, DerefMut, Index, IndexMut, Mul, RangeFrom, RangeFull, Sub};
use std::ops::{
Add, AddAssign, Deref, DerefMut, Index, IndexMut, Mul, MulAssign, RangeFrom, RangeFull, Sub,
};

/// Generic commitment scheme structures
pub mod commitment;
// /// Generic commitment scheme structures
// pub mod commitment;
iquerejeta marked this conversation as resolved.
Show resolved Hide resolved
mod domain;
mod query;
mod strategy;
// mod strategy;
iquerejeta marked this conversation as resolved.
Show resolved Hide resolved

/// KZG commitment scheme
pub mod kzg;

#[cfg(test)]
mod multiopen_test;
pub mod commitment;

pub use domain::*;
pub use query::{ProverQuery, VerifierQuery};
pub use strategy::{Guard, VerificationStrategy};
// pub use strategy::{Guard, VerificationStrategy};
iquerejeta marked this conversation as resolved.
Show resolved Hide resolved

/// This is an error that could occur during proving or circuit synthesis.
// TODO: these errors need to be cleaned up
Expand Down Expand Up @@ -172,52 +174,52 @@ impl<F: SerdePrimeField, B> Polynomial<F, B> {
}
}

pub(crate) fn batch_invert_assigned<F: Field>(
assigned: Vec<Polynomial<Assigned<F>, LagrangeCoeff>>,
) -> Vec<Polynomial<F, LagrangeCoeff>> {
let mut assigned_denominators: Vec<_> = assigned
.iter()
.map(|f| {
f.iter()
.map(|value| value.denominator())
.collect::<Vec<_>>()
})
.collect();

assigned_denominators
.iter_mut()
.flat_map(|f| {
f.iter_mut()
// If the denominator is trivial, we can skip it, reducing the
// size of the batch inversion.
.filter_map(|d| d.as_mut())
})
.batch_invert();

assigned
.iter()
.zip(assigned_denominators)
.map(|(poly, inv_denoms)| poly.invert(inv_denoms.into_iter().map(|d| d.unwrap_or(F::ONE))))
.collect()
}

impl<F: Field> Polynomial<Assigned<F>, LagrangeCoeff> {
pub(crate) fn invert(
&self,
inv_denoms: impl Iterator<Item = F> + ExactSizeIterator,
) -> Polynomial<F, LagrangeCoeff> {
assert_eq!(inv_denoms.len(), self.values.len());
Polynomial {
values: self
.values
.iter()
.zip(inv_denoms)
.map(|(a, inv_den)| a.numerator() * inv_den)
.collect(),
_marker: self._marker,
}
}
}
// pub(crate) fn batch_invert_assigned<F: Field>(
// assigned: Vec<Polynomial<Assigned<F>, LagrangeCoeff>>,
// ) -> Vec<Polynomial<F, LagrangeCoeff>> {
// let mut assigned_denominators: Vec<_> = assigned
// .iter()
// .map(|f| {
// f.iter()
// .map(|value| value.denominator())
// .collect::<Vec<_>>()
// })
// .collect();
//
// assigned_denominators
// .iter_mut()
// .flat_map(|f| {
// f.iter_mut()
// // If the denominator is trivial, we can skip it, reducing the
// // size of the batch inversion.
// .filter_map(|d| d.as_mut())
// })
// .batch_invert();
//
// assigned
// .iter()
// .zip(assigned_denominators)
// .map(|(poly, inv_denoms)| poly.invert(inv_denoms.into_iter().map(|d| d.unwrap_or(F::ONE))))
// .collect()
// }
//
// impl<F: Field> Polynomial<Assigned<F>, LagrangeCoeff> {
// pub(crate) fn invert(
// &self,
// inv_denoms: impl Iterator<Item = F> + ExactSizeIterator,
// ) -> Polynomial<F, LagrangeCoeff> {
// assert_eq!(inv_denoms.len(), self.values.len());
// Polynomial {
// values: self
// .values
// .iter()
// .zip(inv_denoms)
// .map(|(a, inv_den)| a.numerator() * inv_den)
// .collect(),
// _marker: self._marker,
// }
// }
// }

impl<'a, F: Field, B: Basis> Add<&'a Polynomial<F, B>> for Polynomial<F, B> {
type Output = Polynomial<F, B>;
Expand Down Expand Up @@ -319,3 +321,60 @@ impl Rotation {
Rotation(1)
}
}

/// Wrapper type around a blinding factor.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Blind<F>(pub F);

impl<F: Field> Default for Blind<F> {
fn default() -> Self {
Blind(F::ONE)
}
}

impl<F: Field> Blind<F> {
/// Given `rng` creates new blinding scalar
pub fn new<R: RngCore>(rng: &mut R) -> Self {
Blind(F::random(rng))
}
}

impl<F: Field> Add for Blind<F> {
type Output = Self;

fn add(self, rhs: Blind<F>) -> Self {
Blind(self.0 + rhs.0)
}
}

impl<F: Field> Mul for Blind<F> {
type Output = Self;

fn mul(self, rhs: Blind<F>) -> Self {
Blind(self.0 * rhs.0)
}
}

impl<F: Field> AddAssign for Blind<F> {
fn add_assign(&mut self, rhs: Blind<F>) {
self.0 += rhs.0;
}
}

impl<F: Field> MulAssign for Blind<F> {
fn mul_assign(&mut self, rhs: Blind<F>) {
self.0 *= rhs.0;
}
}

impl<F: Field> AddAssign<F> for Blind<F> {
fn add_assign(&mut self, rhs: F) {
self.0 += rhs;
}
}

impl<F: Field> MulAssign<F> for Blind<F> {
fn mul_assign(&mut self, rhs: F) {
self.0 *= rhs;
}
}
Loading