From 2bbcf17699264e4fea02f23f301eb47515e77d43 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 2 Aug 2021 14:17:42 +0200 Subject: [PATCH] Test `eval_unfiltered_*` functions --- src/gates/arithmetic.rs | 8 +++- src/gates/base_sum.rs | 9 +++- src/gates/constant.rs | 9 +++- src/gates/exponentiation.rs | 8 +++- src/gates/gate_testing.rs | 86 +++++++++++++++++++++++++++++++++++-- src/gates/gmimc.rs | 54 ++--------------------- src/gates/insertion.rs | 9 +++- src/gates/interpolation.rs | 9 +++- src/gates/noop.rs | 9 +++- src/gates/reducing.rs | 9 +++- src/iop/witness.rs | 13 ++++++ 11 files changed, 162 insertions(+), 61 deletions(-) diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 1a68bf83..73cf12bc 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -250,12 +250,18 @@ impl, const D: usize> SimpleGenerator for ArithmeticExtensio #[cfg(test)] mod tests { + use anyhow::Result; + use crate::field::crandall_field::CrandallField; use crate::gates::arithmetic::ArithmeticExtensionGate; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; #[test] fn low_degree() { test_low_degree::(ArithmeticExtensionGate) } + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(ArithmeticExtensionGate) + } } diff --git a/src/gates/base_sum.rs b/src/gates/base_sum.rs index 9885f270..7da26095 100644 --- a/src/gates/base_sum.rs +++ b/src/gates/base_sum.rs @@ -184,12 +184,19 @@ impl SimpleGenerator for BaseSplitGenerator { #[cfg(test)] mod tests { + use anyhow::Result; + use crate::field::crandall_field::CrandallField; use crate::gates::base_sum::BaseSumGate; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; #[test] fn low_degree() { test_low_degree::(BaseSumGate::<6>::new(11)) } + + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(BaseSumGate::<6>::new(11)) + } } diff --git a/src/gates/constant.rs b/src/gates/constant.rs index 826fc2c3..5fb98eb2 100644 --- a/src/gates/constant.rs +++ b/src/gates/constant.rs @@ -96,12 +96,19 @@ impl SimpleGenerator for ConstantGenerator { #[cfg(test)] mod tests { + use anyhow::Result; + use crate::field::crandall_field::CrandallField; use crate::gates::constant::ConstantGate; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; #[test] fn low_degree() { test_low_degree::(ConstantGate) } + + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(ConstantGate) + } } diff --git a/src/gates/exponentiation.rs b/src/gates/exponentiation.rs index a1a7d5cd..b956353e 100644 --- a/src/gates/exponentiation.rs +++ b/src/gates/exponentiation.rs @@ -261,6 +261,7 @@ impl, const D: usize> SimpleGenerator for ExponentiationGene mod tests { use std::marker::PhantomData; + use anyhow::Result; use rand::Rng; use crate::field::crandall_field::CrandallField; @@ -268,7 +269,7 @@ mod tests { use crate::field::field_types::Field; use crate::gates::exponentiation::ExponentiationGate; use crate::gates::gate::Gate; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::hash::hash_types::HashOut; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::EvaluationVars; @@ -302,6 +303,11 @@ mod tests { test_low_degree::(ExponentiationGate::new(config)); } + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(ExponentiationGate::new(CircuitConfig::large_config())) + } + #[test] fn test_gate_constraint() { type F = CrandallField; diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index d85ce784..824b1000 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -1,8 +1,14 @@ -use crate::field::extension_field::Extendable; +use anyhow::{ensure, Result}; + +use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::hash::hash_types::HashOut; -use crate::plonk::vars::EvaluationVars; +use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::iop::witness::PartialWitness; +use crate::plonk::circuit_builder::CircuitBuilder; +use crate::plonk::circuit_data::CircuitConfig; +use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::plonk::verifier::verify; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::util::{log2_ceil, transpose}; @@ -75,3 +81,77 @@ fn random_low_degree_values(rate_bits: usize) -> Vec { .fft() .values } + +pub(crate) fn test_eval_fns, G: Gate, const D: usize>( + gate: G, +) -> Result<()> { + // Test that `eval_unfiltered` and `eval_unfiltered_base` are coherent. + let wires_base = F::rand_vec(gate.num_wires()); + let constants_base = F::rand_vec(gate.num_constants()); + let wires = wires_base + .iter() + .map(|&x| F::Extension::from_basefield(x)) + .collect::>(); + let constants = constants_base + .iter() + .map(|&x| F::Extension::from_basefield(x)) + .collect::>(); + let public_inputs_hash = HashOut::rand(); + + let vars_base = EvaluationVarsBase { + local_constants: &constants_base, + local_wires: &wires_base, + public_inputs_hash: &public_inputs_hash, + }; + let vars = EvaluationVars { + local_constants: &constants, + local_wires: &wires, + public_inputs_hash: &public_inputs_hash, + }; + + let evals_base = gate.eval_unfiltered_base(vars_base); + let evals = gate.eval_unfiltered(vars); + ensure!( + evals + == evals_base + .into_iter() + .map(F::Extension::from_basefield) + .collect::>() + ); + + // Test that `eval_unfiltered` and `eval_unfiltered_recursively` are coherent. + let wires = F::Extension::rand_vec(gate.num_wires()); + let constants = F::Extension::rand_vec(gate.num_constants()); + + let config = CircuitConfig::large_config(); + let mut builder = CircuitBuilder::::new(config); + let mut pw = PartialWitness::new(); + + let wires_t = builder.add_virtual_extension_targets(wires.len()); + let constants_t = builder.add_virtual_extension_targets(constants.len()); + pw.set_extension_targets(&wires_t, &wires); + pw.set_extension_targets(&constants_t, &constants); + let public_inputs_hash_t = builder.add_virtual_hash(); + pw.set_hash_target(public_inputs_hash_t, public_inputs_hash); + + let vars = EvaluationVars { + local_constants: &constants, + local_wires: &wires, + public_inputs_hash: &HashOut { + elements: [F::ZERO; 4], + }, + }; + let evals = gate.eval_unfiltered(vars); + + let vars_t = EvaluationTargets { + local_constants: &constants_t, + local_wires: &wires_t, + public_inputs_hash: &public_inputs_hash_t, + }; + let evals_t = gate.eval_unfiltered_recursively(&mut builder, vars_t); + pw.set_extension_targets(&evals_t, &evals); + + let data = builder.build(); + let proof = data.prove(pw)?; + verify(proof, &data.verifier_only, &data.common) +} diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 04ee42bb..73de7956 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -333,17 +333,12 @@ mod tests { use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field_types::Field; use crate::gates::gate::Gate; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::gmimc::{GMiMCGate, W}; use crate::hash::gmimc::gmimc_permute_naive; - use crate::hash::hash_types::HashOut; use crate::iop::generator::generate_partial_witness; use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::vars::{EvaluationTargets, EvaluationVars}; - use crate::plonk::verifier::verify; #[test] fn generated_output() { @@ -398,52 +393,11 @@ mod tests { } #[test] - fn test_evals() -> Result<()> { + fn eval_fns() -> Result<()> { type F = CrandallField; - type FF = QuarticCrandallField; const R: usize = 101; - let config = CircuitConfig::large_config(); - let mut builder = CircuitBuilder::::new(config); - let mut pw = PartialWitness::::new(); let constants = Arc::new([F::TWO; R]); - type Gate = GMiMCGate; - let gate = Gate::new(constants); - - let wires = FF::rand_vec(Gate::end()); - let public_inputs_hash = &HashOut::rand(); - let vars = EvaluationVars { - local_constants: &[], - local_wires: &wires, - public_inputs_hash, - }; - - let ev = gate.eval_unfiltered(vars); - - let wires_t = builder.add_virtual_extension_targets(Gate::end()); - for i in 0..Gate::end() { - pw.set_extension_target(wires_t[i], wires[i]); - } - - let public_inputs_hash_t = builder.add_virtual_hash(); - pw.set_hash_target(public_inputs_hash_t, *public_inputs_hash); - - let vars_t = EvaluationTargets { - local_constants: &[], - local_wires: &wires_t, - public_inputs_hash: &public_inputs_hash_t, - }; - - let ev_t = gate.eval_unfiltered_recursively(&mut builder, vars_t); - - assert_eq!(ev.len(), ev_t.len()); - for (e, e_t) in ev.into_iter().zip(ev_t) { - let e_c = builder.constant_extension(e); - builder.assert_equal_extension(e_c, e_t); - } - - let data = builder.build(); - let proof = data.prove(pw)?; - - verify(proof, &data.verifier_only, &data.common) + let gate = GMiMCGate::::new(constants); + test_eval_fns(gate) } } diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index 0337c36b..c540b5c0 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -319,11 +319,13 @@ impl, const D: usize> SimpleGenerator for InsertionGenerator mod tests { use std::marker::PhantomData; + use anyhow::Result; + use crate::field::crandall_field::CrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field_types::Field; use crate::gates::gate::Gate; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::insertion::InsertionGate; use crate::hash::hash_types::HashOut; use crate::plonk::vars::EvaluationVars; @@ -352,6 +354,11 @@ mod tests { test_low_degree::(InsertionGate::new(4)); } + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(InsertionGate::new(4)) + } + #[test] fn test_gate_constraint() { type F = CrandallField; diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 88fb7d22..cd3e74a2 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -286,11 +286,13 @@ impl, const D: usize> SimpleGenerator for InterpolationGener mod tests { use std::marker::PhantomData; + use anyhow::Result; + use crate::field::crandall_field::CrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field_types::Field; use crate::gates::gate::Gate; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::interpolation::InterpolationGate; use crate::hash::hash_types::HashOut; use crate::plonk::vars::EvaluationVars; @@ -321,6 +323,11 @@ mod tests { test_low_degree::(InterpolationGate::new(4)); } + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(InterpolationGate::new(4)) + } + #[test] fn test_gate_constraint() { type F = CrandallField; diff --git a/src/gates/noop.rs b/src/gates/noop.rs index df97a449..bd99be21 100644 --- a/src/gates/noop.rs +++ b/src/gates/noop.rs @@ -56,12 +56,19 @@ impl, const D: usize> Gate for NoopGate { #[cfg(test)] mod tests { + use anyhow::Result; + use crate::field::crandall_field::CrandallField; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::noop::NoopGate; #[test] fn low_degree() { test_low_degree::(NoopGate) } + + #[test] + fn eval_fns() -> anyhow::Result<()> { + test_eval_fns::(NoopGate) + } } diff --git a/src/gates/reducing.rs b/src/gates/reducing.rs index 896bbd78..a87d8af9 100644 --- a/src/gates/reducing.rs +++ b/src/gates/reducing.rs @@ -213,12 +213,19 @@ impl, const D: usize> SimpleGenerator for ReducingGenerator< #[cfg(test)] mod tests { + use anyhow::Result; + use crate::field::crandall_field::CrandallField; - use crate::gates::gate_testing::test_low_degree; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::reducing::ReducingGate; #[test] fn low_degree() { test_low_degree::(ReducingGate::new(22)); } + + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(ReducingGate::new(22)) + } } diff --git a/src/iop/witness.rs b/src/iop/witness.rs index d004b888..df8010d9 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -115,6 +115,19 @@ impl PartialWitness { }); } + pub fn set_extension_targets( + &mut self, + ets: &[ExtensionTarget], + values: &[F::Extension], + ) where + F: Extendable, + { + debug_assert_eq!(ets.len(), values.len()); + ets.iter() + .zip(values) + .for_each(|(&et, &v)| self.set_extension_target(et, v)); + } + pub fn set_wire(&mut self, wire: Wire, value: F) { self.set_target(Target::Wire(wire), value) }