diff --git a/src/field/fft.rs b/src/field/fft.rs index 96f19857..17c29184 100644 --- a/src/field/fft.rs +++ b/src/field/fft.rs @@ -219,13 +219,17 @@ mod tests { #[test] fn fft_and_ifft() { type F = GoldilocksField; - let degree = 200; - let degree_padded = log2_ceil(degree); - let mut coefficients = Vec::new(); - for i in 0..degree { - coefficients.push(F::from_canonical_usize(i * 1337 % 100)); - } - let coefficients = PolynomialCoeffs::new_padded(coefficients); + let degree = 200usize; + let degree_padded = degree.next_power_of_two(); + + // Create a vector of coeffs; the first degree of them are + // "random", the last degree_padded-degree of them are zero. + let coeffs = (0..degree) + .map(|i| F::from_canonical_usize(i * 1337 % 100)) + .chain(std::iter::repeat(F::ZERO).take(degree_padded - degree)) + .collect::>(); + assert_eq!(coeffs.len(), degree_padded); + let coefficients = PolynomialCoeffs { coeffs }; let points = fft(&coefficients); assert_eq!(points, evaluate_naive(&coefficients)); diff --git a/src/field/packed_avx2/packed_prime_field.rs b/src/field/packed_avx2/packed_prime_field.rs index ed87f347..b892da4a 100644 --- a/src/field/packed_avx2/packed_prime_field.rs +++ b/src/field/packed_avx2/packed_prime_field.rs @@ -43,13 +43,6 @@ impl PackedPrimeField { let ptr = (&self.0).as_ptr().cast::<__m256i>(); unsafe { _mm256_loadu_si256(ptr) } } - - /// Addition that assumes x + y < 2^64 + F::ORDER. May return incorrect results if this - /// condition is not met, hence it is marked unsafe. - #[inline] - pub unsafe fn add_canonical_u64(&self, rhs: __m256i) -> Self { - Self::new(add_canonical_u64::(self.get(), rhs)) - } } impl Add for PackedPrimeField { @@ -293,14 +286,6 @@ unsafe fn canonicalize_s(x_s: __m256i) -> __m256i { _mm256_add_epi64(x_s, wrapback_amt) } -/// Addition that assumes x + y < 2^64 + F::ORDER. -#[inline] -unsafe fn add_canonical_u64(x: __m256i, y: __m256i) -> __m256i { - let y_s = shift(y); - let res_s = add_no_canonicalize_64_64s_s::(x, y_s); - shift(res_s) -} - #[inline] unsafe fn add(x: __m256i, y: __m256i) -> __m256i { let y_s = shift(y); diff --git a/src/gadgets/nonnative.rs b/src/gadgets/nonnative.rs index fd883e5d..84691421 100644 --- a/src/gadgets/nonnative.rs +++ b/src/gadgets/nonnative.rs @@ -96,6 +96,7 @@ impl, const D: usize> CircuitBuilder { } } + #[allow(dead_code)] fn reduce_nonnative( &mut self, x: &ForeignFieldTarget, diff --git a/src/gadgets/permutation.rs b/src/gadgets/permutation.rs index c60eda7d..37169514 100644 --- a/src/gadgets/permutation.rs +++ b/src/gadgets/permutation.rs @@ -3,7 +3,6 @@ use std::marker::PhantomData; use crate::field::field_types::RichField; use crate::field::{extension_field::Extendable, field_types::Field}; -use crate::gates::switch::SwitchGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness}; diff --git a/src/hash/hashing.rs b/src/hash/hashing.rs index d031ebbb..39b3f51e 100644 --- a/src/hash/hashing.rs +++ b/src/hash/hashing.rs @@ -15,6 +15,7 @@ pub const SPONGE_WIDTH: usize = SPONGE_RATE + SPONGE_CAPACITY; pub(crate) const HASH_FAMILY: HashFamily = HashFamily::Poseidon; pub(crate) enum HashFamily { + #[allow(dead_code)] GMiMC, Poseidon, } diff --git a/src/hash/merkle_proofs.rs b/src/hash/merkle_proofs.rs index b9381ed1..7b766895 100644 --- a/src/hash/merkle_proofs.rs +++ b/src/hash/merkle_proofs.rs @@ -54,6 +54,7 @@ pub(crate) fn verify_merkle_proof( impl, const D: usize> CircuitBuilder { /// Verifies that the given leaf data is present at the given index in the Merkle tree with the /// given cap. The index is given by it's little-endian bits. + #[cfg(test)] pub(crate) fn verify_merkle_proof( &mut self, leaf_data: Vec, diff --git a/src/hash/poseidon.rs b/src/hash/poseidon.rs index 4450e659..03dce1f3 100644 --- a/src/hash/poseidon.rs +++ b/src/hash/poseidon.rs @@ -627,6 +627,7 @@ where } } +#[cfg(test)] pub(crate) mod test_helpers { use crate::field::field_types::Field; use crate::hash::poseidon::Poseidon; diff --git a/src/lib.rs b/src/lib.rs index 3ed9f747..46db2cf5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,7 @@ +#![allow(incomplete_features)] +#![allow(const_evaluatable_unchecked)] #![feature(asm)] +#![feature(asm_sym)] #![feature(destructuring_assignment)] #![feature(generic_const_exprs)] #![feature(specialization)] diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 3197b4e0..e24a5c6f 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -15,7 +15,7 @@ use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; -use crate::plonk::proof::ProofWithPublicInputs; +use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; use crate::plonk::prover::prove; use crate::plonk::verifier::verify; use crate::util::marking::MarkedTargets; @@ -57,7 +57,7 @@ impl CircuitConfig { } /// A typical recursion config, without zero-knowledge, targeting ~100 bit security. - pub(crate) fn standard_recursion_config() -> Self { + pub fn standard_recursion_config() -> Self { Self { num_wires: 135, num_routed_wires: 80, @@ -76,7 +76,7 @@ impl CircuitConfig { } } - pub(crate) fn standard_recursion_zk_config() -> Self { + pub fn standard_recursion_zk_config() -> Self { CircuitConfig { zero_knowledge: true, ..Self::standard_recursion_config() @@ -104,6 +104,13 @@ impl, const D: usize> CircuitData { pub fn verify(&self, proof_with_pis: ProofWithPublicInputs) -> Result<()> { verify(proof_with_pis, &self.verifier_only, &self.common) } + + pub fn verify_compressed( + &self, + compressed_proof_with_pis: CompressedProofWithPublicInputs, + ) -> Result<()> { + compressed_proof_with_pis.verify(&self.verifier_only, &self.common) + } } /// Circuit data required by the prover. This may be thought of as a proving key, although it @@ -140,6 +147,13 @@ impl, const D: usize> VerifierCircuitData { pub fn verify(&self, proof_with_pis: ProofWithPublicInputs) -> Result<()> { verify(proof_with_pis, &self.verifier_only, &self.common) } + + pub fn verify_compressed( + &self, + compressed_proof_with_pis: CompressedProofWithPublicInputs, + ) -> Result<()> { + compressed_proof_with_pis.verify(&self.verifier_only, &self.common) + } } /// Circuit data required by the prover, but not the verifier. diff --git a/src/plonk/plonk_common.rs b/src/plonk/plonk_common.rs index 6b84886d..5be13740 100644 --- a/src/plonk/plonk_common.rs +++ b/src/plonk/plonk_common.rs @@ -42,17 +42,6 @@ impl PlonkPolynomials { index: 3, blinding: true, }; - - #[cfg(test)] - pub fn polynomials(i: usize) -> PolynomialsIndexBlinding { - match i { - 0 => Self::CONSTANTS_SIGMAS, - 1 => Self::WIRES, - 2 => Self::ZS_PARTIAL_PRODUCTS, - 3 => Self::QUOTIENT, - _ => panic!("There are only 4 sets of polynomials in Plonk."), - } - } } /// Evaluate the polynomial which vanishes on any multiplicative subgroup of a given order `n`. diff --git a/src/plonk/proof.rs b/src/plonk/proof.rs index ce1207cd..815f807d 100644 --- a/src/plonk/proof.rs +++ b/src/plonk/proof.rs @@ -161,12 +161,12 @@ impl, const D: usize> CompressedProofWithPublicInpu ) -> anyhow::Result> { let challenges = self.get_challenges(common_data)?; let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data); - let compressed_proof = + let decompressed_proof = self.proof .decompress(&challenges, fri_inferred_elements, common_data); Ok(ProofWithPublicInputs { public_inputs: self.public_inputs, - proof: compressed_proof, + proof: decompressed_proof, }) } @@ -177,13 +177,13 @@ impl, const D: usize> CompressedProofWithPublicInpu ) -> anyhow::Result<()> { let challenges = self.get_challenges(common_data)?; let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data); - let compressed_proof = + let decompressed_proof = self.proof .decompress(&challenges, fri_inferred_elements, common_data); verify_with_challenges( ProofWithPublicInputs { public_inputs: self.public_inputs, - proof: compressed_proof, + proof: decompressed_proof, }, challenges, verifier_data, @@ -346,6 +346,6 @@ mod tests { assert_eq!(proof, decompressed_compressed_proof); verify(proof, &data.verifier_only, &data.common)?; - compressed_proof.verify(&data.verifier_only, &data.common) + data.verify_compressed(compressed_proof) } } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 1dd17cb8..3f8e607d 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -237,7 +237,7 @@ fn wires_permutation_partial_products_and_zs, const let degree = common_data.quotient_degree_factor; let subgroup = &prover_data.subgroup; let k_is = &common_data.k_is; - let (num_prods, final_num_prod) = common_data.num_partial_products; + let (num_prods, _final_num_prod) = common_data.num_partial_products; let all_quotient_chunk_products = subgroup .par_iter() .enumerate() diff --git a/src/polynomial/division.rs b/src/polynomial/division.rs index 6ac38676..b5dad629 100644 --- a/src/polynomial/division.rs +++ b/src/polynomial/division.rs @@ -1,7 +1,6 @@ -use crate::field::fft::{fft, ifft}; use crate::field::field_types::Field; use crate::polynomial::polynomial::PolynomialCoeffs; -use crate::util::{log2_ceil, log2_strict}; +use crate::util::log2_ceil; impl PolynomialCoeffs { /// Polynomial division. @@ -67,63 +66,6 @@ impl PolynomialCoeffs { } } - /// Takes a polynomial `a` in coefficient form, and divides it by `Z_H = X^n - 1`. - /// - /// This assumes `Z_H | a`, otherwise result is meaningless. - pub(crate) fn divide_by_z_h(&self, n: usize) -> PolynomialCoeffs { - let mut a = self.clone(); - - // TODO: Is this special case needed? - if a.coeffs.iter().all(|p| *p == F::ZERO) { - return a; - } - - let g = F::MULTIPLICATIVE_GROUP_GENERATOR; - let mut g_pow = F::ONE; - // Multiply the i-th coefficient of `a` by `g^i`. Then `new_a(w^j) = old_a(g.w^j)`. - a.coeffs.iter_mut().for_each(|x| { - *x *= g_pow; - g_pow *= g; - }); - - let root = F::primitive_root_of_unity(log2_strict(a.len())); - // Equals to the evaluation of `a` on `{g.w^i}`. - let mut a_eval = fft(&a); - // Compute the denominators `1/(g^n.w^(n*i) - 1)` using batch inversion. - let denominator_g = g.exp_u64(n as u64); - let root_n = root.exp_u64(n as u64); - let mut root_pow = F::ONE; - let denominators = (0..a_eval.len()) - .map(|i| { - if i != 0 { - root_pow *= root_n; - } - denominator_g * root_pow - F::ONE - }) - .collect::>(); - let denominators_inv = F::batch_multiplicative_inverse(&denominators); - // Divide every element of `a_eval` by the corresponding denominator. - // Then, `a_eval` is the evaluation of `a/Z_H` on `{g.w^i}`. - a_eval - .values - .iter_mut() - .zip(denominators_inv.iter()) - .for_each(|(x, &d)| { - *x *= d; - }); - // `p` is the interpolating polynomial of `a_eval` on `{w^i}`. - let mut p = ifft(&a_eval); - // We need to scale it by `g^(-i)` to get the interpolating polynomial of `a_eval` on `{g.w^i}`, - // a.k.a `a/Z_H`. - let g_inv = g.inverse(); - let mut g_inv_pow = F::ONE; - p.coeffs.iter_mut().for_each(|x| { - *x *= g_inv_pow; - g_inv_pow *= g_inv; - }); - p - } - /// Let `self=p(X)`, this returns `(p(X)-p(z))/(X-z)` and `p(z)`. /// See https://en.wikipedia.org/wiki/Horner%27s_method pub(crate) fn divide_by_linear(&self, z: F) -> (PolynomialCoeffs, F) { @@ -189,34 +131,6 @@ mod tests { use crate::field::goldilocks_field::GoldilocksField; use crate::polynomial::polynomial::PolynomialCoeffs; - #[test] - fn zero_div_z_h() { - type F = GoldilocksField; - let zero = PolynomialCoeffs::::zero(16); - let quotient = zero.divide_by_z_h(4); - assert_eq!(quotient, zero); - } - - #[test] - fn division_by_z_h() { - type F = GoldilocksField; - let zero = F::ZERO; - let three = F::from_canonical_u64(3); - let four = F::from_canonical_u64(4); - let five = F::from_canonical_u64(5); - let six = F::from_canonical_u64(6); - - // a(x) = Z_4(x) q(x), where - // a(x) = 3 x^7 + 4 x^6 + 5 x^5 + 6 x^4 - 3 x^3 - 4 x^2 - 5 x - 6 - // Z_4(x) = x^4 - 1 - // q(x) = 3 x^3 + 4 x^2 + 5 x + 6 - let a = PolynomialCoeffs::new(vec![-six, -five, -four, -three, six, five, four, three]); - let q = PolynomialCoeffs::new(vec![six, five, four, three, zero, zero, zero, zero]); - - let computed_q = a.divide_by_z_h(4); - assert_eq!(computed_q, q); - } - #[test] #[ignore] fn test_division_by_linear() { diff --git a/src/polynomial/polynomial.rs b/src/polynomial/polynomial.rs index 107d7a7b..a021ecd2 100644 --- a/src/polynomial/polynomial.rs +++ b/src/polynomial/polynomial.rs @@ -24,10 +24,6 @@ impl PolynomialValues { PolynomialValues { values } } - pub(crate) fn zero(len: usize) -> Self { - Self::new(vec![F::ZERO; len]) - } - /// The number of values stored. pub(crate) fn len(&self) -> usize { self.values.len() @@ -88,14 +84,6 @@ impl PolynomialCoeffs { PolynomialCoeffs { coeffs } } - /// Create a new polynomial with its coefficient list padded to the next power of two. - pub(crate) fn new_padded(mut coeffs: Vec) -> Self { - while !coeffs.len().is_power_of_two() { - coeffs.push(F::ZERO); - } - PolynomialCoeffs { coeffs } - } - pub(crate) fn empty() -> Self { Self::new(Vec::new()) } @@ -104,10 +92,6 @@ impl PolynomialCoeffs { Self::new(vec![F::ZERO; len]) } - pub(crate) fn one() -> Self { - Self::new(vec![F::ONE]) - } - pub(crate) fn is_zero(&self) -> bool { self.coeffs.iter().all(|x| x.is_zero()) } @@ -538,34 +522,6 @@ mod tests { } } - #[test] - fn test_division_by_z_h() { - type F = GoldilocksField; - let mut rng = thread_rng(); - let a_deg = rng.gen_range(1..10_000); - let n = rng.gen_range(1..a_deg); - let mut a = PolynomialCoeffs::new(F::rand_vec(a_deg)); - a.trim(); - let z_h = { - let mut z_h_vec = vec![F::ZERO; n + 1]; - z_h_vec[n] = F::ONE; - z_h_vec[0] = F::NEG_ONE; - PolynomialCoeffs::new(z_h_vec) - }; - let m = &a * &z_h; - let now = Instant::now(); - let mut a_test = m.divide_by_z_h(n); - a_test.trim(); - println!("Division time: {:?}", now.elapsed()); - assert_eq!(a, a_test); - } - - #[test] - fn divide_zero_poly_by_z_h() { - let zero_poly = PolynomialCoeffs::::empty(); - zero_poly.divide_by_z_h(16); - } - // Test to see which polynomial division method is faster for divisions of the type // `(X^n - 1)/(X - a) #[test]