diff --git a/w3f-plonk-common/src/domain.rs b/w3f-plonk-common/src/domain.rs index a096cd9..07c12de 100644 --- a/w3f-plonk-common/src/domain.rs +++ b/w3f-plonk-common/src/domain.rs @@ -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; @@ -25,26 +25,28 @@ impl Domains { Self { x1, x4 } } - fn column_from_evals(&self, evals: Vec, len: usize) -> FieldColumn { + fn column_from_evals(&self, evals: Vec, constrained_len: usize) -> FieldColumn { assert_eq!(evals.len(), self.x1.size()); + assert!(constrained_len <= evals.len()); let evals = Evaluations::from_vec_and_domain(evals, self.x1); let poly = evals.interpolate_by_ref(); let evals_4x = poly.evaluate_over_domain_by_ref(self.x4); FieldColumn { - len, + constrained_len, poly, evals, evals_4x, } } - fn column_from_poly(&self, poly: DensePolynomial, len: usize) -> FieldColumn { + fn column_from_poly(&self, poly: DensePolynomial, constrained_len: usize) -> FieldColumn { assert!(poly.degree() < self.x1.size()); + assert!(constrained_len <= 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, + constrained_len, poly, evals, evals_4x, @@ -111,9 +113,10 @@ impl Domain { assert!(len <= self.capacity); 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()) - }); + evals.resize_with( + self.domains.x1.size(), + || F::rand(&mut getrandom_or_panic()), + ); } else { evals.resize(self.domains.x1.size(), F::zero()); } diff --git a/w3f-plonk-common/src/gadgets/booleanity.rs b/w3f-plonk-common/src/gadgets/booleanity.rs index ace75da..9f9aab3 100644 --- a/w3f-plonk-common/src/gadgets/booleanity.rs +++ b/w3f-plonk-common/src/gadgets/booleanity.rs @@ -26,6 +26,8 @@ impl BitColumn { } impl Column for BitColumn { + type T = bool; + fn domain(&self) -> GeneralEvaluationDomain { self.col.domain() } @@ -34,8 +36,18 @@ impl Column for BitColumn { self.col.domain_4x() } - fn as_poly(&self) -> &DensePolynomial { - self.col.as_poly() + fn constrained_len(&self) -> usize { + self.col.constrained_len() + } + + fn constrained_vals(&self) -> &[Self::T] { + &self.bits[0..self.constrained_len()] + } +} + +impl BitColumn { + pub fn evaluate(&self, z: &F) -> F { + self.col.evaluate(z) } } diff --git a/w3f-plonk-common/src/gadgets/column_sum.rs b/w3f-plonk-common/src/gadgets/column_sum.rs index 0e841ec..83a177f 100644 --- a/w3f-plonk-common/src/gadgets/column_sum.rs +++ b/w3f-plonk-common/src/gadgets/column_sum.rs @@ -35,8 +35,8 @@ pub struct ColumnSumEvals { impl ColumnSumPolys { pub fn init(col: FieldColumn, domain: &Domain) -> Self { - assert_eq!(col.len, domain.capacity - 1); // last element is not constrained - let partial_sums = Self::partial_sums(col.vals()); + assert_eq!(col.constrained_len(), domain.capacity - 1); // last element is not constrained + let partial_sums = Self::partial_sums(col.constrained_vals()); let mut acc = vec![F::zero()]; acc.extend(partial_sums); let acc = domain.private_column(acc); diff --git a/w3f-plonk-common/src/gadgets/ec/mod.rs b/w3f-plonk-common/src/gadgets/ec/mod.rs index 048548c..e39b65b 100644 --- a/w3f-plonk-common/src/gadgets/ec/mod.rs +++ b/w3f-plonk-common/src/gadgets/ec/mod.rs @@ -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; @@ -31,6 +31,7 @@ impl> AffineColumn { let ys = domain.column(ys, hidden); Self { points, xs, ys } } + pub fn private_column(points: Vec

, domain: &Domain) -> Self { Self::column(points, domain, true) } @@ -42,6 +43,32 @@ impl> AffineColumn { pub fn evaluate(&self, z: &F) -> (F, F) { (self.xs.evaluate(z), self.ys.evaluate(z)) } + + pub fn trim_to(&mut self, n: usize) { + assert!(n <= self.constrained_len()); + self.xs.constrained_len = n; + self.ys.constrained_len = n; + } +} + +impl> Column for AffineColumn { + type T = P; + + fn domain(&self) -> GeneralEvaluationDomain { + self.xs.domain() + } + + fn domain_4x(&self) -> GeneralEvaluationDomain { + self.xs.domain_4x() + } + + fn constrained_len(&self) -> usize { + self.xs.constrained_len() + } + + fn constrained_vals(&self) -> &[Self::T] { + &self.points[0..self.constrained_len()] + } } // Conditional affine addition: @@ -71,13 +98,13 @@ where seed: P, domain: &Domain, ) -> Self { - assert_eq!(bitmask.bits.len(), domain.capacity - 1); - // assert_eq!(points.points.len(), domain.capacity - 1); //TODO + assert_eq!(bitmask.constrained_len(), domain.capacity - 1); + assert_eq!(points.constrained_len(), domain.capacity - 1); let not_last = domain.not_last_row.clone(); let acc = bitmask - .bits + .constrained_vals() .iter() - .zip(points.points.iter()) + .zip(points.constrained_vals()) .scan(seed, |acc, (&b, point)| { if b { *acc = (*acc + point).into_affine(); diff --git a/w3f-plonk-common/src/gadgets/ec/te_doubling.rs b/w3f-plonk-common/src/gadgets/ec/te_doubling.rs index fe893cd..2892511 100644 --- a/w3f-plonk-common/src/gadgets/ec/te_doubling.rs +++ b/w3f-plonk-common/src/gadgets/ec/te_doubling.rs @@ -29,7 +29,7 @@ where F: FftField, { pub fn init(p: P, domain: &Domain) -> Self { - let doublings = Self::doublings_of(p, domain); + let doublings = Self::doublings_of(p, domain.capacity); let doublings = AffineColumn::public_column(doublings, domain); let not_last = domain.not_last_row.clone(); Self { @@ -38,11 +38,11 @@ where } } - pub fn doublings_of(p: P, domain: &Domain) -> Vec

{ + pub fn doublings_of(p: P, n: usize) -> Vec

{ let mut p = p.into_group(); - let mut doublings = Vec::with_capacity(domain.capacity); + let mut doublings = Vec::with_capacity(n); doublings.push(p); - for _ in 1..domain.capacity { + for _ in 1..n { p.double_in_place(); doublings.push(p); } diff --git a/w3f-plonk-common/src/gadgets/fixed_cells.rs b/w3f-plonk-common/src/gadgets/fixed_cells.rs index 56a9fd8..72883cb 100644 --- a/w3f-plonk-common/src/gadgets/fixed_cells.rs +++ b/w3f-plonk-common/src/gadgets/fixed_cells.rs @@ -24,7 +24,7 @@ pub struct FixedCellsValues { impl FixedCells { pub fn init(col: FieldColumn, domain: &Domain) -> Self { - assert_eq!(col.len, domain.capacity); + assert_eq!(col.constrained_len, domain.capacity); let l_first = domain.l_first.clone(); let l_last = domain.l_last.clone(); Self { @@ -35,7 +35,7 @@ impl FixedCells { } pub fn constraints(&self) -> Vec> { - 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.constrained_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] diff --git a/w3f-plonk-common/src/gadgets/inner_prod.rs b/w3f-plonk-common/src/gadgets/inner_prod.rs index f977912..54df870 100644 --- a/w3f-plonk-common/src/gadgets/inner_prod.rs +++ b/w3f-plonk-common/src/gadgets/inner_prod.rs @@ -24,9 +24,9 @@ pub struct InnerProdValues { impl InnerProd { pub fn init(a: FieldColumn, b: FieldColumn, domain: &Domain) -> 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()); + assert_eq!(a.constrained_len(), domain.capacity - 1); // last element is not constrained + assert_eq!(b.constrained_len(), domain.capacity - 1); // last element is not constrained + let inner_prods = Self::partial_inner_prods(a.constrained_vals(), b.constrained_vals()); let mut acc = vec![F::zero()]; acc.extend(inner_prods); let acc = domain.private_column(acc); diff --git a/w3f-plonk-common/src/lib.rs b/w3f-plonk-common/src/lib.rs index 87208d9..7194442 100644 --- a/w3f-plonk-common/src/lib.rs +++ b/w3f-plonk-common/src/lib.rs @@ -16,22 +16,24 @@ pub mod transcript; pub mod verifier; pub trait Column { + /// Type of a column cell. + type T; + /// Evaluation domain of the associated column polynomial `p`: + /// `p(w^i) = col[i]` for the domain generator `w`. fn domain(&self) -> GeneralEvaluationDomain; + /// Evaluation domain of constraint polynomials. fn domain_4x(&self) -> GeneralEvaluationDomain; - fn as_poly(&self) -> &DensePolynomial; - fn size(&self) -> usize { - self.domain().size() - } - fn evaluate(&self, z: &F) -> F { - self.as_poly().evaluate(z) - } + /// Length of the constrained prefix of the column. + /// Is either equal to `domain.capacity` or `domain.capacity - 1`. + fn constrained_len(&self) -> usize; + /// Values of the cells that are constrained. + fn constrained_vals(&self) -> &[Self::T]; } // #[derive(Clone, CanonicalSerialize, CanonicalDeserialize)] #[derive(Clone)] pub struct FieldColumn { - // actual (constrained) len of the input in evaluation form - pub len: usize, + constrained_len: usize, pub poly: DensePolynomial, pub evals: Evaluations, pub evals_4x: Evaluations, @@ -44,12 +46,18 @@ impl FieldColumn { 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 { + &self.poly + } + + pub fn evaluate(&self, z: &F) -> F { + self.poly.evaluate(z) } } impl Column for FieldColumn { + type T = F; + fn domain(&self) -> GeneralEvaluationDomain { self.evals.domain() } @@ -58,8 +66,12 @@ impl Column for FieldColumn { self.evals_4x.domain() } - fn as_poly(&self) -> &DensePolynomial { - &self.poly + fn constrained_len(&self) -> usize { + self.constrained_len + } + + fn constrained_vals(&self) -> &[Self::T] { + &self.evals.evals[..self.constrained_len] } } diff --git a/w3f-ring-proof/src/piop/mod.rs b/w3f-ring-proof/src/piop/mod.rs index a4d2c71..85976b1 100644 --- a/w3f-ring-proof/src/piop/mod.rs +++ b/w3f-ring-proof/src/piop/mod.rs @@ -13,7 +13,7 @@ use w3f_pcs::pcs::{Commitment, PcsParams, PCS}; pub(crate) use prover::PiopProver; pub(crate) use verifier::PiopVerifier; use w3f_plonk_common::gadgets::ec::AffineColumn; -use w3f_plonk_common::{Column, ColumnsCommited, ColumnsEvaluated, FieldColumn}; +use w3f_plonk_common::{ColumnsCommited, ColumnsEvaluated, FieldColumn}; use crate::ring::Ring; use crate::PiopParams; diff --git a/w3f-ring-proof/src/piop/prover.rs b/w3f-ring-proof/src/piop/prover.rs index 07267c3..bba9c46 100644 --- a/w3f-ring-proof/src/piop/prover.rs +++ b/w3f-ring-proof/src/piop/prover.rs @@ -18,7 +18,7 @@ use w3f_plonk_common::gadgets::fixed_cells::FixedCells; use w3f_plonk_common::gadgets::inner_prod::InnerProd; use w3f_plonk_common::gadgets::ProverGadget; use w3f_plonk_common::piop::ProverPiop; -use w3f_plonk_common::{Column, FieldColumn}; +use w3f_plonk_common::FieldColumn; // The 'table': columns representing the execution trace of the computation // and the constraints -- polynomials that vanish on every 2 consecutive rows. @@ -100,7 +100,7 @@ where &self, commit: Fun, ) -> Self::Commitments { - let bits = commit(self.bits.as_poly()); + let bits = commit(self.bits.col.as_poly()); let cond_add_acc = [ commit(self.cond_add.acc.xs.as_poly()), commit(self.cond_add.acc.ys.as_poly()), @@ -121,7 +121,7 @@ where self.points.xs.as_poly().clone(), self.points.ys.as_poly().clone(), self.ring_selector.as_poly().clone(), - self.bits.as_poly().clone(), + self.bits.col.as_poly().clone(), self.inner_prod.acc.as_poly().clone(), self.cond_add.acc.xs.as_poly().clone(), self.cond_add.acc.ys.as_poly().clone(), diff --git a/w3f-ring-vrf-snark/src/piop/cell_equality.rs b/w3f-ring-vrf-snark/src/piop/cell_equality.rs index 0e2f1c6..61e5fb6 100644 --- a/w3f-ring-vrf-snark/src/piop/cell_equality.rs +++ b/w3f-ring-vrf-snark/src/piop/cell_equality.rs @@ -6,7 +6,7 @@ use ark_std::{vec, vec::Vec}; use w3f_plonk_common::domain::Domain; use w3f_plonk_common::gadgets::VerifierGadget; -use w3f_plonk_common::FieldColumn; +use w3f_plonk_common::{Column, FieldColumn}; pub struct CellEqualityPolys { a: FieldColumn, @@ -22,8 +22,8 @@ pub struct CellEqualityEvals { impl CellEqualityPolys { pub fn init(a: FieldColumn, b: FieldColumn, domain: &Domain) -> Self { - assert_eq!(a.len, domain.capacity); - assert_eq!(b.len, domain.capacity); + assert_eq!(a.constrained_len(), domain.capacity); + assert_eq!(b.constrained_len(), domain.capacity); let a_last = a.evals.evals[domain.capacity - 1]; let b_last = b.evals.evals[domain.capacity - 1]; assert_eq!(a_last, b_last); diff --git a/w3f-ring-vrf-snark/src/piop/mod.rs b/w3f-ring-vrf-snark/src/piop/mod.rs index ca040cc..ff23210 100644 --- a/w3f-ring-vrf-snark/src/piop/mod.rs +++ b/w3f-ring-vrf-snark/src/piop/mod.rs @@ -13,7 +13,7 @@ use w3f_pcs::pcs::{Commitment, PcsParams, PCS}; pub(crate) use prover::PiopProver; pub(crate) use verifier::PiopVerifier; use w3f_plonk_common::gadgets::ec::AffineColumn; -use w3f_plonk_common::{Column, ColumnsCommited, ColumnsEvaluated}; +use w3f_plonk_common::{ColumnsCommited, ColumnsEvaluated}; use crate::PiopParams; diff --git a/w3f-ring-vrf-snark/src/piop/params.rs b/w3f-ring-vrf-snark/src/piop/params.rs index c275b65..1f2af63 100644 --- a/w3f-ring-vrf-snark/src/piop/params.rs +++ b/w3f-ring-vrf-snark/src/piop/params.rs @@ -64,7 +64,7 @@ impl> PiopParams { } fn doublings_of_g_col(&self) -> AffineColumn> { - let doublings_of_g = Doubling::doublings_of(self.g, &self.domain); + let doublings_of_g = Doubling::doublings_of(self.g, &self.domain.capacity - 1); AffineColumn::public_column(doublings_of_g, &self.domain) } diff --git a/w3f-ring-vrf-snark/src/piop/prover.rs b/w3f-ring-vrf-snark/src/piop/prover.rs index cc73f17..b90e8ec 100644 --- a/w3f-ring-vrf-snark/src/piop/prover.rs +++ b/w3f-ring-vrf-snark/src/piop/prover.rs @@ -20,7 +20,6 @@ use w3f_plonk_common::piop::ProverPiop; use crate::piop::cell_equality::CellEqualityPolys; use w3f_plonk_common::gadgets::column_sum::ColumnSumPolys; use w3f_plonk_common::gadgets::ec::te_doubling::Doubling; -use w3f_plonk_common::Column; /// The prover's private input is its secret key `sk`. /// The public inputs are: @@ -117,7 +116,10 @@ impl> PiopProver { ); let doublings_of_in_gadget = Doubling::init(vrf_in, &domain); - let doublings_of_in = doublings_of_in_gadget.doublings.clone(); + let mut doublings_of_in = doublings_of_in_gadget.doublings.clone(); + // The `doublings` gadget constrains the points in the column up to `domain.capacity`, + // but the `additions` gadget can't constrain the last point (due to the `seed` point). + doublings_of_in.trim_to(domain.capacity - 1); let out_from_in = CondAdd::init(sk_bits.clone(), doublings_of_in, params.seed, &domain); let out_from_in_x = FixedCells::init(out_from_in.acc.xs.clone(), &domain); let out_from_in_y = FixedCells::init(out_from_in.acc.ys.clone(), &domain); @@ -174,8 +176,8 @@ where &self, commit: Fun, ) -> Self::Commitments { - let sk_bits = commit(self.sk_bits.as_poly()); - let pk_index = commit(self.pk_index.as_poly()); + let sk_bits = commit(self.sk_bits.col.as_poly()); + let pk_index = commit(self.pk_index.col.as_poly()); let pk_from_sk = [ commit(self.pk_from_sk.acc.xs.as_poly()), commit(self.pk_from_sk.acc.ys.as_poly()), @@ -213,8 +215,8 @@ where self.pks.ys.as_poly().clone(), self.doublings_of_g.xs.as_poly().clone(), self.doublings_of_g.ys.as_poly().clone(), - self.sk_bits.as_poly().clone(), - self.pk_index.as_poly().clone(), + self.sk_bits.col.as_poly().clone(), + self.pk_index.col.as_poly().clone(), self.pk_from_sk.acc.xs.as_poly().clone(), self.pk_from_sk.acc.ys.as_poly().clone(), self.doublings_of_in_gadget.doublings.xs.as_poly().clone(),