From 139430c549497b03e2c2f5e48ce809f81cf75793 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 13 Jul 2021 09:15:16 +0200 Subject: [PATCH] Fixed GMiMC --- src/circuit_builder.rs | 2 +- src/circuit_data.rs | 12 ++++++-- src/gates/gate.rs | 3 ++ src/gates/gmimc.rs | 61 ++++++++++++++++++++++++++++++++++----- src/prover.rs | 11 ++++--- src/recursive_verifier.rs | 15 ++++++++-- src/util/marking.rs | 54 ++++++++++++++++++++++++++++++++++ src/util/mod.rs | 1 + src/vanishing_poly.rs | 10 +++++-- src/verifier.rs | 1 + 10 files changed, 150 insertions(+), 20 deletions(-) create mode 100644 src/util/marking.rs diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 1d386b9d..fb0da833 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -45,7 +45,7 @@ pub struct CircuitBuilder, const D: usize> { copy_constraints: Vec<(Target, Target)>, /// Generators used to generate the witness. - generators: Vec>>, + pub generators: Vec>>, constants_to_targets: HashMap, targets_to_constants: HashMap, diff --git a/src/circuit_data.rs b/src/circuit_data.rs index e03a6977..786b7d78 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -11,6 +11,7 @@ use crate::polynomial::commitment::ListPolynomialCommitment; use crate::proof::{Hash, HashTarget, Proof}; use crate::prover::prove; use crate::target::Target; +use crate::util::marking::MarkedTargets; use crate::verifier::verify; use crate::witness::PartialWitness; @@ -77,7 +78,14 @@ pub struct CircuitData, const D: usize> { impl, const D: usize> CircuitData { pub fn prove(&self, inputs: PartialWitness) -> Proof { - prove(&self.prover_only, &self.common, inputs) + prove(&self.prover_only, &self.common, inputs, vec![]) + } + pub fn prove_marked( + &self, + inputs: PartialWitness, + marked: Vec, + ) -> Proof { + prove(&self.prover_only, &self.common, inputs, marked) } pub fn verify(&self, proof: Proof) -> Result<()> { @@ -99,7 +107,7 @@ pub struct ProverCircuitData, const D: usize> { impl, const D: usize> ProverCircuitData { pub fn prove(&self, inputs: PartialWitness) -> Proof { - prove(&self.prover_only, &self.common, inputs) + prove(&self.prover_only, &self.common, inputs, vec![]) } } diff --git a/src/gates/gate.rs b/src/gates/gate.rs index cce665f9..49b610ba 100644 --- a/src/gates/gate.rs +++ b/src/gates/gate.rs @@ -83,6 +83,9 @@ pub trait Gate, const D: usize>: 'static + Send + Sync { let filter = compute_filter_recursively(builder, prefix, vars.local_constants); vars.remove_prefix(prefix); self.eval_unfiltered_recursively(builder, vars) + .into_iter() + .map(|c| builder.mul_extension(filter, c)) + .collect() } fn generators( diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 9f617043..4f23a46e 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -129,16 +129,14 @@ impl, const D: usize, const R: usize> Gate for GMiMCGate< let mut constraints = Vec::with_capacity(self.num_constraints()); let swap = vars.local_wires[Self::WIRE_SWAP]; - let one_ext = builder.one_extension(); - let not_swap = builder.sub_extension(swap, one_ext); - constraints.push(builder.mul_extension(swap, not_swap)); + constraints.push(builder.mul_sub_extension(swap, swap, swap)); let old_index_acc = vars.local_wires[Self::WIRE_INDEX_ACCUMULATOR_OLD]; let new_index_acc = vars.local_wires[Self::WIRE_INDEX_ACCUMULATOR_NEW]; // computed_new_index_acc = 2 * old_index_acc + swap let two = builder.two(); - let double_old_index_acc = builder.scalar_mul_ext(two, old_index_acc); - let computed_new_index_acc = builder.add_extension(double_old_index_acc, swap); + let two = builder.convert_to_ext(two); + let computed_new_index_acc = builder.mul_add_extension(two, old_index_acc, swap); constraints.push(builder.sub_extension(computed_new_index_acc, new_index_acc)); let mut state = Vec::with_capacity(12); @@ -168,8 +166,10 @@ impl, const D: usize, const R: usize> Gate for GMiMCGate< let constant = builder.constant_extension(self.constants[r].into()); let cubing_input = builder.add_many_extension(&[state[active], addition_buffer, constant]); - let square = builder.mul_extension(cubing_input, cubing_input); - let f = builder.mul_extension(square, cubing_input); + let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; + constraints.push(builder.sub_extension(cubing_input, cubing_input_wire)); + let square = builder.mul_extension(cubing_input_wire, cubing_input_wire); + let f = builder.mul_extension(square, cubing_input_wire); addition_buffer = builder.add_extension(addition_buffer, f); state[active] = builder.sub_extension(state[active], f); } @@ -316,8 +316,10 @@ mod tests { use std::convert::TryInto; use std::sync::Arc; + use crate::circuit_builder::CircuitBuilder; use crate::circuit_data::CircuitConfig; use crate::field::crandall_field::CrandallField; + use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field::Field; use crate::gates::gate_testing::test_low_degree; use crate::gates::gmimc::{GMiMCGate, W}; @@ -325,6 +327,8 @@ mod tests { use crate::gmimc::gmimc_permute_naive; use crate::permutation_argument::TargetPartition; use crate::target::Target; + use crate::vars::{EvaluationTargets, EvaluationVars}; + use crate::verifier::verify; use crate::wire::Wire; use crate::witness::PartialWitness; @@ -399,4 +403,47 @@ mod tests { let gate = Gate::with_constants(constants); test_low_degree(gate) } + + #[test] + fn test_evals() { + 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::with_constants(constants); + + let wires = FF::rand_vec(Gate::end()); + let vars = EvaluationVars { + local_constants: &[], + local_wires: &wires, + }; + + let ev = gate.0.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 vars_t = EvaluationTargets { + local_constants: &[], + local_wires: &wires_t, + }; + + let ev_t = gate.0.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.route_extension(e_c, e_t); + } + + let data = builder.build(); + let proof = data.prove(pw); + + verify(proof, &data.verifier_only, &data.common).unwrap(); + } } diff --git a/src/prover.rs b/src/prover.rs index 8194551f..397b0fea 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -12,6 +12,7 @@ use crate::polynomial::commitment::ListPolynomialCommitment; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::proof::Proof; use crate::timed; +use crate::util::marking::MarkedTargets; use crate::util::partial_products::partial_products; use crate::util::{log2_ceil, transpose}; use crate::vanishing_poly::eval_vanishing_poly_base; @@ -22,6 +23,7 @@ pub(crate) fn prove, const D: usize>( prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, inputs: PartialWitness, + marked: Vec, ) -> Proof { let fri_config = &common_data.config.fri_config; let config = &common_data.config; @@ -50,13 +52,10 @@ pub(crate) fn prove, const D: usize>( .unwrap(), // TODO: Change return value to `Result` and use `?` here. "to check copy constraints" ); - - if degree > 7 { - dbg!(witness.get_wire(8, 16)); - dbg!(witness.get_wire(8, 17)); - dbg!(witness.get_wire(8, 18)); - dbg!(witness.get_wire(8, 19)); + for m in marked { + m.display(&witness); } + let wires_values: Vec> = timed!( witness .wire_values diff --git a/src/recursive_verifier.rs b/src/recursive_verifier.rs index 33912663..205ddb91 100644 --- a/src/recursive_verifier.rs +++ b/src/recursive_verifier.rs @@ -7,6 +7,7 @@ use crate::field::field::Field; use crate::gates::gate::{GateRef, PrefixedGate}; use crate::plonk_challenger::RecursiveChallenger; use crate::proof::{HashTarget, ProofTarget}; +use crate::util::marking::MarkedTargets; use crate::util::scaling::ReducingFactorTarget; use crate::vanishing_poly::eval_vanishing_poly_recursively; use crate::vars::EvaluationTargets; @@ -22,6 +23,7 @@ impl, const D: usize> CircuitBuilder { inner_config: &CircuitConfig, inner_verifier_data: &VerifierCircuitTarget, inner_common_data: &CommonCircuitData, + marked: &mut Vec, ) { assert!(self.config.num_wires >= MIN_WIRES); assert!(self.config.num_wires >= MIN_ROUTED_WIRES); @@ -71,8 +73,14 @@ impl, const D: usize> CircuitBuilder { &betas, &gammas, &alphas, + marked, ); + marked.push(MarkedTargets { + name: "vanishing polys".into(), + targets: Box::new(vanishing_polys_zeta[0].clone()), + }); + // let quotient_polys_zeta = &proof.openings.quotient_polys; // let zeta_pow_deg = self.exp_u64_extension(zeta, 1 << inner_common_data.degree_bits as u64); // let z_h_zeta = self.sub_extension(zeta_pow_deg, one); @@ -318,6 +326,8 @@ mod tests { let config = CircuitConfig::large_config(); let mut builder = CircuitBuilder::::new(config); let zero = builder.zero(); + let hash = builder.hash_n_to_m(vec![zero], 2, true); + let z = builder.mul(hash[0], hash[1]); let data = builder.build(); ( data.prove(PartialWitness::new()), @@ -330,6 +340,7 @@ mod tests { let config = CircuitConfig::large_config(); let mut builder = CircuitBuilder::::new(config.clone()); let mut pw = PartialWitness::new(); + let mut marked = Vec::new(); let pt = proof_to_proof_target(&proof, &mut builder); set_proof_target(&proof, &pt, &mut pw); @@ -338,11 +349,11 @@ mod tests { }; pw.set_hash_target(inner_data.constants_sigmas_root, vd.constants_sigmas_root); - builder.add_recursive_verifier(pt, &config, &inner_data, &cd); + builder.add_recursive_verifier(pt, &config, &inner_data, &cd, &mut marked); dbg!(builder.num_gates()); let data = builder.build(); - let recursive_proof = data.prove(pw); + let recursive_proof = data.prove_marked(pw, marked); verify(recursive_proof, &data.verifier_only, &data.common).unwrap(); } diff --git a/src/util/marking.rs b/src/util/marking.rs new file mode 100644 index 00000000..e4a13499 --- /dev/null +++ b/src/util/marking.rs @@ -0,0 +1,54 @@ +use std::convert::TryInto; + +use crate::field::extension_field::target::ExtensionTarget; +use crate::field::field::Field; +use crate::proof::HashTarget; +use crate::target::Target; +use crate::witness::{PartialWitness, Witness}; + +pub trait Markable { + fn targets(&self) -> Vec; +} + +impl Markable for Target { + fn targets(&self) -> Vec { + vec![*self] + } +} + +impl Markable for ExtensionTarget { + fn targets(&self) -> Vec { + self.0.try_into().unwrap() + } +} + +impl Markable for HashTarget { + fn targets(&self) -> Vec { + self.elements.try_into().unwrap() + } +} + +impl Markable for Vec { + fn targets(&self) -> Vec { + self.iter().flat_map(|m| m.targets()).collect() + } +} + +pub struct MarkedTargets { + pub targets: Box, + pub name: String, +} + +impl MarkedTargets { + pub fn display(&self, wit: &Witness) { + let targets = self.targets.targets(); + println!("Values for {}:", self.name); + for &t in &targets { + match t { + Target::Wire(w) => println!("{}", wit.get_wire(w.gate, w.input)), + _ => println!("Not a wire."), + } + } + println!("End of values for {}", self.name); + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 85440d70..6fd0e562 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ +pub mod marking; pub mod partial_products; pub mod scaling; pub(crate) mod timing; diff --git a/src/vanishing_poly.rs b/src/vanishing_poly.rs index a5f63ac2..d1531051 100644 --- a/src/vanishing_poly.rs +++ b/src/vanishing_poly.rs @@ -7,6 +7,7 @@ use crate::gates::gate::{Gate, GateRef, PrefixedGate}; use crate::plonk_common; use crate::plonk_common::{eval_l_1_recursively, ZeroPolyOnCoset}; use crate::target::Target; +use crate::util::marking::MarkedTargets; use crate::util::partial_products::{check_partial_products, check_partial_products_recursively}; use crate::util::scaling::ReducingFactorTarget; use crate::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -94,7 +95,6 @@ pub(crate) fn eval_vanishing_poly, const D: usize>( constraint_terms, ] .concat(); - dbg!(&vanishing_terms); let alphas = &alphas.iter().map(|&a| a.into()).collect::>(); plonk_common::reduce_with_powers_multi(&vanishing_terms, alphas) @@ -233,6 +233,7 @@ pub fn evaluate_gate_constraints_recursively, const D: usize>( gates: &[PrefixedGate], num_gate_constraints: usize, vars: EvaluationTargets, + marked: &mut Vec, ) -> Vec> { let mut constraints = vec![builder.zero_extension(); num_gate_constraints]; for gate in gates { @@ -240,6 +241,10 @@ pub fn evaluate_gate_constraints_recursively, const D: usize>( .gate .0 .eval_filtered_recursively(builder, vars, &gate.prefix); + // marked.push(MarkedTargets { + // name: gate.gate.0.id(), + // targets: Box::new(gate_constraints.clone()), + // }); for (i, c) in gate_constraints.into_iter().enumerate() { constraints[i] = builder.add_extension(constraints[i], c); } @@ -263,6 +268,7 @@ pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( betas: &[Target], gammas: &[Target], alphas: &[Target], + marked: &mut Vec, ) -> Vec> { let max_degree = common_data.quotient_degree_factor; let (num_prods, final_num_prod) = common_data.num_partial_products; @@ -272,6 +278,7 @@ pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( &common_data.gates, common_data.num_gate_constraints, vars, + marked, ); // The L_1(x) (Z(x) - 1) vanishing terms. @@ -343,7 +350,6 @@ pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( constraint_terms, ] .concat(); - dbg!(&vanishing_terms); alphas .iter() diff --git a/src/verifier.rs b/src/verifier.rs index e1d6d967..6da5a2e2 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -56,6 +56,7 @@ pub(crate) fn verify, const D: usize>( &gammas, &alphas, ); + dbg!(vanishing_polys_zeta[0]); // Check each polynomial identity, of the form `vanishing(x) = Z_H(x) quotient(x)`, at zeta. let quotient_polys_zeta = &proof.openings.quotient_polys;