Fixed GMiMC

This commit is contained in:
wborgeaud 2021-07-13 09:15:16 +02:00
parent ad24f5d4d1
commit 139430c549
10 changed files with 150 additions and 20 deletions

View File

@ -45,7 +45,7 @@ pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
copy_constraints: Vec<(Target, Target)>,
/// Generators used to generate the witness.
generators: Vec<Box<dyn WitnessGenerator<F>>>,
pub generators: Vec<Box<dyn WitnessGenerator<F>>>,
constants_to_targets: HashMap<F, Target>,
targets_to_constants: HashMap<Target, F>,

View File

@ -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<F: Extendable<D>, const D: usize> {
impl<F: Extendable<D>, const D: usize> CircuitData<F, D> {
pub fn prove(&self, inputs: PartialWitness<F>) -> Proof<F, D> {
prove(&self.prover_only, &self.common, inputs)
prove(&self.prover_only, &self.common, inputs, vec![])
}
pub fn prove_marked(
&self,
inputs: PartialWitness<F>,
marked: Vec<MarkedTargets>,
) -> Proof<F, D> {
prove(&self.prover_only, &self.common, inputs, marked)
}
pub fn verify(&self, proof: Proof<F, D>) -> Result<()> {
@ -99,7 +107,7 @@ pub struct ProverCircuitData<F: Extendable<D>, const D: usize> {
impl<F: Extendable<D>, const D: usize> ProverCircuitData<F, D> {
pub fn prove(&self, inputs: PartialWitness<F>) -> Proof<F, D> {
prove(&self.prover_only, &self.common, inputs)
prove(&self.prover_only, &self.common, inputs, vec![])
}
}

View File

@ -83,6 +83,9 @@ pub trait Gate<F: Extendable<D>, 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(

View File

@ -129,16 +129,14 @@ impl<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> 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<F: Extendable<D>, const D: usize, const R: usize> Gate<F, D> 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::<F, 4>::new(config);
let mut pw = PartialWitness::<F>::new();
let constants = Arc::new([F::TWO; R]);
type Gate = GMiMCGate<F, 4, R>;
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();
}
}

View File

@ -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<F: Extendable<D>, const D: usize>(
prover_data: &ProverOnlyCircuitData<F, D>,
common_data: &CommonCircuitData<F, D>,
inputs: PartialWitness<F>,
marked: Vec<MarkedTargets>,
) -> Proof<F, D> {
let fri_config = &common_data.config.fri_config;
let config = &common_data.config;
@ -50,13 +52,10 @@ pub(crate) fn prove<F: Extendable<D>, 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<PolynomialValues<F>> = timed!(
witness
.wire_values

View File

@ -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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
inner_config: &CircuitConfig,
inner_verifier_data: &VerifierCircuitTarget,
inner_common_data: &CommonCircuitData<F, D>,
marked: &mut Vec<MarkedTargets>,
) {
assert!(self.config.num_wires >= MIN_WIRES);
assert!(self.config.num_wires >= MIN_ROUTED_WIRES);
@ -71,8 +73,14 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
&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::<F, 4>::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::<F, 4>::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();
}

54
src/util/marking.rs Normal file
View File

@ -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<Target>;
}
impl Markable for Target {
fn targets(&self) -> Vec<Target> {
vec![*self]
}
}
impl<const D: usize> Markable for ExtensionTarget<D> {
fn targets(&self) -> Vec<Target> {
self.0.try_into().unwrap()
}
}
impl Markable for HashTarget {
fn targets(&self) -> Vec<Target> {
self.elements.try_into().unwrap()
}
}
impl<M: Markable> Markable for Vec<M> {
fn targets(&self) -> Vec<Target> {
self.iter().flat_map(|m| m.targets()).collect()
}
}
pub struct MarkedTargets {
pub targets: Box<dyn Markable>,
pub name: String,
}
impl MarkedTargets {
pub fn display<F: Field>(&self, wit: &Witness<F>) {
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);
}
}

View File

@ -1,3 +1,4 @@
pub mod marking;
pub mod partial_products;
pub mod scaling;
pub(crate) mod timing;

View File

@ -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<F: Extendable<D>, const D: usize>(
constraint_terms,
]
.concat();
dbg!(&vanishing_terms);
let alphas = &alphas.iter().map(|&a| a.into()).collect::<Vec<_>>();
plonk_common::reduce_with_powers_multi(&vanishing_terms, alphas)
@ -233,6 +233,7 @@ pub fn evaluate_gate_constraints_recursively<F: Extendable<D>, const D: usize>(
gates: &[PrefixedGate<F, D>],
num_gate_constraints: usize,
vars: EvaluationTargets<D>,
marked: &mut Vec<MarkedTargets>,
) -> Vec<ExtensionTarget<D>> {
let mut constraints = vec![builder.zero_extension(); num_gate_constraints];
for gate in gates {
@ -240,6 +241,10 @@ pub fn evaluate_gate_constraints_recursively<F: Extendable<D>, 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<F: Extendable<D>, const D: usize>(
betas: &[Target],
gammas: &[Target],
alphas: &[Target],
marked: &mut Vec<MarkedTargets>,
) -> Vec<ExtensionTarget<D>> {
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<F: Extendable<D>, 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<F: Extendable<D>, const D: usize>(
constraint_terms,
]
.concat();
dbg!(&vanishing_terms);
alphas
.iter()

View File

@ -56,6 +56,7 @@ pub(crate) fn verify<F: Extendable<D>, 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;