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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = [
# "evm-vrfier",
"w3f-plonk-common",
"w3f-ring-proof",
"w3f-ring-vrf-snark",
# "w3f-ring-vrf-snark",
]

[workspace.dependencies]
Expand All @@ -14,7 +14,7 @@ ark-ec = { version = "0.5", default-features = false }
ark-poly = { version = "0.5", default-features = false }
ark-serialize = { version = "0.5", default-features = false, features = ["derive"] }
w3f-pcs = { version = "0.0.5", default-features = false }
w3f-plonk-common = { version = "0.0.6", default-features = false }
w3f-plonk-common = { path="w3f-plonk-common", default-features = false }
rayon = { version = "1", default-features = false }
ark-transcript = { version = "0.0.3", default-features = false }
blake2 = { version = "0.10", default-features = false }
Expand Down
65 changes: 35 additions & 30 deletions w3f-plonk-common/src/domain.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::FieldColumn;
use ark_ff::{batch_inversion, FftField, Zero};
use ark_poly::univariate::DensePolynomial;
use ark_poly::{
DenseUVPolynomial, EvaluationDomain, Evaluations, GeneralEvaluationDomain, Polynomial,
};
use ark_std::{vec, vec::Vec};

use crate::FieldColumn;
use getrandom_or_panic::getrandom_or_panic;

pub const ZK_ROWS: usize = 3;

Expand All @@ -25,29 +25,29 @@ impl<F: FftField> Domains<F> {
Self { x1, x4 }
}

