Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
136 changes: 136 additions & 0 deletions w3f-plonk-common/src/gadgets/column_sum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use ark_ff::{FftField, Field};
use ark_poly::univariate::DensePolynomial;
use ark_poly::{Evaluations, GeneralEvaluationDomain};
use ark_std::rc::Rc;
use ark_std::{vec, vec::Vec};

use crate::domain::Domain;
use crate::gadgets::{ProverGadget, VerifierGadget};
use crate::{Column, FieldColumn};

/// Computes the sum of the elements of a `col`. All but last.
///
/// Let `c` be the domain "capacity" (`c = domain.size - ZK_ROWS`).
/// The gadget populates and constrains a witness column `acc`,
/// such that `acc[i+1] = acc[i] + col[i], i = 0,...,c-2`.
/// Then `acc[c-1] = acc[0] + (col[0] + ... + col[c-2]) = acc[0] + sum(col[0..c-1])`.
/// `acc[0]` and `acc[c-1]` have to be additionally constrained.
pub struct ColumnSumPolys<F: FftField> {
/// Input column.
/// Should have length `c-1`,
/// `col[0], ..., col[c-2]`
pub col: Rc<FieldColumn<F>>,
/// Partial sums of `col`:
/// `acc[0] = 0, acc[i+1] = col[0] + ... + col[i], i = 0,...,c-2`
pub acc: Rc<FieldColumn<F>>,
/// `p(X) = X - w^(c-1)` -- disables the constraint for `i = c-1`, i.e. between `acc[c-1]` and `acc[c]`.
pub not_last: FieldColumn<F>,
}

pub struct ColumnSumEvals<F: Field> {
pub col: F,
pub acc: F,
pub not_last: F,
}

impl<F: FftField> ColumnSumPolys<F> {
pub fn init(col: Rc<FieldColumn<F>>, domain: &Domain<F>) -> Self {
assert_eq!(col.len, domain.capacity - 1); // last element is not constrained
let partial_sums = Self::partial_sums(col.vals());
let mut acc = vec![F::zero()];
acc.extend(partial_sums);
let acc = domain.private_column(acc);
let acc = Rc::new(acc);
Self {
col,
acc,
not_last: domain.not_last_row.clone(),
}
}

/// Returns `col[0], col[0] + col[1], ..., col[0] + col[1] + ... + col[n-1]`.
pub fn partial_sums(col: &[F]) -> Vec<F> {
col.iter()
.scan(F::zero(), |state, &x| {
*state += x;
Some(*state)
})
.collect()
}
}

impl<F: FftField> ProverGadget<F> for ColumnSumPolys<F> {
fn witness_columns(&self) -> Vec<DensePolynomial<F>> {
vec![self.acc.poly.clone()]
}

fn constraints(&self) -> Vec<Evaluations<F>> {
// A degree `n` polynomial is computed using evaluations at `4n` points.
// Still it's convenient, as we aggregate the constraints in the evaluation form
// over the `4x` domain.
let col = &self.col.evals_4x;
let acc = &self.acc.evals_4x;
let acc_shifted = &self.acc.shifted_4x();
let not_last = &self.not_last.evals_4x;
let c = &(&(acc_shifted - acc) - col) * not_last;
vec![c]
}

fn constraints_linearized(&self, z: &F) -> Vec<DensePolynomial<F>> {
let c = &self.acc.poly * self.not_last.evaluate(z);
vec![c]
}

fn domain(&self) -> GeneralEvaluationDomain<F> {
self.col.evals.domain()
}
}

impl<F: Field> VerifierGadget<F> for ColumnSumEvals<F> {
fn evaluate_constraints_main(&self) -> Vec<F> {
let c = (-self.acc - self.col) * self.not_last;
vec![c]
}
}

