diff --git a/pasta-tree/src/lib.rs b/pasta-tree/src/lib.rs index e85f1ac..6cf3a94 100644 --- a/pasta-tree/src/lib.rs +++ b/pasta-tree/src/lib.rs @@ -86,7 +86,7 @@ fn piop_params, R: Rng>( h: G, rng: &mut R, ) -> PiopParams { - let domain = Domain::::new(domain_size, true); + let domain = Domain::::with_zk_rows(domain_size, 3); let seed = G::rand(rng); let padding = G::rand(rng); PiopParams::setup(domain, h, seed, padding) diff --git a/w3f-plonk-common/benches/plonk_common.rs b/w3f-plonk-common/benches/plonk_common.rs index 6186965..d6f91b2 100644 --- a/w3f-plonk-common/benches/plonk_common.rs +++ b/w3f-plonk-common/benches/plonk_common.rs @@ -16,10 +16,10 @@ fn bench_domain_creation(c: &mut Criterion) { for log_n in [9, 10, 12, 14] { let n = 1usize << log_n; group.bench_with_input(BenchmarkId::new("hiding", n), &n, |b, &n| { - b.iter(|| Domain::::new(n, true)); + b.iter(|| Domain::::with_zk_rows(n, 3)); }); group.bench_with_input(BenchmarkId::new("non_hiding", n), &n, |b, &n| { - b.iter(|| Domain::::new(n, false)); + b.iter(|| Domain::::no_zk(n)); }); } group.finish(); @@ -30,14 +30,14 @@ fn bench_field_column(c: &mut Criterion) { let mut group = c.benchmark_group("field_column"); for log_n in [9, 10, 12] { let n = 1usize << log_n; - let domain = Domain::::new(n, true); + let domain = Domain::::with_zk_rows(n, 3); let vals: Vec = random_vec(domain.capacity - 1, rng); group.bench_with_input( BenchmarkId::new("private_column", n), &(vals.clone(), &domain), |b, (vals, domain)| { - b.iter(|| domain.private_column(vals.clone())); + b.iter(|| domain.column(vals.clone())); }, ); @@ -62,7 +62,7 @@ fn bench_booleanity_gadget(c: &mut Criterion) { let mut group = c.benchmark_group("booleanity"); for log_n in [9, 10, 12] { let n = 1usize << log_n; - let domain = Domain::::new(n, true); + let domain = Domain::::with_zk_rows(n, 3); let bits = random_bitvec(domain.capacity - 1, 0.5, rng); let bit_col = BitColumn::init(bits, &domain); @@ -83,7 +83,7 @@ fn bench_inner_prod_gadget(c: &mut Criterion) { let mut group = c.benchmark_group("inner_prod"); for log_n in [9, 10, 12] { let n = 1usize << log_n; - let domain = Domain::::new(n, true); + let domain = Domain::::with_zk_rows(n, 3); let a: Vec = random_vec(domain.capacity - 1, rng); let b_vals: Vec = random_vec(domain.capacity - 1, rng); @@ -92,8 +92,8 @@ fn bench_inner_prod_gadget(c: &mut Criterion) { &(a.clone(), b_vals.clone(), &domain), |bench, (a, b_vals, domain)| { bench.iter(|| { - let a_col = domain.private_column(a.clone()); - let b_col = domain.private_column(b_vals.clone()); + let a_col = domain.column(a.clone()); + let b_col = domain.column(b_vals.clone()); InnerProd::::init(a_col, b_col, domain); }); }, @@ -128,7 +128,7 @@ fn bench_te_cond_add_gadget(c: &mut Criterion) { let mut group = c.benchmark_group("te_cond_add"); for log_n in [9, 10, 12] { let n = 1usize << log_n; - let domain = Domain::::new(n, true); + let domain = Domain::::with_zk_rows(n, 3); let seed = EdwardsAffine::generator(); let bitmask = random_bitvec(domain.capacity - 1, 0.5, rng); diff --git a/w3f-plonk-common/src/domain.rs b/w3f-plonk-common/src/domain.rs index ab6af0b..ef500e3 100644 --- a/w3f-plonk-common/src/domain.rs +++ b/w3f-plonk-common/src/domain.rs @@ -7,8 +7,6 @@ use ark_poly::{ use ark_std::{vec, vec::Vec}; use getrandom_or_panic::getrandom_or_panic; -pub const ZK_ROWS: usize = 3; - // Domains for performing calculations with constraint polynomials of degree up to 4. #[derive(Clone)] pub struct Domains { @@ -69,14 +67,14 @@ pub struct Domain { } impl Domain { - pub fn new(n: usize, hiding: bool) -> Self { - if hiding { - Self::with_zk_rows(n, ZK_ROWS) - } else { - Self::with_zk_rows(n, 0) - } + /// Returns a "non-blinding" domain of full `capacity = N`. + pub fn no_zk(n: usize) -> Self { + Self::with_zk_rows(n, 0) } + /// Returns a domain that blinds (column) polynomials. + /// The highest `zk_rows` evaluations (aka Lagrange coefficients) are set random. + /// After interpolation that is equivallent to adding `r(X).Z'(X)`, for a random `deg(r) = zk_rows - 1`. pub fn with_zk_rows(n: usize, zk_rows: usize) -> Self { let domains = Domains::new(n); let domain_size = domains.x1.size(); @@ -88,7 +86,7 @@ impl Domain { let l_last = l_i(last_row_index, domain_size); let l_last = domains.column_from_evals(l_last, 0); - let (zk_rows_prod, last_row) = compute_row_polys(domains.x1, zk_rows).unwrap(); + let (zk_rows_prod, last_row) = compute_row_polys(domains.x1, zk_rows); let not_last_row = domains.column_from_poly(last_row); Self { @@ -102,6 +100,18 @@ impl Domain { } } + #[cfg(test)] + pub const ZK_ROWS_TEST: usize = 3; + + #[cfg(test)] + pub fn test_domain(n: usize, hiding: bool) -> Self { + if hiding { + Self::with_zk_rows(n, Self::ZK_ROWS_TEST) + } else { + Self::with_zk_rows(n, 0) + } + } + pub fn is_hiding(&self) -> bool { self.zk_rows != 0 } @@ -176,7 +186,7 @@ fn elements_rev>(domain: D) -> impl Iterator } /// `Z(c) = X - c` -fn z(c: F) -> DensePolynomial { +fn z_poly(c: F) -> DensePolynomial { DensePolynomial::from_coefficients_vec(vec![-c, F::one()]) } @@ -184,19 +194,19 @@ fn one() -> DensePolynomial { DensePolynomial::from_coefficients_vec(vec![F::one()]) } -/// For a domain of size `N`, returns `(Z(X), (X - w^{N - zk_rows - 1}))`, -/// where `Z(X) = (X - w^{N-1}) * (X - w^{N-2}) * ... * (X - w^{N - zk_rows})`. +/// For a domain of size `N` returns the vanishing polynomial `Z` of its suffix, `deg(Z) = zk_rows`, +/// `Z(X) = (X - w^{N-1}) * (X - w^{N-2}) * ... * (X - w^{N-zk_rows})`, +/// and the following not included term `X - w^{N-zk_rows-1}`. fn compute_row_polys>( domain: D, zk_rows: usize, -) -> Option<(DensePolynomial, DensePolynomial)> { - if domain.size() < zk_rows + 1 { - return None; - } - let mut wis = elements_rev(domain).map(|wi| z(wi)); - let zk_rows_prod = wis.by_ref().take(zk_rows).fold(one(), |acc, x| acc * x); - let last_row = wis.by_ref().next().unwrap(); - Some((zk_rows_prod, last_row)) +) -> (DensePolynomial, DensePolynomial) { + assert!(domain.size() >= 1 + zk_rows, "0 domain"); + let ws_rev_iter = elements_rev(domain); // `w^{N-1},...,0 = w^N` + let mut z_polys = ws_rev_iter.map(|wi| z_poly(wi)); + let zk_rows_prod = z_polys.by_ref().take(zk_rows).fold(one(), |acc, x| acc * x); + let last_row = z_polys.next().unwrap(); + (zk_rows_prod, last_row) } pub struct EvaluatedDomain { @@ -268,7 +278,7 @@ mod tests { // let domain = GeneralEvaluationDomain::new(1024); let n = 1024; - let domain = Domain::new(n, hiding); + let domain = Domain::test_domain(n, hiding); let z = Fq::rand(rng); let domain_eval = domain.evaluate(z); assert_eq!(domain.l_first.poly.evaluate(&z), domain_eval.l_first); @@ -280,31 +290,32 @@ mod tests { } #[test] + #[should_panic(expected = "0 domain")] fn test_domain_zk_rows() { let log_n = 4; let n = 1 << log_n; let domain = Radix2EvaluationDomain::::new(n).unwrap(); let w = domain.group_gen(); - let (zk_rows_prod, last_row) = compute_row_polys(domain, 0).unwrap(); + let (zk_rows_prod, last_row) = compute_row_polys(domain, 0); assert_eq!(zk_rows_prod, one()); - assert_eq!(last_row, z(domain.group_gen_inv())); + assert_eq!(last_row, z_poly(domain.group_gen_inv())); let zk_rows = 3; - let (zk_rows_prod, last_row) = compute_row_polys(domain, zk_rows).unwrap(); + let (zk_rows_prod, last_row) = compute_row_polys(domain, zk_rows); assert_eq!(zk_rows_prod.degree(), zk_rows); let last_row_index = n - (zk_rows + 1); - assert_eq!(last_row, z(w.pow([last_row_index as u64]))); + assert_eq!(last_row, z_poly(w.pow([last_row_index as u64]))); let zk_rows = n - 1; - let (zk_rows_prod, last_row) = compute_row_polys(domain, zk_rows).unwrap(); - assert_eq!(last_row, z(Fq::one())); + let (zk_rows_prod, last_row) = compute_row_polys(domain, zk_rows); + assert_eq!(last_row, z_poly(Fq::one())); assert_eq!( zk_rows_prod * last_row, domain.vanishing_polynomial().into() ); let zk_rows = n; - assert!(compute_row_polys(domain, zk_rows).is_none()); + compute_row_polys(domain, zk_rows); } #[test] diff --git a/w3f-plonk-common/src/gadgets/column_sum.rs b/w3f-plonk-common/src/gadgets/column_sum.rs index 6978f1d..2926afa 100644 --- a/w3f-plonk-common/src/gadgets/column_sum.rs +++ b/w3f-plonk-common/src/gadgets/column_sum.rs @@ -110,7 +110,7 @@ mod tests { let log_n = 10; let n = 2usize.pow(log_n); - let domain = Domain::new(n, hiding); + let domain = Domain::test_domain(n, hiding); let col = random_vec(domain.capacity - 1, rng); let sum = col.iter().sum(); diff --git a/w3f-plonk-common/src/gadgets/ec/sw_cond_add.rs b/w3f-plonk-common/src/gadgets/ec/sw_cond_add.rs index a34769f..f5eb5b6 100644 --- a/w3f-plonk-common/src/gadgets/ec/sw_cond_add.rs +++ b/w3f-plonk-common/src/gadgets/ec/sw_cond_add.rs @@ -168,7 +168,7 @@ mod tests { let log_n = 10; let n = 2usize.pow(log_n); - let domain = Domain::new(n, hiding); + let domain = Domain::test_domain(n, hiding); let seed = SWAffine::generator(); let bitmask = random_bitvec(domain.capacity - 1, 0.5, rng); diff --git a/w3f-plonk-common/src/gadgets/ec/te_cond_add.rs b/w3f-plonk-common/src/gadgets/ec/te_cond_add.rs index 1a2e13d..6fa6405 100644 --- a/w3f-plonk-common/src/gadgets/ec/te_cond_add.rs +++ b/w3f-plonk-common/src/gadgets/ec/te_cond_add.rs @@ -170,7 +170,7 @@ mod tests { let log_n = 10; let n = 2usize.pow(log_n); - let domain = Domain::new(n, hiding); + let domain = Domain::test_domain(n, hiding); let seed = EdwardsAffine::generator(); let bitmask = random_bitvec(domain.capacity - 1, 0.5, rng); diff --git a/w3f-plonk-common/src/gadgets/ec/te_doubling.rs b/w3f-plonk-common/src/gadgets/ec/te_doubling.rs index f31c011..17bf1fa 100644 --- a/w3f-plonk-common/src/gadgets/ec/te_doubling.rs +++ b/w3f-plonk-common/src/gadgets/ec/te_doubling.rs @@ -169,7 +169,7 @@ mod tests { let log_n = 4; let n = 2usize.pow(log_n); - let domain = Domain::new(n, false); + let domain = Domain::test_domain(n, false); let p = EdwardsAffine::rand(rng); let gadget = Doubling::init(p, &domain); diff --git a/w3f-plonk-common/src/gadgets/inner_prod.rs b/w3f-plonk-common/src/gadgets/inner_prod.rs index ba8677a..cb460a9 100644 --- a/w3f-plonk-common/src/gadgets/inner_prod.rs +++ b/w3f-plonk-common/src/gadgets/inner_prod.rs @@ -106,7 +106,7 @@ mod tests { let log_n = 10; let n = 2usize.pow(log_n); - let domain = Domain::new(n, hiding); + let domain = Domain::test_domain(n, hiding); let a = random_vec(domain.capacity - 1, rng); let b = random_vec(domain.capacity - 1, rng); diff --git a/w3f-ring-proof/benches/ring_proof.rs b/w3f-ring-proof/benches/ring_proof.rs index 56f8158..e610969 100644 --- a/w3f-ring-proof/benches/ring_proof.rs +++ b/w3f-ring-proof/benches/ring_proof.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criteri use ark_bls12_381::Bls12_381; use ark_ec::CurveGroup; -use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, EdwardsAffine, Fq, Fr}; +use ark_ed_on_bls12_381_bandersnatch::{EdwardsAffine, Fq, Fr}; use ark_serialize::CanonicalSerialize; use ark_std::ops::Mul; use ark_std::rand::Rng; @@ -10,7 +10,6 @@ use ark_std::{test_rng, UniformRand}; use w3f_pcs::pcs::kzg::KZG; use w3f_pcs::pcs::PCS; -use w3f_plonk_common::domain::Domain; use w3f_plonk_common::test_helpers::random_vec; use w3f_ring_proof::ring_prover::RingProver; use w3f_ring_proof::ring_verifier::RingVerifier; @@ -21,14 +20,10 @@ type CS = KZG; fn setup( rng: &mut impl Rng, domain_size: usize, -) -> (>::Params, PiopParams) { +) -> (>::Params, PiopParams) { let setup_degree = 3 * domain_size; let pcs_params = CS::setup(setup_degree, rng); - let domain = Domain::new(domain_size, true); - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); - let piop_params = PiopParams::setup(domain, h, seed, padding); + let piop_params = PiopParams::rand(domain_size, rng); (pcs_params, piop_params) } @@ -37,13 +32,13 @@ fn make_transcript() -> ArkTranscript { } /// Get the Pedersen blinding base H from the PIOP params (first element of the power-of-2 multiples). -fn get_h(piop_params: &PiopParams) -> EdwardsAffine { +fn get_h(piop_params: &PiopParams) -> EdwardsAffine { piop_params.power_of_2_multiples_of_h()[0] } /// Generate a proof and its corresponding blinded public key. fn generate_proof( - piop_params: &PiopParams, + piop_params: &PiopParams, pcs_params: &>::Params, pks: &[EdwardsAffine], rng: &mut impl Rng, diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 065579f..77cee5b 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -155,13 +155,7 @@ mod tests { ) -> (CS::Params, PiopParams) { let setup_degree = 3 * domain_size; let pcs_params = CS::setup(setup_degree, rng); - - let domain = Domain::new(domain_size, true); - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); - let piop_params = PiopParams::setup(domain, h, seed, padding); - + let piop_params = PiopParams::rand(domain_size, rng); (pcs_params, piop_params) } diff --git a/w3f-ring-proof/src/piop/params.rs b/w3f-ring-proof/src/piop/params.rs index 81e8ad3..ae6e48a 100644 --- a/w3f-ring-proof/src/piop/params.rs +++ b/w3f-ring-proof/src/piop/params.rs @@ -1,12 +1,14 @@ use ark_ec::{AdditiveGroup, AffineRepr, CurveGroup}; use ark_ff::{BigInteger, One, PrimeField, Zero}; +use ark_std::rand::Rng; use ark_std::{vec, vec::Vec}; - use w3f_plonk_common::domain::Domain; use w3f_plonk_common::gadgets::ec::AffineColumn; use crate::piop::FixedColumns; +pub const ZK_ROWS: usize = 3; + /// Plonk Interactive Oracle Proofs (PIOP) parameters. #[derive(Clone)] pub struct PiopParams> { @@ -47,6 +49,14 @@ impl> PiopParams { } } + pub fn rand(domain_size: usize, rng: &mut R) -> Self { + let domain = Domain::with_zk_rows(domain_size, ZK_ROWS); + let h = G::rand(rng); + let seed = G::rand(rng); + let padding = G::rand(rng); + Self::setup(domain, h, seed, padding) + } + pub fn fixed_columns(&self, keys: &[G]) -> FixedColumns { let ring_selector = self.keyset_part_selector(); let ring_selector = self.domain.public_column(ring_selector); @@ -114,7 +124,7 @@ mod tests { let h = EdwardsAffine::rand(rng); let seed = EdwardsAffine::rand(rng); let padding = EdwardsAffine::rand(rng); - let domain = Domain::new(1024, false); + let domain = Domain::no_zk(1024); let params = PiopParams::::setup(domain, h, seed, padding); let t = Fr::rand(rng); diff --git a/w3f-ring-proof/src/ring.rs b/w3f-ring-proof/src/ring.rs index a69843f..32e40ce 100644 --- a/w3f-ring-proof/src/ring.rs +++ b/w3f-ring-proof/src/ring.rs @@ -10,7 +10,7 @@ use ark_std::vec::Vec; use w3f_pcs::pcs::kzg::urs::URS; use w3f_pcs::pcs::PcsParams; -use w3f_plonk_common::domain::ZK_ROWS; +use crate::piop::params::ZK_ROWS; use crate::PiopParams; @@ -246,12 +246,11 @@ impl> RingBuilderKey::setup(domain_size - 1, rng); let ring_builder_key = RingBuilderKey::from_srs(&pcs_params, domain_size); let srs = |range: Range| Ok(ring_builder_key.lis_in_g1[range].to_vec()); - - // piop params - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); - let domain = Domain::new(domain_size, true); - let piop_params = PiopParams::setup(domain, h, seed, padding); + let piop_params = PiopParams::rand(domain_size, rng); let mut ring = TestRing::empty(&piop_params, srs, ring_builder_key.g1); let (monimial_cx, monimial_cy) = get_monomial_commitment(&pcs_params, &piop_params, &[]); @@ -302,13 +295,7 @@ mod tests { let pcs_params = KZG::::setup(domain_size - 1, rng); let ring_builder_key = RingBuilderKey::from_srs(&pcs_params, domain_size); let srs = |range: Range| Ok(ring_builder_key.lis_in_g1[range].to_vec()); - - // piop params - let h = EdwardsAffine::rand(rng); - let seed = EdwardsAffine::rand(rng); - let padding = EdwardsAffine::rand(rng); - let domain = Domain::new(domain_size, true); - let piop_params = PiopParams::setup(domain, h, seed, padding); + let piop_params = PiopParams::rand(domain_size, rng); let ring = TestRing::empty(&piop_params, srs, ring_builder_key.g1); let same_ring = TestRing::with_keys(&piop_params, &[], &ring_builder_key);