fn column_from_evals(&self, evals: Vec<F>, len: usize) -> FieldColumn<F> {
assert_eq!(evals.len(), self.x1.size());
let evals = Evaluations::from_vec_and_domain(evals, self.x1);
fn column_from_evals(&self, padded_evals: Vec<F>, payload_len: usize) -> FieldColumn<F> {
debug_assert_eq!(padded_evals.len(), self.x1.size());
let evals = Evaluations::from_vec_and_domain(padded_evals, self.x1);
let poly = evals.interpolate_by_ref();
let evals_4x = poly.evaluate_over_domain_by_ref(self.x4);
FieldColumn {
len,
poly,
evals,
evals_4x,
payload_len,
}
}

fn column_from_poly(&self, poly: DensePolynomial<F>, len: usize) -> FieldColumn<F> {
assert!(poly.degree() < self.x1.size());
fn column_from_poly(&self, poly: DensePolynomial<F>) -> FieldColumn<F> {
debug_assert!(poly.degree() + 1 <= self.x1.size());
let evals_4x = self.amplify(&poly);
let evals = evals_4x.evals.iter().step_by(4).cloned().collect();
let evals = Evaluations::from_vec_and_domain(evals, self.x1);
FieldColumn {
len,
poly,
evals,
evals_4x,
payload_len: self.x1.size(),
}
}

Expand All @@ -71,23 +71,27 @@ pub struct Domain<F: FftField> {
impl<F: FftField> Domain<F> {
pub fn new(n: usize, hiding: bool) -> Self {
let domains = Domains::new(n);
let size = domains.x1.size();
let capacity = if hiding { size - ZK_ROWS } else { size };
let last_row_index = capacity - 1;

let l_first = l_i(0, size);
let l_first = domains.column_from_evals(l_first, capacity);
let l_last = l_i(last_row_index, size);
let l_last = domains.column_from_evals(l_last, capacity);
let domain_size = domains.x1.size();
let domain_capacity = if hiding {
domain_size - ZK_ROWS
} else {
domain_size
};
let last_row_index = domain_capacity - 1;

let l_first = l_i(0, domain_size);
let l_first = domains.column_from_evals(l_first, 0);
let l_last = l_i(last_row_index, domain_size);
let l_last = domains.column_from_evals(l_last, 0);
let not_last_row = vanishes_on_row(last_row_index, domains.x1);
let not_last_row = domains.column_from_poly(not_last_row, capacity);
let not_last_row = domains.column_from_poly(not_last_row);

let zk_rows_vanishing_poly = hiding.then(|| vanishes_on_last_3_rows(domains.x1));

Self {
domains,
hiding,
capacity,
capacity: domain_capacity,
not_last_row,
l_first,
l_last,
Expand All @@ -106,22 +110,23 @@ impl<F: FftField> Domain<F> {
quotient
}

pub(crate) fn column(&self, mut evals: Vec<F>, hidden: bool) -> FieldColumn<F> {
let len = evals.len();
assert!(len <= self.capacity);
pub(crate) fn column(&self, mut values: Vec<F>, hidden: bool) -> FieldColumn<F> {
let payload_len = values.len();
debug_assert!(payload_len <= self.capacity);
values.resize(self.capacity, F::zero());
if self.hiding && hidden && !cfg!(feature = "test-vectors") {
evals.resize(self.capacity, F::zero());
evals.resize_with(self.domains.x1.size(), || {
F::rand(&mut getrandom_or_panic::getrandom_or_panic())
});
values.resize_with(
self.domains.x1.size(),
|| F::rand(&mut getrandom_or_panic()),
);
} else {
evals.resize(self.domains.x1.size(), F::zero());
values.resize(self.domains.x1.size(), F::zero());
}
self.domains.column_from_evals(evals, len)
self.domains.column_from_evals(values, payload_len)
}

pub fn private_column(&self, evals: Vec<F>) -> FieldColumn<F> {
self.column(evals, true)
pub fn private_column(&self, values: Vec<F>) -> FieldColumn<F> {
self.column(values, true)
}

// public column
Expand Down
16 changes: 12 additions & 4 deletions w3f-plonk-common/src/gadgets/booleanity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use ark_ff::{FftField, Field, Zero};
use ark_poly::univariate::DensePolynomial;
use ark_poly::{Evaluations, GeneralEvaluationDomain};
use ark_poly::{Evaluations, GeneralEvaluationDomain, Polynomial};

use ark_std::{vec, vec::Vec};

Expand All @@ -23,9 +23,17 @@ impl<F: FftField> BitColumn<F> {
let col = domain.private_column(bits_as_field_elements);
Self { bits, col }
}

pub fn as_poly(&self) -> &DensePolynomial<F> {
self.col.as_poly()
}

pub fn evaluate(&self, z: &F) -> F {
self.as_poly().evaluate(z)
}
}

impl<F: FftField> Column<F> for BitColumn<F> {
impl<F: FftField> Column<F, bool> for BitColumn<F> {
fn domain(&self) -> GeneralEvaluationDomain<F> {
self.col.domain()
}
Expand All @@ -34,8 +42,8 @@ impl<F: FftField> Column<F> for BitColumn<F> {
self.col.domain_4x()
}

fn as_poly(&self) -> &DensePolynomial<F> {
self.col.as_poly()
fn payload(&self) -> &[bool] {
self.bits.as_slice()
}
}

Expand Down
5 changes: 3 additions & 2 deletions w3f-plonk-common/src/gadgets/column_sum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ pub struct ColumnSumEvals<F: Field> {

impl<F: FftField> ColumnSumPolys<F> {
pub fn init(col: 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());
// we need an extra slot to seed the partial sums acc with `0`.
debug_assert_eq!(col.payload_len(), domain.capacity - 1);
let partial_sums = Self::partial_sums(col.payload());
let mut acc = vec![F::zero()];
acc.extend(partial_sums);
let acc = domain.private_column(acc);
Expand Down
42 changes: 32 additions & 10 deletions w3f-plonk-common/src/gadgets/ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::gadgets::booleanity::BitColumn;
use crate::{Column, FieldColumn};
use ark_ec::{AffineRepr, CurveGroup};
use ark_ff::{FftField, Field};

use ark_poly::GeneralEvaluationDomain;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::marker::PhantomData;
use ark_std::vec::Vec;
Expand All @@ -14,7 +14,6 @@ pub mod te_doubling;

// A vec of affine points from the prime-order subgroup of the curve whose base field enables FFTs,
// and its convenience representation as columns of coordinates over the curve's base field.

#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
pub struct AffineColumn<F: FftField, P: AffineRepr<BaseField = F>> {
points: Vec<P>,
Expand Down Expand Up @@ -43,6 +42,20 @@ impl<F: FftField, P: AffineRepr<BaseField = F>> AffineColumn<F, P> {
}
}

impl<F: FftField, P: AffineRepr<BaseField = F>> Column<F, P> for AffineColumn<F, P> {
fn domain(&self) -> GeneralEvaluationDomain<F> {
self.xs.domain()
}

fn domain_4x(&self) -> GeneralEvaluationDomain<F> {
self.xs.domain_4x()
}

fn payload(&self) -> &[P] {
&self.points
}
}

// Conditional affine addition:
// if the bit is set for a point, add the point to the acc and store,
// otherwise copy the acc value
Expand All @@ -53,7 +66,6 @@ pub struct CondAdd<F: FftField, P: AffineRepr<BaseField = F>> {
not_last: FieldColumn<F>,
// Accumulates the (conditional) rolling sum of the points
pub acc: AffineColumn<F, P>,
pub result: P,
}

impl<F, P: AffineRepr<BaseField = F>> CondAdd<F, P>
Expand All @@ -70,8 +82,8 @@ where
seed: P,
domain: &Domain<F>,
) -> Self {
assert_eq!(bitmask.bits.len(), domain.capacity - 1);
// assert_eq!(points.points.len(), domain.capacity - 1); //TODO
debug_assert_eq!(bitmask.payload_len(), domain.capacity - 1);
debug_assert_eq!(points.payload_len(), domain.capacity - 1);
let not_last = domain.not_last_row.clone();
let mut projective_acc = seed.into_group();
let projective_points: Vec<_> = bitmask
Expand All @@ -88,17 +100,13 @@ where
let mut acc = Vec::with_capacity(projective_points.len() + 1);
acc.push(seed);
acc.extend(P::Group::normalize_batch(&projective_points));
let init_plus_result = acc.last().unwrap();
let result = init_plus_result.into_group() - seed.into_group();
let result = result.into_affine();
let acc = AffineColumn::private_column(acc, domain);

debug_assert_eq!(acc.payload_len(), domain.capacity);
Self {
bitmask,
points,
acc,
not_last,
result,
}
}

Expand All @@ -111,6 +119,20 @@ where
_phantom: PhantomData,
}
}

pub fn seed(&self) -> P {
self.acc.payload()[0]
}

pub fn seed_plus_sum(&self) -> P {
let len = self.acc.payload_len();
self.acc.payload()[len - 1]
}

pub fn result(&self) -> P {
let sum = self.seed_plus_sum() - self.seed();
sum.into_affine()
}
}

pub struct CondAddValues<F: Field, P: AffineRepr<BaseField = F>> {
Expand Down
4 changes: 2 additions & 2 deletions w3f-plonk-common/src/gadgets/fixed_cells.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct FixedCellsValues<F: Field> {

impl<F: FftField> FixedCells<F> {
pub fn init(col: FieldColumn<F>, domain: &Domain<F>) -> Self {
assert_eq!(col.len, domain.capacity);
debug_assert_eq!(col.payload_len(), domain.capacity);
let l_first = domain.l_first.clone();
let l_last = domain.l_last.clone();
Self {
Expand All @@ -35,7 +35,7 @@ impl<F: FftField> FixedCells<F> {
}

pub fn constraints(&self) -> Vec<Evaluations<F>> {
let domain_capacity = self.col.len; // that's an ugly way to learn the capacity, but we've asserted it above.
let domain_capacity = self.col.payload_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]
Expand Down
7 changes: 4 additions & 3 deletions w3f-plonk-common/src/gadgets/inner_prod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ pub struct InnerProdValues<F: Field> {

impl<F: FftField> InnerProd<F> {
pub fn init(a: FieldColumn<F>, b: FieldColumn<F>, domain: &Domain<F>) -> Self {
assert_eq!(a.len, domain.capacity - 1); // last element is not constrained
assert_eq!(b.len, domain.capacity - 1); // last element is not constrained
let inner_prods = Self::partial_inner_prods(a.vals(), b.vals());
// we need an extra slot to seed the partial inner products acc with `0`.
assert_eq!(a.payload_len(), domain.capacity - 1);
assert_eq!(b.payload_len(), domain.capacity - 1);
let inner_prods = Self::partial_inner_prods(a.payload(), b.payload());
let mut acc = vec![F::zero()];
acc.extend(inner_prods);
let acc = domain.private_column(acc);
Expand Down
31 changes: 17 additions & 14 deletions w3f-plonk-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,24 @@ pub mod test_helpers;
pub mod transcript;
pub mod verifier;

pub trait Column<F: FftField> {
pub trait Column<F: FftField, V> {
fn domain(&self) -> GeneralEvaluationDomain<F>;
fn domain_4x(&self) -> GeneralEvaluationDomain<F>;
fn as_poly(&self) -> &DensePolynomial<F>;
fn size(&self) -> usize {
self.domain().size()
}
fn evaluate(&self, z: &F) -> F {
self.as_poly().evaluate(z)
fn payload(&self) -> &[V];
fn payload_len(&self) -> usize {
self.payload().len()
}
}

#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
pub struct FieldColumn<F: FftField> {
// actual (constrained) len of the input in evaluation form
pub len: usize,
pub poly: DensePolynomial<F>,
pub evals: Evaluations<F>,
pub evals_4x: Evaluations<F>,
// We require all the evaluations padded to the domain size
// (as we need to add blinding cells aka zk_rows) at the end of the vector.
// `payload_len` keeps the original length of the data.
payload_len: usize,
}

impl<F: FftField> FieldColumn<F> {
Expand All @@ -46,12 +45,16 @@ impl<F: FftField> FieldColumn<F> {
Evaluations::from_vec_and_domain(evals_4x, self.domain_4x())
}

pub fn vals(&self) -> &[F] {
&self.evals.evals[..self.len]
pub fn as_poly(&self) -> &DensePolynomial<F> {
&self.poly
}

pub fn evaluate(&self, z: &F) -> F {
self.as_poly().evaluate(z)
}
}

impl<F: FftField> Column<F> for FieldColumn<F> {
impl<F: FftField> Column<F, F> for FieldColumn<F> {
fn domain(&self) -> GeneralEvaluationDomain<F> {
self.evals.domain()
}
Expand All @@ -60,8 +63,8 @@ impl<F: FftField> Column<F> for FieldColumn<F> {
self.evals_4x.domain()
}

fn as_poly(&self) -> &DensePolynomial<F> {
&self.poly
fn payload(&self) -> &[F] {
&self.evals.evals[..self.payload_len]
}
}

Expand Down
Loading
Loading