#[cfg(test)]
mod tests {
use ark_ed_on_bls12_381_bandersnatch::Fq;
use ark_ff::Zero;
use ark_poly::Polynomial;
use ark_std::test_rng;

use crate::domain::Domain;
use crate::test_helpers::random_vec;

use super::*;

fn _column_sum_gadget(hiding: bool) {
let rng = &mut test_rng();

let log_n = 10;
let n = 2usize.pow(log_n);
let domain = Domain::new(n, hiding);

let col = random_vec(domain.capacity - 1, rng);
let sum = col.iter().sum();
let col = Rc::new(domain.private_column(col));

let gadget = ColumnSumPolys::<Fq>::init(col, &domain);

let acc = &gadget.acc.evals.evals;
assert!(acc[0].is_zero());
assert_eq!(acc[domain.capacity - 1], sum);

let constraint_poly = gadget.constraints()[0].interpolate_by_ref();

assert_eq!(constraint_poly.degree(), n);
domain.divide_by_vanishing_poly(&constraint_poly);
}

#[test]
fn column_sum_gadget() {
_column_sum_gadget(false);
_column_sum_gadget(true);
}
}
2 changes: 1 addition & 1 deletion w3f-plonk-common/src/gadgets/ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ where
domain: &Domain<F>,
) -> Self {
assert_eq!(bitmask.bits.len(), domain.capacity - 1);
assert_eq!(points.points.len(), domain.capacity - 1);
// assert_eq!(points.points.len(), domain.capacity - 1); //TODO
let not_last = domain.not_last_row.clone();
let acc = bitmask
.bits
Expand Down
39 changes: 23 additions & 16 deletions w3f-plonk-common/src/gadgets/fixed_cells.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use crate::{const_evals, Column, FieldColumn};

pub struct FixedCells<F: FftField> {
col: Rc<FieldColumn<F>>,
col_first: F,
col_last: F,
l_first: FieldColumn<F>,
l_last: FieldColumn<F>,
}
Expand All @@ -27,40 +25,49 @@ pub struct FixedCellsValues<F: Field> {
impl<F: FftField> FixedCells<F> {
pub fn init(col: Rc<FieldColumn<F>>, domain: &Domain<F>) -> Self {
assert_eq!(col.len, domain.capacity);
let col_first = col.evals.evals[0];
let col_last = col.evals.evals[domain.capacity - 1];
let l_first = domain.l_first.clone();
let l_last = domain.l_last.clone();
Self {
col,
col_first,
col_last,
l_first,
l_last,
}
}

pub fn constraints(&self) -> Vec<Evaluations<F>> {
let col = &self.col;
let domain = col.domain_4x();
let first = &const_evals(self.col_first, domain);
let last = &const_evals(self.col_last, domain);
let col = &self.col.evals_4x;
let l_first = &self.l_first.evals_4x;
let l_last = &self.l_last.evals_4x;
let c = &(l_first * &(col - first)) + &(l_last * &(col - last));
let domain_capacity = self.col.len; // that's an ugly way to learn the capacity, but we've asserted it above.
let c = &Self::constraint_cell(&self.col, &self.l_first, 0)
+ &Self::constraint_cell(&self.col, &self.l_last, domain_capacity - 1);
vec![c]
}

pub fn constraints_linearized(&self, _z: &F) -> Vec<DensePolynomial<F>> {
vec![DensePolynomial::zero()]
}

/// Constraints the column `col` to have the value `col[i]` at index `i`.
/// `li` should be the `i-th` Lagrange basis polynomial `li = L_i(X)`.
/// The constraint polynomial is `c(X) = L_i(X).col(X) - col[i].L_i(X)`.
pub fn constraint_cell(col: &FieldColumn<F>, li: &FieldColumn<F>, i: usize) -> Evaluations<F> {
let cell_val = col.evals[i];
let domain = col.domain_4x();
let cell_val = &const_evals(cell_val, domain);
let col = &col.evals_4x;
let li = &li.evals_4x;
li * &(col - cell_val)
}
}

impl<F: Field> FixedCellsValues<F> {
pub fn evaluate_for_cell(col_eval: F, li_eval: F, cell_val: F) -> F {
li_eval * (col_eval - cell_val)
}
}

impl<F: Field> VerifierGadget<F> for FixedCellsValues<F> {
fn evaluate_constraints_main(&self) -> Vec<F> {
let c =
(self.col - self.col_first) * self.l_first + (self.col - self.col_last) * self.l_last;
let c = Self::evaluate_for_cell(self.col, self.l_first, self.col_first)
+ Self::evaluate_for_cell(self.col, self.l_last, self.col_last);
vec![c]
}
}
1 change: 1 addition & 0 deletions w3f-plonk-common/src/gadgets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use ark_std::vec::Vec;

pub mod booleanity;
// pub mod inner_prod_pub;
pub mod column_sum;
pub mod ec;
pub mod fixed_cells;
pub mod inner_prod;
Expand Down
8 changes: 4 additions & 4 deletions w3f-plonk-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ pub trait Column<F: FftField> {
#[derive(Clone)]
pub struct FieldColumn<F: FftField> {
// actual (constrained) len of the input in evaluation form
len: usize,
poly: DensePolynomial<F>,
evals: Evaluations<F>,
evals_4x: Evaluations<F>,
pub len: usize,
pub poly: DensePolynomial<F>,
pub evals: Evaluations<F>,
pub evals_4x: Evaluations<F>,
}

impl<F: FftField> FieldColumn<F> {
Expand Down
2 changes: 0 additions & 2 deletions w3f-plonk-common/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ impl<F: PrimeField, CS: PCS<F>, T: PlonkTranscript<F, CS>> PlonkProver<F, CS, T>
let lin_at_zeta_omega = lin.evaluate(&zeta_omega);
transcript.add_evaluations(&columns_at_zeta, &lin_at_zeta_omega);

println!("z= {}", zeta);

let polys_at_zeta = [columns_to_open, vec![quotient_poly]].concat();
let nus = transcript.get_kzg_aggregation_challenges(polys_at_zeta.len());
let agg_at_zeta = aggregate_polys(&polys_at_zeta, &nus);
Expand Down
1 change: 1 addition & 0 deletions w3f-ring-proof/src/piop/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl<F: PrimeField, Curve: TECurveConfig<BaseField = F>> PiopProver<F, Curve> {
}
}

// TODO: move to params?
fn bits_column(
params: &PiopParams<F, Curve>,
index_in_keys: usize,
Expand Down
Loading
Loading