From 322556260c250bd165187efa19be540279104507 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 14 Jun 2021 16:06:41 +0200 Subject: [PATCH 01/12] Cosmetic changes --- src/generator.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/generator.rs b/src/generator.rs index 443809b6..b6534921 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -17,17 +17,13 @@ pub(crate) fn generate_partial_witness( for watch in generator.watch_list() { generator_indices_by_watches .entry(watch) - .or_insert_with(Vec::new) - .push(i); + .or_insert_with(|| vec![i]); } } // Build a list of "pending" generators which are queued to be run. Initially, all generators // are queued. - let mut pending_generator_indices = HashSet::new(); - for i in 0..generators.len() { - pending_generator_indices.insert(i); - } + let mut pending_generator_indices: HashSet<_> = (0..generators.len()).collect(); // We also track a list of "expired" generators which have already returned false. let mut expired_generator_indices = HashSet::new(); From ea6a724560392b2422be85cce1988093c6debfbf Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 14 Jun 2021 17:02:52 +0200 Subject: [PATCH 02/12] Enforce copy constraints in partial witness generation. --- src/circuit_builder.rs | 11 ++++++++--- src/circuit_data.rs | 3 +++ src/gates/gmimc.rs | 10 +++++++++- src/generator.rs | 9 ++++++++- src/permutation_argument.rs | 21 +++++++++++++++++++++ src/plonk_challenger.rs | 9 +++++++-- src/prover.rs | 6 +++++- src/witness.rs | 4 ++++ 8 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 4150bb68..b9b2e533 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -236,7 +236,7 @@ impl, const D: usize> CircuitBuilder { .collect() } - fn sigma_vecs(&self, k_is: &[F]) -> Vec> { + fn sigma_vecs(&self, k_is: &[F]) -> (Vec>, TargetPartitions) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); let mut target_partitions = TargetPartitions::new(); @@ -256,7 +256,11 @@ impl, const D: usize> CircuitBuilder { } let wire_partitions = target_partitions.to_wire_partitions(); - wire_partitions.get_sigma_polys(degree_log, k_is) + + ( + wire_partitions.get_sigma_polys(degree_log, k_is), + target_partitions, + ) } /// Builds a "full circuit", with both prover and verifier data. @@ -278,7 +282,7 @@ impl, const D: usize> CircuitBuilder { ); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); - let sigma_vecs = self.sigma_vecs(&k_is); + let (sigma_vecs, targets_partition) = self.sigma_vecs(&k_is); let sigmas_commitment = ListPolynomialCommitment::new( sigma_vecs.into_iter().map(|v| v.ifft()).collect(), self.config.fri_config.rate_bits, @@ -297,6 +301,7 @@ impl, const D: usize> CircuitBuilder { generators, constants_commitment, sigmas_commitment, + targets_partition, }; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 4d9a7110..6b6d614a 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -5,6 +5,7 @@ use crate::field::field::Field; use crate::fri::FriConfig; use crate::gates::gate::GateRef; use crate::generator::WitnessGenerator; +use crate::permutation_argument::TargetPartitions; use crate::polynomial::commitment::ListPolynomialCommitment; use crate::proof::{Hash, HashTarget, Proof}; use crate::prover::prove; @@ -104,6 +105,8 @@ pub(crate) struct ProverOnlyCircuitData { pub constants_commitment: ListPolynomialCommitment, /// Commitments to the sigma polynomial. pub sigmas_commitment: ListPolynomialCommitment, + /// Partition of the targets into copy-constrained sets. + pub targets_partition: TargetPartitions, } /// Circuit data required by the verifier, but not the prover. diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 19042d57..ac5741e4 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -323,6 +323,8 @@ mod tests { use crate::gates::gmimc::{GMiMCGate, W}; use crate::generator::generate_partial_witness; use crate::gmimc::gmimc_permute_naive; + use crate::permutation_argument::TargetPartitions; + use crate::target::Target; use crate::wire::Wire; use crate::witness::PartialWitness; @@ -368,7 +370,13 @@ mod tests { } let generators = gate.0.generators(0, &[]); - generate_partial_witness(&mut witness, &generators); + let mut tp = TargetPartitions::new(); + for g in 0..10 { + for i in 0..config.num_routed_wires { + tp.add_partition(Target::wire(g, i)); + } + } + generate_partial_witness(&mut witness, &generators, &tp); let expected_outputs: [F; W] = gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); diff --git a/src/generator.rs b/src/generator.rs index b6534921..b04442b5 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use crate::field::field::Field; +use crate::permutation_argument::TargetPartitions; use crate::target::Target; use crate::witness::PartialWitness; @@ -10,6 +11,7 @@ use crate::witness::PartialWitness; pub(crate) fn generate_partial_witness( witness: &mut PartialWitness, generators: &[Box>], + target_partition: &TargetPartitions, ) { // Index generator indices by their watched targets. let mut generator_indices_by_watches = HashMap::new(); @@ -21,6 +23,8 @@ pub(crate) fn generate_partial_witness( } } + target_partition.generate_copies(witness, &witness.all_populated_targets()); + // Build a list of "pending" generators which are queued to be run. Initially, all generators // are queued. let mut pending_generator_indices: HashSet<_> = (0..generators.len()).collect(); @@ -33,11 +37,14 @@ pub(crate) fn generate_partial_witness( let mut next_pending_generator_indices = HashSet::new(); for &generator_idx in &pending_generator_indices { - let (result, finished) = generators[generator_idx].run(&witness); + let (mut result, finished) = generators[generator_idx].run(&witness); if finished { expired_generator_indices.insert(generator_idx); } + let new_targets = result.all_populated_targets(); + target_partition.generate_copies(&mut result, &new_targets); + // Enqueue unfinished generators that were watching one of the newly populated targets. for watch in result.target_values.keys() { if let Some(watching_generator_indices) = generator_indices_by_watches.get(watch) { diff --git a/src/permutation_argument.rs b/src/permutation_argument.rs index 62ee63d4..f2739756 100644 --- a/src/permutation_argument.rs +++ b/src/permutation_argument.rs @@ -6,6 +6,7 @@ use crate::field::field::Field; use crate::polynomial::polynomial::PolynomialValues; use crate::target::Target; use crate::wire::Wire; +use crate::witness::PartialWitness; #[derive(Debug, Clone)] pub struct TargetPartitions { @@ -82,6 +83,26 @@ impl TargetPartitions { indices, } } + /// For the given set of targets, find any copy constraints involving those targets and populate + /// the witness with copies as needed. + pub fn generate_copies(&self, witness: &mut PartialWitness, targets: &[Target]) { + let mut result = PartialWitness::new(); + + for &target in targets { + let value = witness.get_target(target); + let partition = self.get_partition(target); + + for &sibling in partition { + if witness.contains(sibling) { + // This sibling's value was already set; make sure it has the same value. + assert_eq!(witness.get_target(sibling), value); + } else { + result.set_target(sibling, value); + } + } + } + witness.extend(result); + } } pub struct WirePartitions { diff --git a/src/plonk_challenger.rs b/src/plonk_challenger.rs index fd21ee0d..30d4cf70 100644 --- a/src/plonk_challenger.rs +++ b/src/plonk_challenger.rs @@ -289,6 +289,7 @@ mod tests { use crate::field::crandall_field::CrandallField; use crate::field::field::Field; use crate::generator::generate_partial_witness; + use crate::permutation_argument::TargetPartitions; use crate::plonk_challenger::{Challenger, RecursiveChallenger}; use crate::target::Target; use crate::witness::PartialWitness; @@ -337,7 +338,7 @@ mod tests { let config = CircuitConfig { num_wires: 12 + 12 + 3 + 101, - num_routed_wires: 27, + num_routed_wires: 200, ..CircuitConfig::default() }; let mut builder = CircuitBuilder::::new(config); @@ -351,7 +352,11 @@ mod tests { } let circuit = builder.build(); let mut witness = PartialWitness::new(); - generate_partial_witness(&mut witness, &circuit.prover_only.generators); + generate_partial_witness( + &mut witness, + &circuit.prover_only.generators, + &circuit.prover_only.targets_partition, + ); let recursive_output_values_per_round: Vec> = recursive_outputs_per_round .iter() .map(|outputs| witness.get_targets(outputs)) diff --git a/src/prover.rs b/src/prover.rs index 7a492eaa..fc4e6f38 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -34,7 +34,11 @@ pub(crate) fn prove, const D: usize>( let mut witness = inputs; info!("Running {} generators", prover_data.generators.len()); timed!( - generate_partial_witness(&mut witness, &prover_data.generators), + generate_partial_witness( + &mut witness, + &prover_data.generators, + &prover_data.targets_partition + ), "to generate witness" ); diff --git a/src/witness.rs b/src/witness.rs index a0b4b2a4..e71eebc9 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -59,6 +59,10 @@ impl PartialWitness { targets.iter().all(|&t| self.contains(t)) } + pub fn all_populated_targets(&self) -> Vec { + self.target_values.keys().cloned().collect() + } + pub fn set_target(&mut self, target: Target, value: F) { let opt_old_value = self.target_values.insert(target, value); if let Some(old_value) = opt_old_value { From 86b4b0ab41295df4d133c5803ccca8125dd25e98 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 14 Jun 2021 17:06:53 +0200 Subject: [PATCH 03/12] Add check that all generators were run. --- src/generator.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/generator.rs b/src/generator.rs index b04442b5..a5ba4eaf 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -61,6 +61,11 @@ pub(crate) fn generate_partial_witness( pending_generator_indices = next_pending_generator_indices; } + assert_eq!( + expired_generator_indices.len(), + generators.len(), + "Some generators weren't run." + ); } /// A generator participates in the generation of the witness. From c22bc6261ed9c36288300acbf833fdaca0cefb84 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 14 Jun 2021 21:03:50 +0200 Subject: [PATCH 04/12] Revert watch insertion --- src/generator.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/generator.rs b/src/generator.rs index a5ba4eaf..5b6a258a 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -19,7 +19,8 @@ pub(crate) fn generate_partial_witness( for watch in generator.watch_list() { generator_indices_by_watches .entry(watch) - .or_insert_with(|| vec![i]); + .or_insert_with(Vec::new) + .push(i) } } From 3bc27c65ef49a149cdfb4e68dfe7d4dff8d13823 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Jun 2021 13:46:19 +0200 Subject: [PATCH 05/12] Rollback to previous semantics --- src/circuit_builder.rs | 10 +++------- src/circuit_data.rs | 3 --- src/gates/gmimc.rs | 8 +------- src/generator.rs | 10 ++-------- src/permutation_argument.rs | 21 --------------------- src/plonk_challenger.rs | 6 +----- src/prover.rs | 6 +----- src/witness.rs | 4 ---- 8 files changed, 8 insertions(+), 60 deletions(-) diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index b9b2e533..8c7d0a72 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -236,7 +236,7 @@ impl, const D: usize> CircuitBuilder { .collect() } - fn sigma_vecs(&self, k_is: &[F]) -> (Vec>, TargetPartitions) { + fn sigma_vecs(&self, k_is: &[F]) -> Vec> { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); let mut target_partitions = TargetPartitions::new(); @@ -257,10 +257,7 @@ impl, const D: usize> CircuitBuilder { let wire_partitions = target_partitions.to_wire_partitions(); - ( - wire_partitions.get_sigma_polys(degree_log, k_is), - target_partitions, - ) + wire_partitions.get_sigma_polys(degree_log, k_is) } /// Builds a "full circuit", with both prover and verifier data. @@ -282,7 +279,7 @@ impl, const D: usize> CircuitBuilder { ); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); - let (sigma_vecs, targets_partition) = self.sigma_vecs(&k_is); + let sigma_vecs = self.sigma_vecs(&k_is); let sigmas_commitment = ListPolynomialCommitment::new( sigma_vecs.into_iter().map(|v| v.ifft()).collect(), self.config.fri_config.rate_bits, @@ -301,7 +298,6 @@ impl, const D: usize> CircuitBuilder { generators, constants_commitment, sigmas_commitment, - targets_partition, }; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 6b6d614a..4d9a7110 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -5,7 +5,6 @@ use crate::field::field::Field; use crate::fri::FriConfig; use crate::gates::gate::GateRef; use crate::generator::WitnessGenerator; -use crate::permutation_argument::TargetPartitions; use crate::polynomial::commitment::ListPolynomialCommitment; use crate::proof::{Hash, HashTarget, Proof}; use crate::prover::prove; @@ -105,8 +104,6 @@ pub(crate) struct ProverOnlyCircuitData { pub constants_commitment: ListPolynomialCommitment, /// Commitments to the sigma polynomial. pub sigmas_commitment: ListPolynomialCommitment, - /// Partition of the targets into copy-constrained sets. - pub targets_partition: TargetPartitions, } /// Circuit data required by the verifier, but not the prover. diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index ac5741e4..bdfade7c 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -370,13 +370,7 @@ mod tests { } let generators = gate.0.generators(0, &[]); - let mut tp = TargetPartitions::new(); - for g in 0..10 { - for i in 0..config.num_routed_wires { - tp.add_partition(Target::wire(g, i)); - } - } - generate_partial_witness(&mut witness, &generators, &tp); + generate_partial_witness(&mut witness, &generators); let expected_outputs: [F; W] = gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); diff --git a/src/generator.rs b/src/generator.rs index 5b6a258a..db81172f 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -11,7 +11,6 @@ use crate::witness::PartialWitness; pub(crate) fn generate_partial_witness( witness: &mut PartialWitness, generators: &[Box>], - target_partition: &TargetPartitions, ) { // Index generator indices by their watched targets. let mut generator_indices_by_watches = HashMap::new(); @@ -20,12 +19,10 @@ pub(crate) fn generate_partial_witness( generator_indices_by_watches .entry(watch) .or_insert_with(Vec::new) - .push(i) + .push(i); } } - target_partition.generate_copies(witness, &witness.all_populated_targets()); - // Build a list of "pending" generators which are queued to be run. Initially, all generators // are queued. let mut pending_generator_indices: HashSet<_> = (0..generators.len()).collect(); @@ -38,14 +35,11 @@ pub(crate) fn generate_partial_witness( let mut next_pending_generator_indices = HashSet::new(); for &generator_idx in &pending_generator_indices { - let (mut result, finished) = generators[generator_idx].run(&witness); + let (result, finished) = generators[generator_idx].run(&witness); if finished { expired_generator_indices.insert(generator_idx); } - let new_targets = result.all_populated_targets(); - target_partition.generate_copies(&mut result, &new_targets); - // Enqueue unfinished generators that were watching one of the newly populated targets. for watch in result.target_values.keys() { if let Some(watching_generator_indices) = generator_indices_by_watches.get(watch) { diff --git a/src/permutation_argument.rs b/src/permutation_argument.rs index f2739756..62ee63d4 100644 --- a/src/permutation_argument.rs +++ b/src/permutation_argument.rs @@ -6,7 +6,6 @@ use crate::field::field::Field; use crate::polynomial::polynomial::PolynomialValues; use crate::target::Target; use crate::wire::Wire; -use crate::witness::PartialWitness; #[derive(Debug, Clone)] pub struct TargetPartitions { @@ -83,26 +82,6 @@ impl TargetPartitions { indices, } } - /// For the given set of targets, find any copy constraints involving those targets and populate - /// the witness with copies as needed. - pub fn generate_copies(&self, witness: &mut PartialWitness, targets: &[Target]) { - let mut result = PartialWitness::new(); - - for &target in targets { - let value = witness.get_target(target); - let partition = self.get_partition(target); - - for &sibling in partition { - if witness.contains(sibling) { - // This sibling's value was already set; make sure it has the same value. - assert_eq!(witness.get_target(sibling), value); - } else { - result.set_target(sibling, value); - } - } - } - witness.extend(result); - } } pub struct WirePartitions { diff --git a/src/plonk_challenger.rs b/src/plonk_challenger.rs index 30d4cf70..290b5231 100644 --- a/src/plonk_challenger.rs +++ b/src/plonk_challenger.rs @@ -352,11 +352,7 @@ mod tests { } let circuit = builder.build(); let mut witness = PartialWitness::new(); - generate_partial_witness( - &mut witness, - &circuit.prover_only.generators, - &circuit.prover_only.targets_partition, - ); + generate_partial_witness(&mut witness, &circuit.prover_only.generators); let recursive_output_values_per_round: Vec> = recursive_outputs_per_round .iter() .map(|outputs| witness.get_targets(outputs)) diff --git a/src/prover.rs b/src/prover.rs index fc4e6f38..81b02674 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -34,11 +34,7 @@ pub(crate) fn prove, const D: usize>( let mut witness = inputs; info!("Running {} generators", prover_data.generators.len()); timed!( - generate_partial_witness( - &mut witness, - &prover_data.generators, - &prover_data.targets_partition - ), + generate_partial_witness(&mut witness, &prover_data.generators,), "to generate witness" ); diff --git a/src/witness.rs b/src/witness.rs index e71eebc9..a0b4b2a4 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -59,10 +59,6 @@ impl PartialWitness { targets.iter().all(|&t| self.contains(t)) } - pub fn all_populated_targets(&self) -> Vec { - self.target_values.keys().cloned().collect() - } - pub fn set_target(&mut self, target: Target, value: F) { let opt_old_value = self.target_values.insert(target, value); if let Some(old_value) = opt_old_value { From bc90909fa34ca0c81b73d42545edecddc53ec01f Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Jun 2021 14:16:05 +0200 Subject: [PATCH 06/12] Add check of copy constraints after witness generation --- src/circuit_builder.rs | 5 +++-- src/circuit_data.rs | 13 +++++++++---- src/prover.rs | 11 +++++++++-- src/witness.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 8c7d0a72..9be203bb 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -293,11 +293,12 @@ impl, const D: usize> CircuitBuilder { sigmas_root, }; - let generators = self.generators; let prover_only = ProverOnlyCircuitData { - generators, + generators: self.generators, constants_commitment, sigmas_commitment, + copy_constraints: self.copy_constraints, + gate_instances: self.gate_instances, }; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 4d9a7110..37925c0c 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -3,11 +3,12 @@ use anyhow::Result; use crate::field::extension_field::Extendable; use crate::field::field::Field; use crate::fri::FriConfig; -use crate::gates::gate::GateRef; +use crate::gates::gate::{GateInstance, GateRef}; use crate::generator::WitnessGenerator; use crate::polynomial::commitment::ListPolynomialCommitment; use crate::proof::{Hash, HashTarget, Proof}; use crate::prover::prove; +use crate::target::Target; use crate::verifier::verify; use crate::witness::PartialWitness; @@ -52,7 +53,7 @@ impl CircuitConfig { /// Circuit data required by the prover or the verifier. pub struct CircuitData, const D: usize> { - pub(crate) prover_only: ProverOnlyCircuitData, + pub(crate) prover_only: ProverOnlyCircuitData, pub(crate) verifier_only: VerifierOnlyCircuitData, pub(crate) common: CommonCircuitData, } @@ -75,7 +76,7 @@ impl, const D: usize> CircuitData { /// required, like LDEs of preprocessed polynomials. If more succinctness was desired, we could /// construct a more minimal prover structure and convert back and forth. pub struct ProverCircuitData, const D: usize> { - pub(crate) prover_only: ProverOnlyCircuitData, + pub(crate) prover_only: ProverOnlyCircuitData, pub(crate) common: CommonCircuitData, } @@ -98,12 +99,16 @@ impl, const D: usize> VerifierCircuitData { } /// Circuit data required by the prover, but not the verifier. -pub(crate) struct ProverOnlyCircuitData { +pub(crate) struct ProverOnlyCircuitData, const D: usize> { pub generators: Vec>>, /// Commitments to the constants polynomial. pub constants_commitment: ListPolynomialCommitment, /// Commitments to the sigma polynomial. pub sigmas_commitment: ListPolynomialCommitment, + /// The circuit's copy constraints. + pub copy_constraints: Vec<(Target, Target)>, + /// The concrete placement of each gate in the circuit. + pub gate_instances: Vec>, } /// Circuit data required by the verifier, but not the prover. diff --git a/src/prover.rs b/src/prover.rs index 81b02674..0215aa13 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -23,7 +23,7 @@ use crate::witness::PartialWitness; pub const PLONK_BLINDING: [bool; 5] = [false, false, true, true, true]; pub(crate) fn prove, const D: usize>( - prover_data: &ProverOnlyCircuitData, + prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, inputs: PartialWitness, ) -> Proof { @@ -38,6 +38,13 @@ pub(crate) fn prove, const D: usize>( "to generate witness" ); + timed!( + witness + .check_copy_constraints(&prover_data.copy_constraints, &prover_data.gate_instances) + .unwrap(), // TODO: Change return value to `Result` and use `?` here. + "to check copy constraints" + ); + let config = &common_data.config; let num_wires = config.num_wires; let num_challenges = config.num_challenges; @@ -162,7 +169,7 @@ fn compute_z, const D: usize>( fn compute_vanishing_polys, const D: usize>( common_data: &CommonCircuitData, - prover_data: &ProverOnlyCircuitData, + prover_data: &ProverOnlyCircuitData, wires_commitment: &ListPolynomialCommitment, plonk_zs_commitment: &ListPolynomialCommitment, betas: &[F], diff --git a/src/witness.rs b/src/witness.rs index a0b4b2a4..ff6a8a50 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -1,7 +1,10 @@ use std::collections::HashMap; +use anyhow::{ensure, Result}; + use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field::Field; +use crate::gates::gate::GateInstance; use crate::target::Target; use crate::wire::Wire; @@ -97,6 +100,30 @@ impl PartialWitness { self.set_target(target, value); } } + + /// Checks that the copy constraints are satisfied in the witness. + pub fn check_copy_constraints( + &self, + copy_constraints: &[(Target, Target)], + gate_instances: &[GateInstance], + ) -> Result<()> + where + F: Extendable, + { + for &(a, b) in copy_constraints { + if let (Target::Wire(wa), Target::Wire(wb)) = (a, b) { + let va = self.target_values.get(&a).copied().unwrap_or(F::ZERO); + let vb = self.target_values.get(&b).copied().unwrap_or(F::ZERO); + ensure!( + va == vb, + "Copy constraint between wire {} of gate #{} (`{}`) and wire {} of gate #{} (`{}`) is not satisfied.\ + Got values of {} and {} respectively.", + wa.input, wa.gate, gate_instances[wa.gate].gate_type.0.id(), wb.input, wb.gate, + gate_instances[wb.gate].gate_type.0.id(), va, vb); + } + } + Ok(()) + } } impl Default for PartialWitness { From 8ae664d94fba60ea38d96dc55ca5353c3a40e72c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Jun 2021 14:22:42 +0200 Subject: [PATCH 07/12] Minor --- src/gadgets/arithmetic.rs | 2 -- src/witness.rs | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/gadgets/arithmetic.rs b/src/gadgets/arithmetic.rs index 520f8cd9..7a9fd441 100644 --- a/src/gadgets/arithmetic.rs +++ b/src/gadgets/arithmetic.rs @@ -385,8 +385,6 @@ mod tests { let x = FF::rand(); let y = FF::rand(); - let x = FF::TWO; - let y = FF::ONE; let z = x / y; let xt = builder.constant_extension(x); let yt = builder.constant_extension(y); diff --git a/src/witness.rs b/src/witness.rs index f55d4297..aff0192a 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::convert::TryInto; use anyhow::{ensure, Result}; @@ -139,8 +140,8 @@ impl PartialWitness { let vb = self.target_values.get(&b).copied().unwrap_or(F::ZERO); ensure!( va == vb, - "Copy constraint between wire {} of gate #{} (`{}`) and wire {} of gate #{} (`{}`) is not satisfied.\ - Got values of {} and {} respectively.", + "Copy constraint between wire {} of gate #{} (`{}`) and wire {} of gate #{} (`{}`) is not satisfied. \ + Got values of {} and {} respectively.", wa.input, wa.gate, gate_instances[wa.gate].gate_type.0.id(), wb.input, wb.gate, gate_instances[wb.gate].gate_type.0.id(), va, vb); } From 747f1875af0e76b3b44ed6c91dc19430bff7ac4a Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Jun 2021 14:26:05 +0200 Subject: [PATCH 08/12] Add todo for public inputs --- src/circuit_builder.rs | 1 - src/witness.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 640e17a5..0a7041e5 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -274,7 +274,6 @@ impl, const D: usize> CircuitBuilder { } let wire_partitions = target_partitions.to_wire_partitions(); - wire_partitions.get_sigma_polys(degree_log, k_is) } diff --git a/src/witness.rs b/src/witness.rs index aff0192a..989ec2bc 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -135,6 +135,7 @@ impl PartialWitness { F: Extendable, { for &(a, b) in copy_constraints { + // TODO: Take care of public inputs once they land. if let (Target::Wire(wa), Target::Wire(wb)) = (a, b) { let va = self.target_values.get(&a).copied().unwrap_or(F::ZERO); let vb = self.target_values.get(&b).copied().unwrap_or(F::ZERO); From d69f11794e45034964a95d6f5069d88aaa4b9bc6 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Jun 2021 19:15:52 +0200 Subject: [PATCH 09/12] Revert `num_routed_wires` to 27 --- src/plonk_challenger.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plonk_challenger.rs b/src/plonk_challenger.rs index d1141672..9af5e590 100644 --- a/src/plonk_challenger.rs +++ b/src/plonk_challenger.rs @@ -1,3 +1,5 @@ +use std::convert::TryInto; + use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; @@ -5,7 +7,6 @@ use crate::field::field::Field; use crate::hash::{permute, SPONGE_RATE, SPONGE_WIDTH}; use crate::proof::{Hash, HashTarget, OpeningSet}; use crate::target::Target; -use std::convert::TryInto; /// Observes prover messages, and generates challenges by hashing the transcript. #[derive(Clone)] @@ -369,7 +370,7 @@ mod tests { let config = CircuitConfig { num_wires: 12 + 12 + 3 + 101, - num_routed_wires: 200, + num_routed_wires: 27, ..CircuitConfig::default() }; let mut builder = CircuitBuilder::::new(config); From ac1179255a95aefd0dfacd3cd2c8e5d6403148ee Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Wed, 23 Jun 2021 15:45:48 -0700 Subject: [PATCH 10/12] Delete coset [I]FFT methods (#72) I think they had a mistake, and in any case we have a similar method in `polynomial.rs` now which has tests. --- src/field/fft.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/field/fft.rs b/src/field/fft.rs index 8bcde967..e1c1a097 100644 --- a/src/field/fft.rs +++ b/src/field/fft.rs @@ -126,32 +126,11 @@ pub(crate) fn fft_with_precomputation_power_of_2( PolynomialValues { values } } -pub(crate) fn coset_fft(poly: PolynomialCoeffs, shift: F) -> PolynomialValues { - let mut points = fft(poly); - let mut shift_exp_i = F::ONE; - for p in points.values.iter_mut() { - *p *= shift_exp_i; - shift_exp_i *= shift; - } - points -} - pub(crate) fn ifft(poly: PolynomialValues) -> PolynomialCoeffs { let precomputation = fft_precompute(poly.len()); ifft_with_precomputation_power_of_2(poly, &precomputation) } -pub(crate) fn coset_ifft(poly: PolynomialValues, shift: F) -> PolynomialCoeffs { - let shift_inv = shift.inverse(); - let mut shift_inv_exp_i = F::ONE; - let mut coeffs = ifft(poly); - for c in coeffs.coeffs.iter_mut() { - *c *= shift_inv_exp_i; - shift_inv_exp_i *= shift_inv; - } - coeffs -} - #[cfg(test)] mod tests { use crate::field::crandall_field::CrandallField; From aa78d02c016f8c0f3708adf20a9045940e66db84 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Thu, 24 Jun 2021 10:43:44 -0700 Subject: [PATCH 11/12] Delete outdated comment --- src/bin/bench_recursion.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 9fab2456..0682578d 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -51,12 +51,6 @@ fn bench_prove, const D: usize>() { builder.add_gate(ConstantGate::get(), vec![F::NEG_ONE]); - // for _ in 0..(40 * 5) { - // builder.add_gate( - // FriConsistencyGate::new(2, 3, 13), - // vec![F::primitive_root_of_unity(13)]); - // } - let prover = builder.build_prover(); let inputs = PartialWitness::new(); prover.prove(inputs); From e50eeb6cf49c2fa23455b3c406a5246a1d4d69c0 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Thu, 24 Jun 2021 10:44:46 -0700 Subject: [PATCH 12/12] Delete more outdated comments --- src/bin/bench_recursion.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 0682578d..1c9104f9 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -18,12 +18,6 @@ fn main() { env_logger::Builder::from_env(Env::default().default_filter_or("debug")).init(); bench_prove::(); - - // bench_field_mul::(); - - // bench_fft(); - println!(); - // bench_gmimc::(); } fn bench_prove, const D: usize>() {