Fix all lint warnings (#353)

* Suppress warnings about use of unstable compiler features.

* Remove unused functions.

* Refactor and remove PolynomialCoeffs::new_padded(); fix degree_padded.

Note that this fixes a minor mistake in the FFT testing code, where
`degree_padded` value was log2 of what it should have been, preventing
a testing loop from executing.

* Remove divide_by_z_h() and related test functions.

* Only compile check_{consistency,test_vectors} when testing.

* Move verify() to test module.

* Remove unused functions.

NB: Changed the config in the gadgets/arithmetic_extension.rs::tests
module which may change the test's meaning?

* Remove unused import.

* Mark GMiMC option as allowed 'dead code'.

* Fix missing feature.

* Remove unused functions.

* cargo fmt

* Mark variable as unused.

* Revert "Remove unused functions."

This reverts commit 99d2357f1c967fd9fd6cac63e1216d929888be72.

* Make config functions public.

* Mark 'reduce_nonnative()' as dead code for now.

* Revert "Move verify() to test module." Refactor to `verify_compressed`.

This reverts commit b426e810d033c642f54e25ebc4a8114491df5076.

* cargo fmt

* Reinstate `verify()` fn on `CompressedProofWithPublicInputs`.
This commit is contained in:
Hamish Ivey-Law 2021-11-16 21:18:27 +11:00 committed by GitHub
parent 4769efa4dd
commit 909a5c2392
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 42 additions and 174 deletions

View File

@ -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::<Vec<_>>();
assert_eq!(coeffs.len(), degree_padded);
let coefficients = PolynomialCoeffs { coeffs };
let points = fft(&coefficients);
assert_eq!(points, evaluate_naive(&coefficients));

View File

@ -43,13 +43,6 @@ impl<F: ReducibleAVX2> PackedPrimeField<F> {
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::<F>(self.get(), rhs))
}
}
impl<F: ReducibleAVX2> Add<Self> for PackedPrimeField<F> {
@ -293,14 +286,6 @@ unsafe fn canonicalize_s<F: PrimeField>(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<F: PrimeField>(x: __m256i, y: __m256i) -> __m256i {
let y_s = shift(y);
let res_s = add_no_canonicalize_64_64s_s::<F>(x, y_s);
shift(res_s)
}
#[inline]
unsafe fn add<F: PrimeField>(x: __m256i, y: __m256i) -> __m256i {
let y_s = shift(y);

View File

@ -96,6 +96,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
}
#[allow(dead_code)]
fn reduce_nonnative<FF: Field>(
&mut self,
x: &ForeignFieldTarget<FF>,

View File

@ -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};

View File

@ -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,
}

View File

@ -54,6 +54,7 @@ pub(crate) fn verify_merkle_proof<F: RichField>(
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// 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<Target>,

View File

@ -627,6 +627,7 @@ where
}
}
#[cfg(test)]
pub(crate) mod test_helpers {
use crate::field::field_types::Field;
use crate::hash::poseidon::Poseidon;

View File

@ -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)]

View File

@ -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<F: RichField + Extendable<D>, const D: usize> CircuitData<F, D> {
pub fn verify(&self, proof_with_pis: ProofWithPublicInputs<F, D>) -> Result<()> {
verify(proof_with_pis, &self.verifier_only, &self.common)
}
pub fn verify_compressed(
&self,
compressed_proof_with_pis: CompressedProofWithPublicInputs<F, D>,
) -> 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<F: RichField + Extendable<D>, const D: usize> VerifierCircuitData<F, D> {
pub fn verify(&self, proof_with_pis: ProofWithPublicInputs<F, D>) -> Result<()> {
verify(proof_with_pis, &self.verifier_only, &self.common)
}
pub fn verify_compressed(
&self,
compressed_proof_with_pis: CompressedProofWithPublicInputs<F, D>,
) -> Result<()> {
compressed_proof_with_pis.verify(&self.verifier_only, &self.common)
}
}
/// Circuit data required by the prover, but not the verifier.

View File

@ -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`.

View File

@ -161,12 +161,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CompressedProofWithPublicInpu
) -> anyhow::Result<ProofWithPublicInputs<F, D>> {
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<F: RichField + Extendable<D>, 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)
}
}

View File

@ -237,7 +237,7 @@ fn wires_permutation_partial_products_and_zs<F: RichField + Extendable<D>, 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()

View File

@ -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<F: Field> PolynomialCoeffs<F> {
/// Polynomial division.
@ -67,63 +66,6 @@ impl<F: Field> PolynomialCoeffs<F> {
}
}
/// 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<F> {
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::<Vec<_>>();
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>, 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::<F>::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() {

View File

@ -24,10 +24,6 @@ impl<F: Field> PolynomialValues<F> {
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<F: Field> PolynomialCoeffs<F> {
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<F>) -> 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<F: Field> PolynomialCoeffs<F> {
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::<GoldilocksField>::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]