From 74c2be5090a6062de3271d0a2af1d916578674d7 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 19 Aug 2021 14:54:11 +0200 Subject: [PATCH 01/19] First pass --- src/gadgets/arithmetic_extension.rs | 5 +- src/gadgets/range_check.rs | 4 +- src/gadgets/split_base.rs | 4 +- src/gadgets/split_join.rs | 6 +- src/gates/arithmetic.rs | 6 +- src/gates/base_sum.rs | 4 +- src/gates/constant.rs | 4 +- src/gates/exponentiation.rs | 4 +- src/gates/gmimc.rs | 176 +++++++++++----------- src/gates/insertion.rs | 4 +- src/gates/interpolation.rs | 5 +- src/gates/random_access.rs | 4 +- src/gates/reducing.rs | 5 +- src/iop/challenger.rs | 172 +++++++++++----------- src/iop/generator.rs | 221 +++++++++++++++++++++++++--- src/iop/witness.rs | 3 + src/plonk/circuit_builder.rs | 26 +++- src/plonk/circuit_data.rs | 3 + src/plonk/permutation_argument.rs | 40 ++--- src/plonk/prover.rs | 65 ++++++-- 20 files changed, 499 insertions(+), 262 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 94b37eaa..f7b8eee5 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -5,7 +5,7 @@ use crate::field::extension_field::FieldExtension; use crate::field::extension_field::{Extendable, OEF}; use crate::field::field_types::Field; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; -use crate::iop::generator::{GeneratedValues, SimpleGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -433,6 +433,7 @@ impl, const D: usize> CircuitBuilder { } } +#[derive(Debug)] struct QuotientGeneratorExtension { numerator: ExtensionTarget, denominator: ExtensionTarget, @@ -446,7 +447,7 @@ impl, const D: usize> SimpleGenerator for QuotientGeneratorE deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let num = witness.get_extension_target(self.numerator); let dem = witness.get_extension_target(self.denominator); let quotient = num / dem; diff --git a/src/gadgets/range_check.rs b/src/gadgets/range_check.rs index be7eaf2e..c03dae7b 100644 --- a/src/gadgets/range_check.rs +++ b/src/gadgets/range_check.rs @@ -1,7 +1,7 @@ use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -56,7 +56,7 @@ impl SimpleGenerator for LowHighGenerator { vec![self.integer] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let integer_value = witness.get_target(self.integer).to_canonical_u64(); let low = integer_value & ((1 << self.n_log) - 1); let high = integer_value >> self.n_log; diff --git a/src/gadgets/split_base.rs b/src/gadgets/split_base.rs index 69cfa377..cca2a166 100644 --- a/src/gadgets/split_base.rs +++ b/src/gadgets/split_base.rs @@ -3,7 +3,7 @@ use std::borrow::Borrow; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -68,7 +68,7 @@ impl SimpleGenerator for BaseSumGenerator { self.limbs.iter().map(|b| b.target).collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let sum = self .limbs .iter() diff --git a/src/gadgets/split_join.rs b/src/gadgets/split_join.rs index 71c171f0..875ead00 100644 --- a/src/gadgets/split_join.rs +++ b/src/gadgets/split_join.rs @@ -1,7 +1,7 @@ use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -68,7 +68,7 @@ impl SimpleGenerator for SplitGenerator { vec![self.integer] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let mut integer_value = witness.get_target(self.integer).to_canonical_u64(); for &b in &self.bits { @@ -96,7 +96,7 @@ impl SimpleGenerator for WireSplitGenerator { vec![self.integer] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let mut integer_value = witness.get_target(self.integer).to_canonical_u64(); for &gate in &self.gates { diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index dcabcee8..159628e1 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -4,7 +4,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -138,7 +138,7 @@ impl, const D: usize> Gate for ArithmeticExtensionGate } } -#[derive(Clone)] +#[derive(Debug)] struct ArithmeticExtensionGenerator, const D: usize> { gate_index: usize, const_0: F, @@ -157,7 +157,7 @@ impl, const D: usize> SimpleGenerator for ArithmeticExtensio .collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let extract_extension = |range: Range| -> F::Extension { let t = ExtensionTarget::from_range(self.gate_index, range); witness.get_extension_target(t) diff --git a/src/gates/base_sum.rs b/src/gates/base_sum.rs index fe4e51a2..c46bfee1 100644 --- a/src/gates/base_sum.rs +++ b/src/gates/base_sum.rs @@ -4,7 +4,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -132,7 +132,7 @@ impl SimpleGenerator for BaseSplitGenerator { vec![Target::wire(self.gate_index, BaseSumGate::::WIRE_SUM)] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let sum_value = witness .get_target(Target::wire(self.gate_index, BaseSumGate::::WIRE_SUM)) .to_canonical_u64() as usize; diff --git a/src/gates/constant.rs b/src/gates/constant.rs index 0cc22b22..94d5fa03 100644 --- a/src/gates/constant.rs +++ b/src/gates/constant.rs @@ -2,7 +2,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; @@ -85,7 +85,7 @@ impl SimpleGenerator for ConstantGenerator { Vec::new() } - fn run_once(&self, _witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, _witness: &Yo, out_buffer: &mut GeneratedValues) { let wire = Wire { gate: self.gate_index, input: ConstantGate::WIRE_OUTPUT, diff --git a/src/gates/exponentiation.rs b/src/gates/exponentiation.rs index 468f58e2..69827907 100644 --- a/src/gates/exponentiation.rs +++ b/src/gates/exponentiation.rs @@ -4,7 +4,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; @@ -218,7 +218,7 @@ impl, const D: usize> SimpleGenerator for ExponentiationGene deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 1830b9c7..2e0f652f 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -5,7 +5,7 @@ use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; use crate::hash::gmimc::gmimc_automatic_constants; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; @@ -264,7 +264,7 @@ impl, const D: usize, const R: usize> SimpleGenerator .collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let mut state = (0..W) .map(|i| { witness.get_wire(Wire { @@ -317,89 +317,89 @@ impl, const D: usize, const R: usize> SimpleGenerator } } -#[cfg(test)] -mod tests { - use std::convert::TryInto; - use std::sync::Arc; - - use anyhow::Result; - - use crate::field::crandall_field::CrandallField; - use crate::field::field_types::Field; - use crate::gates::gate::Gate; - 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::iop::generator::generate_partial_witness; - use crate::iop::wire::Wire; - use crate::iop::witness::PartialWitness; - use crate::util::timing::TimingTree; - - #[test] - fn generated_output() { - type F = CrandallField; - const R: usize = 101; - let constants = Arc::new([F::TWO; R]); - type Gate = GMiMCGate; - let gate = Gate::new(constants.clone()); - - let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::>(); - - let mut witness = PartialWitness::new(gate.num_wires()); - witness.set_wire( - Wire { - gate: 0, - input: Gate::WIRE_SWAP, - }, - F::ZERO, - ); - for i in 0..W { - witness.set_wire( - Wire { - gate: 0, - input: Gate::wire_input(i), - }, - permutation_inputs[i], - ); - } - - let generators = gate.generators(0, &[]); - generate_partial_witness( - &mut witness, - &generators, - gate.num_wires(), - 1, - 1, - &mut TimingTree::default(), - ); - - let expected_outputs: [F; W] = - gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); - - for i in 0..W { - let out = witness.get_wire(Wire { - gate: 0, - input: Gate::wire_output(i), - }); - assert_eq!(out, expected_outputs[i]); - } - } - - #[test] - fn low_degree() { - type F = CrandallField; - const R: usize = 101; - let constants = Arc::new([F::TWO; R]); - let gate = GMiMCGate::::new(constants); - test_low_degree(gate) - } - - #[test] - fn eval_fns() -> Result<()> { - type F = CrandallField; - const R: usize = 101; - let constants = Arc::new([F::TWO; R]); - let gate = GMiMCGate::::new(constants); - test_eval_fns(gate) - } -} +// #[cfg(test)] +// mod tests { +// use std::convert::TryInto; +// use std::sync::Arc; +// +// use anyhow::Result; +// +// use crate::field::crandall_field::CrandallField; +// use crate::field::field_types::Field; +// use crate::gates::gate::Gate; +// 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::iop::generator::generate_partial_witness; +// use crate::iop::wire::Wire; +// use crate::iop::witness::PartialWitness; +// use crate::util::timing::TimingTree; +// +// #[test] +// fn generated_output() { +// type F = CrandallField; +// const R: usize = 101; +// let constants = Arc::new([F::TWO; R]); +// type Gate = GMiMCGate; +// let gate = Gate::new(constants.clone()); +// +// let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::>(); +// +// let mut witness = PartialWitness::new(gate.num_wires()); +// witness.set_wire( +// Wire { +// gate: 0, +// input: Gate::WIRE_SWAP, +// }, +// F::ZERO, +// ); +// for i in 0..W { +// witness.set_wire( +// Wire { +// gate: 0, +// input: Gate::wire_input(i), +// }, +// permutation_inputs[i], +// ); +// } +// +// let generators = gate.generators(0, &[]); +// generate_partial_witness( +// &mut witness, +// &generators, +// gate.num_wires(), +// 1, +// 1, +// &mut TimingTree::default(), +// ); +// +// let expected_outputs: [F; W] = +// gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); +// +// for i in 0..W { +// let out = witness.get_wire(Wire { +// gate: 0, +// input: Gate::wire_output(i), +// }); +// assert_eq!(out, expected_outputs[i]); +// } +// } +// +// #[test] +// fn low_degree() { +// type F = CrandallField; +// const R: usize = 101; +// let constants = Arc::new([F::TWO; R]); +// let gate = GMiMCGate::::new(constants); +// test_low_degree(gate) +// } +// +// #[test] +// fn eval_fns() -> Result<()> { +// type F = CrandallField; +// const R: usize = 101; +// let constants = Arc::new([F::TWO; R]); +// let gate = GMiMCGate::::new(constants); +// test_eval_fns(gate) +// } +// } diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index 7a42be41..d1c2ea22 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -6,7 +6,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; @@ -261,7 +261,7 @@ impl, const D: usize> SimpleGenerator for InsertionGenerator deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 9356d428..a9cd7d38 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -8,7 +8,7 @@ use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::interpolation::interpolant; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; @@ -213,6 +213,7 @@ impl, const D: usize> Gate for InterpolationGate { } } +#[derive(Debug)] struct InterpolationGenerator, const D: usize> { gate_index: usize, gate: InterpolationGate, @@ -239,7 +240,7 @@ impl, const D: usize> SimpleGenerator for InterpolationGener deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let n = self.gate.num_points; let local_wire = |input| Wire { diff --git a/src/gates/random_access.rs b/src/gates/random_access.rs index 0dd008f0..561bfbfd 100644 --- a/src/gates/random_access.rs +++ b/src/gates/random_access.rs @@ -5,7 +5,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; @@ -208,7 +208,7 @@ impl, const D: usize> SimpleGenerator for RandomAccessGenera deps } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/reducing.rs b/src/gates/reducing.rs index 8bfdc0c4..64987e79 100644 --- a/src/gates/reducing.rs +++ b/src/gates/reducing.rs @@ -4,7 +4,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -159,6 +159,7 @@ impl, const D: usize> Gate for ReducingGate { } } +#[derive(Debug)] struct ReducingGenerator { gate_index: usize, gate: ReducingGate, @@ -173,7 +174,7 @@ impl, const D: usize> SimpleGenerator for ReducingGenerator< .collect() } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let extract_extension = |range: Range| -> F::Extension { let t = ExtensionTarget::from_range(self.gate_index, range); witness.get_extension_target(t) diff --git a/src/iop/challenger.rs b/src/iop/challenger.rs index 70c7e310..13e16035 100644 --- a/src/iop/challenger.rs +++ b/src/iop/challenger.rs @@ -353,89 +353,89 @@ impl RecursiveChallenger { } } -#[cfg(test)] -mod tests { - use crate::field::crandall_field::CrandallField; - use crate::field::field_types::Field; - use crate::iop::challenger::{Challenger, RecursiveChallenger}; - use crate::iop::generator::generate_partial_witness; - use crate::iop::target::Target; - use crate::iop::witness::PartialWitness; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::util::timing::TimingTree; - - #[test] - fn no_duplicate_challenges() { - type F = CrandallField; - let mut challenger = Challenger::new(); - let mut challenges = Vec::new(); - - for i in 1..10 { - challenges.extend(challenger.get_n_challenges(i)); - challenger.observe_element(F::rand()); - } - - let dedup_challenges = { - let mut dedup = challenges.clone(); - dedup.dedup(); - dedup - }; - assert_eq!(dedup_challenges, challenges); - } - - /// Tests for consistency between `Challenger` and `RecursiveChallenger`. - #[test] - fn test_consistency() { - type F = CrandallField; - - // These are mostly arbitrary, but we want to test some rounds with enough inputs/outputs to - // trigger multiple absorptions/squeezes. - let num_inputs_per_round = vec![2, 5, 3]; - let num_outputs_per_round = vec![1, 2, 4]; - - // Generate random input messages. - let inputs_per_round: Vec> = num_inputs_per_round - .iter() - .map(|&n| F::rand_vec(n)) - .collect(); - - let mut challenger = Challenger::new(); - let mut outputs_per_round: Vec> = Vec::new(); - for (r, inputs) in inputs_per_round.iter().enumerate() { - challenger.observe_elements(inputs); - outputs_per_round.push(challenger.get_n_challenges(num_outputs_per_round[r])); - } - - let config = CircuitConfig { - num_wires: 12 + 12 + 1 + 101, - num_routed_wires: 27, - ..CircuitConfig::default() - }; - let mut witness = PartialWitness::new(config.num_wires); - let mut builder = CircuitBuilder::::new(config.clone()); - let mut recursive_challenger = RecursiveChallenger::new(&mut builder); - let mut recursive_outputs_per_round: Vec> = Vec::new(); - for (r, inputs) in inputs_per_round.iter().enumerate() { - recursive_challenger.observe_elements(&builder.constants(inputs)); - recursive_outputs_per_round.push( - recursive_challenger.get_n_challenges(&mut builder, num_outputs_per_round[r]), - ); - } - let circuit = builder.build(); - generate_partial_witness( - &mut witness, - &circuit.prover_only.generators, - config.num_wires, - circuit.common.degree(), - circuit.prover_only.num_virtual_targets, - &mut TimingTree::default(), - ); - let recursive_output_values_per_round: Vec> = recursive_outputs_per_round - .iter() - .map(|outputs| witness.get_targets(outputs)) - .collect(); - - assert_eq!(outputs_per_round, recursive_output_values_per_round); - } -} +// #[cfg(test)] +// mod tests { +// use crate::field::crandall_field::CrandallField; +// use crate::field::field_types::Field; +// use crate::iop::challenger::{Challenger, RecursiveChallenger}; +// use crate::iop::generator::generate_partial_witness; +// use crate::iop::target::Target; +// use crate::iop::witness::PartialWitness; +// use crate::plonk::circuit_builder::CircuitBuilder; +// use crate::plonk::circuit_data::CircuitConfig; +// use crate::util::timing::TimingTree; +// +// #[test] +// fn no_duplicate_challenges() { +// type F = CrandallField; +// let mut challenger = Challenger::new(); +// let mut challenges = Vec::new(); +// +// for i in 1..10 { +// challenges.extend(challenger.get_n_challenges(i)); +// challenger.observe_element(F::rand()); +// } +// +// let dedup_challenges = { +// let mut dedup = challenges.clone(); +// dedup.dedup(); +// dedup +// }; +// assert_eq!(dedup_challenges, challenges); +// } +// +// /// Tests for consistency between `Challenger` and `RecursiveChallenger`. +// #[test] +// fn test_consistency() { +// type F = CrandallField; +// +// // These are mostly arbitrary, but we want to test some rounds with enough inputs/outputs to +// // trigger multiple absorptions/squeezes. +// let num_inputs_per_round = vec![2, 5, 3]; +// let num_outputs_per_round = vec![1, 2, 4]; +// +// // Generate random input messages. +// let inputs_per_round: Vec> = num_inputs_per_round +// .iter() +// .map(|&n| F::rand_vec(n)) +// .collect(); +// +// let mut challenger = Challenger::new(); +// let mut outputs_per_round: Vec> = Vec::new(); +// for (r, inputs) in inputs_per_round.iter().enumerate() { +// challenger.observe_elements(inputs); +// outputs_per_round.push(challenger.get_n_challenges(num_outputs_per_round[r])); +// } +// +// let config = CircuitConfig { +// num_wires: 12 + 12 + 1 + 101, +// num_routed_wires: 27, +// ..CircuitConfig::default() +// }; +// let mut witness = PartialWitness::new(config.num_wires); +// let mut builder = CircuitBuilder::::new(config.clone()); +// let mut recursive_challenger = RecursiveChallenger::new(&mut builder); +// let mut recursive_outputs_per_round: Vec> = Vec::new(); +// for (r, inputs) in inputs_per_round.iter().enumerate() { +// recursive_challenger.observe_elements(&builder.constants(inputs)); +// recursive_outputs_per_round.push( +// recursive_challenger.get_n_challenges(&mut builder, num_outputs_per_round[r]), +// ); +// } +// let circuit = builder.build(); +// generate_partial_witness( +// &mut witness, +// &circuit.prover_only.generators, +// config.num_wires, +// circuit.common.degree(), +// circuit.prover_only.num_virtual_targets, +// &mut TimingTree::default(), +// ); +// let recursive_output_values_per_round: Vec> = recursive_outputs_per_round +// .iter() +// .map(|outputs| witness.get_targets(outputs)) +// .collect(); +// +// assert_eq!(outputs_per_round, recursive_output_values_per_round); +// } +// } diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 6ab1b412..71b9aa3a 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -1,41 +1,199 @@ -use std::convert::identity; +use std::convert::{identity, TryInto}; use std::fmt::Debug; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; -use crate::hash::hash_types::{HashOut, HashOutTarget}; -use crate::iop::target::Target; +use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; +use crate::hash::merkle_tree::MerkleCap; +use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, Witness}; +use crate::plonk::permutation_argument::ForestNode; use crate::timed; use crate::util::timing::TimingTree; +pub struct Yo( + pub Vec>, + pub Box usize>, +); +impl Yo { + pub fn get_target(&self, target: Target) -> F { + self.0[self.0[self.1(target)].parent].value.unwrap() + } + + pub fn get_targets(&self, targets: &[Target]) -> Vec { + targets.iter().map(|&t| self.get_target(t)).collect() + } + + pub fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension + where + F: Extendable, + { + F::Extension::from_basefield_array( + self.get_targets(&et.to_target_array()).try_into().unwrap(), + ) + } + + pub fn get_extension_targets( + &self, + ets: &[ExtensionTarget], + ) -> Vec + where + F: Extendable, + { + ets.iter() + .map(|&et| self.get_extension_target(et)) + .collect() + } + + pub fn get_bool_target(&self, target: BoolTarget) -> bool { + let value = self.get_target(target.target).to_canonical_u64(); + match value { + 0 => false, + 1 => true, + _ => panic!("not a bool"), + } + } + + pub fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { + HashOut { + elements: self.get_targets(&ht.elements).try_into().unwrap(), + } + } + + pub fn try_get_target(&self, target: Target) -> Option { + self.0[self.0[self.1(target)].parent].value + } + + pub fn get_wire(&self, wire: Wire) -> F { + self.get_target(Target::Wire(wire)) + } + + pub fn try_get_wire(&self, wire: Wire) -> Option { + self.try_get_target(Target::Wire(wire)) + } + + pub fn contains(&self, target: Target) -> bool { + self.0[self.0[self.1(target)].parent].value.is_some() + } + + pub fn contains_all(&self, targets: &[Target]) -> bool { + targets.iter().all(|&t| self.contains(t)) + } + + pub fn set_target(&mut self, target: Target, value: F) { + let i = self.0[self.1(target)].parent; + self.0[i].value = Some(value); + } + + pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { + ht.elements + .iter() + .zip(value.elements) + .for_each(|(&t, x)| self.set_target(t, x)); + } + + pub fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap) { + for (ht, h) in ct.0.iter().zip(&value.0) { + self.set_hash_target(*ht, *h); + } + } + + pub fn set_extension_target( + &mut self, + et: ExtensionTarget, + value: F::Extension, + ) where + F: Extendable, + { + let limbs = value.to_basefield_array(); + (0..D).for_each(|i| { + self.set_target(et.0[i], limbs[i]); + }); + } + + 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_bool_target(&mut self, target: BoolTarget, value: bool) { + self.set_target(target.target, F::from_bool(value)) + } + + pub fn set_wire(&mut self, wire: Wire, value: F) { + self.set_target(Target::Wire(wire), value) + } + + pub fn set_wires(&mut self, wires: W, values: &[F]) + where + W: IntoIterator, + { + // If we used itertools, we could use zip_eq for extra safety. + for (wire, &value) in wires.into_iter().zip(values) { + self.set_wire(wire, value); + } + } + + pub fn set_ext_wires(&mut self, wires: W, value: F::Extension) + where + F: Extendable, + W: IntoIterator, + { + self.set_wires(wires, &value.to_basefield_array()); + } + + pub fn extend>(&mut self, pairs: I) { + for (t, v) in pairs { + self.set_target(t, v); + } + } + + pub fn full_witness(self, degree: usize, num_wires: usize) -> Witness { + let mut wire_values = vec![vec![F::ZERO; degree]; num_wires]; + // assert!(self.wire_values.len() <= degree); + for i in 0..degree { + for j in 0..num_wires { + let t = Target::Wire(Wire { gate: i, input: j }); + wire_values[j][i] = self.0[self.0[self.1(t)].parent].value.unwrap_or(F::ZERO); + } + } + Witness { wire_values } + } +} + /// Given a `PartialWitness` that has only inputs set, populates the rest of the witness using the /// given set of generators. pub(crate) fn generate_partial_witness( - witness: &mut PartialWitness, + witness: &mut Yo, generators: &[Box>], num_wires: usize, degree: usize, max_virtual_target: usize, timing: &mut TimingTree, ) { - let target_index = |t: Target| -> usize { - match t { - Target::Wire(Wire { gate, input }) => gate * num_wires + input, - Target::VirtualTarget { index } => degree * num_wires + index, - } - }; - let max_target_index = target_index(Target::VirtualTarget { - index: max_virtual_target, - }); + // let target_index = |t: Target| -> usize { + // match t { + // Target::Wire(Wire { gate, input }) => gate * num_wires + input, + // Target::VirtualTarget { index } => degree * num_wires + index, + // } + // }; + let max_target_index = witness.0.len(); // Index generator indices by their watched targets. let mut generator_indices_by_watches = vec![Vec::new(); max_target_index]; timed!(timing, "index generators by their watched targets", { for (i, generator) in generators.iter().enumerate() { for watch in generator.watch_list() { - generator_indices_by_watches[target_index(watch)].push(i); + generator_indices_by_watches[witness.1(watch)].push(i); } } }); @@ -65,7 +223,7 @@ pub(crate) fn generate_partial_witness( // Enqueue unfinished generators that were watching one of the newly populated targets. for &(watch, _) in &buffer.target_values { - for &watching_generator_idx in &generator_indices_by_watches[target_index(watch)] { + for &watching_generator_idx in &generator_indices_by_watches[witness.1(watch)] { next_pending_generator_indices.push(watching_generator_idx); } } @@ -76,6 +234,19 @@ pub(crate) fn generate_partial_witness( pending_generator_indices = next_pending_generator_indices; } + for i in 0..degree { + for j in 0..num_wires { + if !witness.contains(Target::Wire(Wire { gate: i, input: j })) { + println!("{} {}", i, j); + } + } + } + // for i in 0..generator_is_expired.len() { + // if !generator_is_expired[i] { + // println!("{:?}", generators[i]); + // println!("{:?}", generators[i].watch_list()); + // } + // } assert!( generator_is_expired.into_iter().all(identity), "Some generators weren't run." @@ -83,7 +254,7 @@ pub(crate) fn generate_partial_witness( } /// A generator participates in the generation of the witness. -pub trait WitnessGenerator: 'static + Send + Sync { +pub trait WitnessGenerator: 'static + Send + Sync + Debug { /// Targets to be "watched" by this generator. Whenever a target in the watch list is populated, /// the generator will be queued to run. fn watch_list(&self) -> Vec; @@ -91,7 +262,7 @@ pub trait WitnessGenerator: 'static + Send + Sync { /// Run this generator, returning a flag indicating whether the generator is finished. If the /// flag is true, the generator will never be run again, otherwise it will be queued for another /// run next time a target in its watch list is populated. - fn run(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) -> bool; + fn run(&self, witness: &Yo, out_buffer: &mut GeneratedValues) -> bool; } /// Values generated by a generator invocation. @@ -186,10 +357,10 @@ impl GeneratedValues { } /// A generator which runs once after a list of dependencies is present in the witness. -pub trait SimpleGenerator: 'static + Send + Sync { +pub trait SimpleGenerator: 'static + Send + Sync + Debug { fn dependencies(&self) -> Vec; - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues); + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues); } impl> WitnessGenerator for SG { @@ -197,7 +368,7 @@ impl> WitnessGenerator for SG { self.dependencies() } - fn run(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) -> bool { + fn run(&self, witness: &Yo, out_buffer: &mut GeneratedValues) -> bool { if witness.contains_all(&self.dependencies()) { self.run_once(witness, out_buffer); true @@ -219,13 +390,14 @@ impl SimpleGenerator for CopyGenerator { vec![self.src] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let value = witness.get_target(self.src); out_buffer.set_target(self.dst, value); } } /// A generator for including a random value +#[derive(Debug)] pub(crate) struct RandomValueGenerator { pub(crate) target: Target, } @@ -235,7 +407,7 @@ impl SimpleGenerator for RandomValueGenerator { Vec::new() } - fn run_once(&self, _witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, _witness: &Yo, out_buffer: &mut GeneratedValues) { let random_value = F::rand(); out_buffer.set_target(self.target, random_value); @@ -243,6 +415,7 @@ impl SimpleGenerator for RandomValueGenerator { } /// A generator for testing if a value equals zero +#[derive(Debug)] pub(crate) struct NonzeroTestGenerator { pub(crate) to_test: Target, pub(crate) dummy: Target, @@ -253,7 +426,7 @@ impl SimpleGenerator for NonzeroTestGenerator { vec![self.to_test] } - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { let to_test_value = witness.get_target(self.to_test); let dummy_value = if to_test_value == F::ZERO { diff --git a/src/iop/witness.rs b/src/iop/witness.rs index 51b5a182..cfcf5950 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -28,6 +28,7 @@ impl Witness { pub struct PartialWitness { pub(crate) wire_values: Vec>>, pub(crate) virtual_target_values: Vec>, + pub(crate) set_targets: Vec<(Target, F)>, } impl PartialWitness { @@ -35,6 +36,7 @@ impl PartialWitness { PartialWitness { wire_values: vec![vec![None; num_wires]], virtual_target_values: vec![], + set_targets: vec![], } } @@ -148,6 +150,7 @@ impl PartialWitness { } } } + self.set_targets.push((target, value)); } pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 8afec0e4..1fb70bad 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -24,7 +24,7 @@ use crate::plonk::circuit_data::{ VerifierCircuitData, VerifierOnlyCircuitData, }; use crate::plonk::copy_constraint::CopyConstraint; -use crate::plonk::permutation_argument::TargetPartition; +use crate::plonk::permutation_argument::{ForestNode, TargetPartition}; use crate::plonk::plonk_common::PlonkPolynomials; use crate::polynomial::polynomial::PolynomialValues; use crate::util::context_tree::ContextTree; @@ -176,13 +176,13 @@ impl, const D: usize> CircuitBuilder { /// Shorthand for `generate_copy` and `assert_equal`. /// Both elements must be routable, otherwise this method will panic. pub fn route(&mut self, src: Target, dst: Target) { - self.generate_copy(src, dst); + // self.generate_copy(src, dst); self.assert_equal(src, dst); } /// Same as `route` with a named copy constraint. pub fn named_route(&mut self, src: Target, dst: Target, name: String) { - self.generate_copy(src, dst); + // self.generate_copy(src, dst); self.named_assert_equal(src, dst, name); } @@ -263,10 +263,14 @@ impl, const D: usize> CircuitBuilder { } pub fn add_generators(&mut self, generators: Vec>>) { + // for g in &generators { + // println!("{:?}", g); + // } self.generators.extend(generators); } pub fn add_generator>(&mut self, generator: G) { + // println!("{:?}", generator); self.generators.push(Box::new(generator)); } @@ -502,7 +506,11 @@ impl, const D: usize> CircuitBuilder { .collect() } - fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> Vec> { + fn sigma_vecs( + &self, + k_is: &[F], + subgroup: &[F], + ) -> (Vec>, Vec>) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); let mut target_partition = TargetPartition::new(|t| match t { @@ -524,8 +532,11 @@ impl, const D: usize> CircuitBuilder { target_partition.merge(a, b); } - let wire_partition = target_partition.wire_partition(); - wire_partition.get_sigma_polys(degree_log, k_is, subgroup) + let (wire_partition, partition) = target_partition.wire_partition(); + ( + wire_partition.get_sigma_polys(degree_log, k_is, subgroup), + partition, + ) } /// Fill the remaining unused arithmetic operations with zeros, so that all @@ -614,7 +625,7 @@ impl, const D: usize> CircuitBuilder { let constant_vecs = self.constant_polys(&prefixed_gates, num_constants); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); - let sigma_vecs = self.sigma_vecs(&k_is, &subgroup); + let (sigma_vecs, partition) = self.sigma_vecs(&k_is, &subgroup); let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat(); let constants_sigmas_commitment = PolynomialBatchCommitment::from_values( @@ -640,6 +651,7 @@ impl, const D: usize> CircuitBuilder { public_inputs: self.public_inputs, marked_targets: self.marked_targets, num_virtual_targets: self.virtual_target_index, + partition, }; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index e4353c70..f3d13fb4 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -13,6 +13,7 @@ use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; use crate::plonk::copy_constraint::CopyConstraint; +use crate::plonk::permutation_argument::ForestNode; use crate::plonk::proof::ProofWithPublicInputs; use crate::plonk::prover::prove; use crate::plonk::verifier::verify; @@ -155,6 +156,8 @@ pub(crate) struct ProverOnlyCircuitData, const D: usize> { pub marked_targets: Vec>, /// Number of virtual targets used in the circuit. pub num_virtual_targets: usize, + + pub partition: Vec>, } /// Circuit data required by the verifier, but not the prover. diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index 08ebcd48..3a9a93aa 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -11,22 +11,25 @@ use crate::polynomial::polynomial::PolynomialValues; /// Node in the Disjoint Set Forest. #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct ForestNode { - t: T, - parent: usize, - size: usize, - index: usize, +pub struct ForestNode { + pub t: T, + pub parent: usize, + pub size: usize, + pub index: usize, + pub value: Option, } /// Disjoint Set Forest data-structure following https://en.wikipedia.org/wiki/Disjoint-set_data_structure. #[derive(Debug, Clone)] -pub struct TargetPartition usize> { - forest: Vec>, +pub struct TargetPartition usize> { + forest: Vec>, /// Function to compute a node's index in the forest. indices: F, } -impl usize> TargetPartition { +impl usize> + TargetPartition +{ pub fn new(f: F) -> Self { Self { forest: Vec::new(), @@ -42,11 +45,12 @@ impl usize> TargetPartition parent: index, size: 1, index, + value: None, }); } /// Path compression method, see https://en.wikipedia.org/wiki/Disjoint-set_data_structure#Finding_set_representatives. - pub fn find(&mut self, x: ForestNode) -> ForestNode { + pub fn find(&mut self, x: ForestNode) -> ForestNode { if x.parent != x.index { let root = self.find(self.forest[x.parent]); self.forest[x.index].parent = root.index; @@ -80,8 +84,8 @@ impl usize> TargetPartition self.forest[y.index] = y; } } -impl usize> TargetPartition { - pub fn wire_partition(&mut self) -> WirePartitions { +impl usize> TargetPartition { + pub fn wire_partition(mut self) -> (WirePartitions, Vec>) { let mut partition = HashMap::<_, Vec<_>>::new(); let nodes = self.forest.clone(); for x in nodes { @@ -89,7 +93,7 @@ impl usize> TargetPartition { v.push(x.t); } - let mut indices = HashMap::new(); + // let mut indices = HashMap::new(); // Here we keep just the Wire targets, filtering out everything else. let partition = partition .into_values() @@ -102,13 +106,13 @@ impl usize> TargetPartition { .collect::>() }) .collect::>(); - partition.iter().enumerate().for_each(|(i, v)| { - v.iter().for_each(|t| { - indices.insert(*t, i); - }); - }); + // partition.iter().enumerate().for_each(|(i, v)| { + // v.iter().for_each(|t| { + // indices.insert(*t, i); + // }); + // }); - WirePartitions { partition } + (WirePartitions { partition }, self.forest) } } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 0d66daa8..431a3441 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -7,9 +7,12 @@ use crate::fri::commitment::PolynomialBatchCommitment; use crate::hash::hash_types::HashOut; use crate::hash::hashing::hash_n_to_hash; use crate::iop::challenger::Challenger; -use crate::iop::generator::generate_partial_witness; +use crate::iop::generator::{generate_partial_witness, Yo}; +use crate::iop::target::Target; +use crate::iop::wire::Wire; use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; +use crate::plonk::permutation_argument::ForestNode; use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::plonk_common::ZeroPolyOnCoset; use crate::plonk::proof::{Proof, ProofWithPublicInputs}; @@ -32,8 +35,44 @@ pub(crate) fn prove, const D: usize>( let num_challenges = config.num_challenges; let quotient_degree = common_data.quotient_degree(); let degree = common_data.degree(); + println!("{}", prover_data.gate_instances[0].gate_ref.0.id()); + println!("{}", prover_data.gate_instances[1].gate_ref.0.id()); - let mut partial_witness = inputs; + let nrw = config.num_routed_wires; + let nw = config.num_wires; + let nvt = prover_data.num_virtual_targets; + let target_index = move |t: Target| -> usize { + match t { + Target::Wire(Wire { gate, input }) if input < nrw => gate * nrw + input, + Target::Wire(Wire { gate, input }) if input >= nrw => { + degree * nrw + nvt + gate * (nw - nrw) + input - nrw + } + Target::VirtualTarget { index } => degree * nrw + index, + _ => unreachable!(), + } + }; + let mut partial_witness = prover_data.partition.clone(); + let n = partial_witness.len(); + timed!(timing, "fill partition", { + partial_witness.reserve_exact(degree * (config.num_wires - config.num_routed_wires)); + for i in 0..degree * (config.num_wires - config.num_routed_wires) { + partial_witness.push(ForestNode { + t: Target::Wire(Wire { gate: 0, input: 0 }), + parent: n + i, + size: 0, + index: n + i, + value: None, + }) + } + for &(t, v) in &inputs.set_targets { + // println!("{:?} {} {}", t, target_index(t), partial_witness.len()); + let parent = partial_witness[target_index(t)].parent; + // println!("{} {}", parent, partial_witness.len()); + partial_witness[parent].value = Some(v); + } + }); + // let mut partial_witness = inputs; + let mut partial_witness = Yo(partial_witness, Box::new(target_index)); timed!( timing, &format!("run {} generators", prover_data.generators.len()), @@ -50,17 +89,17 @@ pub(crate) fn prove, const D: usize>( let public_inputs = partial_witness.get_targets(&prover_data.public_inputs); let public_inputs_hash = hash_n_to_hash(public_inputs.clone(), true); - // Display the marked targets for debugging purposes. - for m in &prover_data.marked_targets { - m.display(&partial_witness); - } - - timed!( - timing, - "check copy constraints", - partial_witness - .check_copy_constraints(&prover_data.copy_constraints, &prover_data.gate_instances)? - ); + // // Display the marked targets for debugging purposes. + // for m in &prover_data.marked_targets { + // m.display(&partial_witness); + // } + // + // timed!( + // timing, + // "check copy constraints", + // partial_witness + // .check_copy_constraints(&prover_data.copy_constraints, &prover_data.gate_instances)? + // ); let witness = timed!( timing, From af0ea25fc86aca58fe31172be72dd0f015a08f90 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 19 Aug 2021 15:59:05 +0200 Subject: [PATCH 02/19] more trials --- src/iop/generator.rs | 30 +++++++++++++++++++----------- src/plonk/prover.rs | 11 +++++++++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 71b9aa3a..90e0f7c4 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::convert::{identity, TryInto}; use std::fmt::Debug; @@ -198,6 +199,11 @@ pub(crate) fn generate_partial_witness( } }); + let mut parents: HashMap> = HashMap::new(); + for i in 0..witness.0.len() { + parents.entry(witness.0[i].parent).or_default().push(i); + } + // Build a list of "pending" generators which are queued to be run. Initially, all generators // are queued. let mut pending_generator_indices: Vec<_> = (0..generators.len()).collect(); @@ -217,14 +223,20 @@ pub(crate) fn generate_partial_witness( } let finished = generators[generator_idx].run(&witness, &mut buffer); + // dbg!(&generators[generator_idx], &buffer); if finished { generator_is_expired[generator_idx] = true; } // Enqueue unfinished generators that were watching one of the newly populated targets. for &(watch, _) in &buffer.target_values { - for &watching_generator_idx in &generator_indices_by_watches[witness.1(watch)] { - next_pending_generator_indices.push(watching_generator_idx); + let parent = witness.0[witness.1(watch)].parent; + for &yo in &parents[&parent] { + for &watching_generator_idx in &generator_indices_by_watches[yo] { + if !generator_is_expired[watching_generator_idx] { + next_pending_generator_indices.push(watching_generator_idx); + } + } } } @@ -234,17 +246,12 @@ pub(crate) fn generate_partial_witness( pending_generator_indices = next_pending_generator_indices; } - for i in 0..degree { - for j in 0..num_wires { - if !witness.contains(Target::Wire(Wire { gate: i, input: j })) { - println!("{} {}", i, j); - } - } - } // for i in 0..generator_is_expired.len() { // if !generator_is_expired[i] { - // println!("{:?}", generators[i]); - // println!("{:?}", generators[i].watch_list()); + // println!("{}: {:?}", i, generators[i]); + // for a in generators[i].watch_list() { + // println!("{:?} {}", a, witness.contains(a)); + // } // } // } assert!( @@ -266,6 +273,7 @@ pub trait WitnessGenerator: 'static + Send + Sync + Debug { } /// Values generated by a generator invocation. +#[derive(Debug)] pub struct GeneratedValues { pub(crate) target_values: Vec<(Target, F)>, } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 431a3441..558ca290 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -35,8 +35,9 @@ pub(crate) fn prove, const D: usize>( let num_challenges = config.num_challenges; let quotient_degree = common_data.quotient_degree(); let degree = common_data.degree(); - println!("{}", prover_data.gate_instances[0].gate_ref.0.id()); - println!("{}", prover_data.gate_instances[1].gate_ref.0.id()); + // for i in 0..prover_data.gate_instances.len() { + // println!("{}: {}", i, prover_data.gate_instances[i].gate_ref.0.id()); + // } let nrw = config.num_routed_wires; let nw = config.num_wires; @@ -71,6 +72,12 @@ pub(crate) fn prove, const D: usize>( partial_witness[parent].value = Some(v); } }); + // let t = partial_witness[target_index(Target::Wire(Wire { + // gate: 14, + // input: 16, + // }))]; + // dbg!(t); + // dbg!(partial_witness[t.parent]); // let mut partial_witness = inputs; let mut partial_witness = Yo(partial_witness, Box::new(target_index)); timed!( From 98559c3256d84d0f196c788dd75590dc3ae6c30d Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 09:20:03 +0200 Subject: [PATCH 03/19] Working --- src/iop/generator.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 90e0f7c4..f86d9f30 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -199,11 +199,6 @@ pub(crate) fn generate_partial_witness( } }); - let mut parents: HashMap> = HashMap::new(); - for i in 0..witness.0.len() { - parents.entry(witness.0[i].parent).or_default().push(i); - } - // Build a list of "pending" generators which are queued to be run. Initially, all generators // are queued. let mut pending_generator_indices: Vec<_> = (0..generators.len()).collect(); @@ -213,8 +208,10 @@ pub(crate) fn generate_partial_witness( let mut buffer = GeneratedValues::empty(); + let mut count = 0; // Keep running generators until no generators are queued. - while !pending_generator_indices.is_empty() { + // while !pending_generator_indices.is_empty() { + while !generator_is_expired.iter().all(|&x| x) { let mut next_pending_generator_indices = Vec::new(); for &generator_idx in &pending_generator_indices { @@ -226,16 +223,15 @@ pub(crate) fn generate_partial_witness( // dbg!(&generators[generator_idx], &buffer); if finished { generator_is_expired[generator_idx] = true; + } else { + count += 1; } // Enqueue unfinished generators that were watching one of the newly populated targets. for &(watch, _) in &buffer.target_values { - let parent = witness.0[witness.1(watch)].parent; - for &yo in &parents[&parent] { - for &watching_generator_idx in &generator_indices_by_watches[yo] { - if !generator_is_expired[watching_generator_idx] { - next_pending_generator_indices.push(watching_generator_idx); - } + for &watching_generator_idx in &generator_indices_by_watches[witness.1(watch)] { + if !generator_is_expired[watching_generator_idx] { + next_pending_generator_indices.push(watching_generator_idx); } } } @@ -243,9 +239,15 @@ pub(crate) fn generate_partial_witness( witness.extend(buffer.target_values.drain(..)); } - pending_generator_indices = next_pending_generator_indices; + // pending_generator_indices = next_pending_generator_indices; + pending_generator_indices = if next_pending_generator_indices.is_empty() { + (0..generators.len()).collect() + } else { + next_pending_generator_indices + }; } + dbg!(count); // for i in 0..generator_is_expired.len() { // if !generator_is_expired[i] { // println!("{}: {:?}", i, generators[i]); From a44bf9ffd8cbd044fa4d3b58803c4964a9dd75b9 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 09:50:07 +0200 Subject: [PATCH 04/19] Added witness trait --- src/gadgets/arithmetic_extension.rs | 2 +- src/gadgets/select.rs | 2 +- src/gates/gate_testing.rs | 2 +- src/hash/merkle_proofs.rs | 2 +- src/iop/generator.rs | 6 +- src/iop/witness.rs | 335 ++++++++++++---------------- src/plonk/prover.rs | 6 +- src/plonk/recursive_verifier.rs | 2 +- src/util/marking.rs | 2 +- 9 files changed, 151 insertions(+), 208 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index f7b8eee5..8ed0e934 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -504,7 +504,7 @@ mod tests { use crate::field::extension_field::algebra::ExtensionAlgebra; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field_types::Field; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; diff --git a/src/gadgets/select.rs b/src/gadgets/select.rs index 3be3455c..3f0e001d 100644 --- a/src/gadgets/select.rs +++ b/src/gadgets/select.rs @@ -43,7 +43,7 @@ mod tests { use crate::field::crandall_field::CrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::field_types::Field; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index 4d336454..0e773aa0 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -4,7 +4,7 @@ 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::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/hash/merkle_proofs.rs b/src/hash/merkle_proofs.rs index 7a7b358d..5f333f4e 100644 --- a/src/hash/merkle_proofs.rs +++ b/src/hash/merkle_proofs.rs @@ -221,7 +221,7 @@ mod tests { use super::*; use crate::field::crandall_field::CrandallField; use crate::hash::merkle_tree::MerkleTree; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; diff --git a/src/iop/generator.rs b/src/iop/generator.rs index f86d9f30..62fe4d26 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -9,7 +9,7 @@ use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, Witness}; +use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; use crate::plonk::permutation_argument::ForestNode; use crate::timed; use crate::util::timing::TimingTree; @@ -159,7 +159,7 @@ impl Yo { } } - pub fn full_witness(self, degree: usize, num_wires: usize) -> Witness { + pub fn full_witness(self, degree: usize, num_wires: usize) -> MatrixWitness { let mut wire_values = vec![vec![F::ZERO; degree]; num_wires]; // assert!(self.wire_values.len() <= degree); for i in 0..degree { @@ -168,7 +168,7 @@ impl Yo { wire_values[j][i] = self.0[self.0[self.1(t)].parent].value.unwrap_or(F::ZERO); } } - Witness { wire_values } + MatrixWitness { wire_values } } } diff --git a/src/iop/witness.rs b/src/iop/witness.rs index cfcf5950..5d1441ff 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -13,12 +13,143 @@ use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; use crate::plonk::copy_constraint::CopyConstraint; +pub trait Witness { + fn try_get_target(&self, target: Target) -> Option; + + fn set_target(&mut self, target: Target, value: F); + + fn get_target(&self, target: Target) -> F { + self.try_get_target(target).unwrap() + } + + fn get_targets(&self, targets: &[Target]) -> Vec { + targets.iter().map(|&t| self.get_target(t)).collect() + } + + fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension + where + F: Extendable, + { + F::Extension::from_basefield_array( + self.get_targets(&et.to_target_array()).try_into().unwrap(), + ) + } + + fn get_extension_targets(&self, ets: &[ExtensionTarget]) -> Vec + where + F: Extendable, + { + ets.iter() + .map(|&et| self.get_extension_target(et)) + .collect() + } + + fn get_bool_target(&self, target: BoolTarget) -> bool { + let value = self.get_target(target.target).to_canonical_u64(); + match value { + 0 => false, + 1 => true, + _ => panic!("not a bool"), + } + } + + fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { + HashOut { + elements: self.get_targets(&ht.elements).try_into().unwrap(), + } + } + + fn get_wire(&self, wire: Wire) -> F { + self.get_target(Target::Wire(wire)) + } + + fn try_get_wire(&self, wire: Wire) -> Option { + self.try_get_target(Target::Wire(wire)) + } + + fn contains(&self, target: Target) -> bool { + self.try_get_target(target).is_some() + } + + fn contains_all(&self, targets: &[Target]) -> bool { + targets.iter().all(|&t| self.contains(t)) + } + + fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { + ht.elements + .iter() + .zip(value.elements) + .for_each(|(&t, x)| self.set_target(t, x)); + } + + fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap) { + for (ht, h) in ct.0.iter().zip(&value.0) { + self.set_hash_target(*ht, *h); + } + } + + fn set_extension_target(&mut self, et: ExtensionTarget, value: F::Extension) + where + F: Extendable, + { + let limbs = value.to_basefield_array(); + (0..D).for_each(|i| { + self.set_target(et.0[i], limbs[i]); + }); + } + + 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)); + } + + fn set_bool_target(&mut self, target: BoolTarget, value: bool) { + self.set_target(target.target, F::from_bool(value)) + } + + fn set_wire(&mut self, wire: Wire, value: F) { + self.set_target(Target::Wire(wire), value) + } + + fn set_wires(&mut self, wires: W, values: &[F]) + where + W: IntoIterator, + { + // If we used itertools, we could use zip_eq for extra safety. + for (wire, &value) in wires.into_iter().zip(values) { + self.set_wire(wire, value); + } + } + + fn set_ext_wires(&mut self, wires: W, value: F::Extension) + where + F: Extendable, + W: IntoIterator, + { + self.set_wires(wires, &value.to_basefield_array()); + } + + fn extend>(&mut self, pairs: I) { + for (t, v) in pairs { + self.set_target(t, v); + } + } +} + #[derive(Clone, Debug)] -pub struct Witness { +pub struct MatrixWitness { pub(crate) wire_values: Vec>, } -impl Witness { +impl MatrixWitness { pub fn get_wire(&self, gate: usize, input: usize) -> F { self.wire_values[input][gate] } @@ -39,86 +170,17 @@ impl PartialWitness { set_targets: vec![], } } +} - pub fn get_target(&self, target: Target) -> F { +impl Witness for PartialWitness { + fn try_get_target(&self, target: Target) -> Option { match target { - Target::Wire(Wire { gate, input }) => self.wire_values[gate][input].unwrap(), - Target::VirtualTarget { index } => self.virtual_target_values[index].unwrap(), + Target::Wire(Wire { gate, input }) => *self.wire_values.get(gate)?.get(input)?, + Target::VirtualTarget { index } => *self.virtual_target_values.get(index)?, } } - pub fn get_targets(&self, targets: &[Target]) -> Vec { - targets.iter().map(|&t| self.get_target(t)).collect() - } - - pub fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension - where - F: Extendable, - { - F::Extension::from_basefield_array( - self.get_targets(&et.to_target_array()).try_into().unwrap(), - ) - } - - pub fn get_extension_targets( - &self, - ets: &[ExtensionTarget], - ) -> Vec - where - F: Extendable, - { - ets.iter() - .map(|&et| self.get_extension_target(et)) - .collect() - } - - pub fn get_bool_target(&self, target: BoolTarget) -> bool { - let value = self.get_target(target.target).to_canonical_u64(); - match value { - 0 => false, - 1 => true, - _ => panic!("not a bool"), - } - } - - pub fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { - HashOut { - elements: self.get_targets(&ht.elements).try_into().unwrap(), - } - } - - pub fn try_get_target(&self, target: Target) -> Option { - match target { - Target::Wire(Wire { gate, input }) => self.wire_values[gate][input], - Target::VirtualTarget { index } => self.virtual_target_values[index], - } - } - - pub fn get_wire(&self, wire: Wire) -> F { - self.get_target(Target::Wire(wire)) - } - - pub fn try_get_wire(&self, wire: Wire) -> Option { - self.try_get_target(Target::Wire(wire)) - } - - pub fn contains(&self, target: Target) -> bool { - match target { - Target::Wire(Wire { gate, input }) => { - self.wire_values.len() > gate && self.wire_values[gate][input].is_some() - } - Target::VirtualTarget { index } => { - self.virtual_target_values.len() > index - && self.virtual_target_values[index].is_some() - } - } - } - - pub fn contains_all(&self, targets: &[Target]) -> bool { - targets.iter().all(|&t| self.contains(t)) - } - - pub fn set_target(&mut self, target: Target, value: F) { + fn set_target(&mut self, target: Target, value: F) { match target { Target::Wire(Wire { gate, input }) => { if gate >= self.wire_values.len() { @@ -152,123 +214,4 @@ impl PartialWitness { } self.set_targets.push((target, value)); } - - pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { - ht.elements - .iter() - .zip(value.elements) - .for_each(|(&t, x)| self.set_target(t, x)); - } - - pub fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap) { - for (ht, h) in ct.0.iter().zip(&value.0) { - self.set_hash_target(*ht, *h); - } - } - - pub fn set_extension_target( - &mut self, - et: ExtensionTarget, - value: F::Extension, - ) where - F: Extendable, - { - let limbs = value.to_basefield_array(); - (0..D).for_each(|i| { - self.set_target(et.0[i], limbs[i]); - }); - } - - 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_bool_target(&mut self, target: BoolTarget, value: bool) { - self.set_target(target.target, F::from_bool(value)) - } - - pub fn set_wire(&mut self, wire: Wire, value: F) { - self.set_target(Target::Wire(wire), value) - } - - pub fn set_wires(&mut self, wires: W, values: &[F]) - where - W: IntoIterator, - { - // If we used itertools, we could use zip_eq for extra safety. - for (wire, &value) in wires.into_iter().zip(values) { - self.set_wire(wire, value); - } - } - - pub fn set_ext_wires(&mut self, wires: W, value: F::Extension) - where - F: Extendable, - W: IntoIterator, - { - self.set_wires(wires, &value.to_basefield_array()); - } - - pub fn extend>(&mut self, pairs: I) { - for (t, v) in pairs { - self.set_target(t, v); - } - } - - pub fn full_witness(self, degree: usize, num_wires: usize) -> Witness { - let mut wire_values = vec![vec![F::ZERO; degree]; num_wires]; - assert!(self.wire_values.len() <= degree); - for i in 0..self.wire_values.len() { - for j in 0..num_wires { - wire_values[j][i] = self.wire_values[i][j].unwrap_or(F::ZERO); - } - } - Witness { wire_values } - } - - /// Checks that the copy constraints are satisfied in the witness. - pub fn check_copy_constraints( - &self, - copy_constraints: &[CopyConstraint], - gate_instances: &[GateInstance], - ) -> Result<()> - where - F: Extendable, - { - for CopyConstraint { pair: (a, b), name } in copy_constraints { - let va = self.try_get_target(*a).unwrap_or(F::ZERO); - let vb = self.try_get_target(*b).unwrap_or(F::ZERO); - let desc = |t: &Target| -> String { - match t { - Target::Wire(Wire { gate, input }) => format!( - "wire {} of gate #{} (`{}`)", - input, - gate, - gate_instances[*gate].gate_ref.0.id() - ), - Target::VirtualTarget { index } => format!("{}-th virtual target", index), - } - }; - ensure!( - va == vb, - "Copy constraint '{}' between {} and {} is not satisfied. \ - Got values of {} and {} respectively.", - name, - desc(a), - desc(b), - va, - vb - ); - } - Ok(()) - } } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 558ca290..49b93190 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -10,7 +10,7 @@ use crate::iop::challenger::Challenger; use crate::iop::generator::{generate_partial_witness, Yo}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, Witness}; +use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; use crate::plonk::permutation_argument::ForestNode; use crate::plonk::plonk_common::PlonkPolynomials; @@ -268,7 +268,7 @@ pub(crate) fn prove, const D: usize>( /// Compute the partial products used in the `Z` polynomials. fn all_wires_permutation_partial_products, const D: usize>( - witness: &Witness, + witness: &MatrixWitness, betas: &[F], gammas: &[F], prover_data: &ProverOnlyCircuitData, @@ -291,7 +291,7 @@ fn all_wires_permutation_partial_products, const D: usize>( /// Returns the polynomials interpolating `partial_products(f / g)` /// where `f, g` are the products in the definition of `Z`: `Z(g^i) = f / g`. fn wires_permutation_partial_products, const D: usize>( - witness: &Witness, + witness: &MatrixWitness, beta: F, gamma: F, prover_data: &ProverOnlyCircuitData, diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 5f45af7e..97ebd84c 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -137,7 +137,7 @@ mod tests { use crate::fri::FriConfig; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::hash::merkle_proofs::MerkleProofTarget; - use crate::iop::witness::PartialWitness; + use crate::iop::witness::{PartialWitness, Witness}; use crate::plonk::proof::{OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs}; use crate::plonk::verifier::verify; use crate::util::log2_strict; diff --git a/src/util/marking.rs b/src/util/marking.rs index e98f7cbc..6e0ad993 100644 --- a/src/util/marking.rs +++ b/src/util/marking.rs @@ -2,7 +2,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::hash::hash_types::HashOutTarget; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, Witness}; /// Enum representing all types of targets, so that they can be marked. #[derive(Clone)] From c6cf5cf130649c0e9740f08ef69ca84a6f0189c1 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 09:55:49 +0200 Subject: [PATCH 05/19] Move PartitionWitness --- src/gadgets/arithmetic_extension.rs | 6 +- src/gadgets/range_check.rs | 6 +- src/gadgets/split_base.rs | 6 +- src/gadgets/split_join.rs | 8 +- src/gates/arithmetic.rs | 6 +- src/gates/base_sum.rs | 6 +- src/gates/constant.rs | 6 +- src/gates/exponentiation.rs | 6 +- src/gates/gmimc.rs | 6 +- src/gates/insertion.rs | 6 +- src/gates/interpolation.rs | 6 +- src/gates/random_access.rs | 6 +- src/gates/reducing.rs | 6 +- src/iop/generator.rs | 174 ++-------------------------- src/iop/witness.rs | 31 +++++ src/plonk/prover.rs | 6 +- 16 files changed, 82 insertions(+), 209 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 8ed0e934..b53f03a6 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -5,9 +5,9 @@ use crate::field::extension_field::FieldExtension; use crate::field::extension_field::{Extendable, OEF}; use crate::field::field_types::Field; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; @@ -447,7 +447,7 @@ impl, const D: usize> SimpleGenerator for QuotientGeneratorE deps } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let num = witness.get_extension_target(self.numerator); let dem = witness.get_extension_target(self.denominator); let quotient = num / dem; diff --git a/src/gadgets/range_check.rs b/src/gadgets/range_check.rs index c03dae7b..4be8f80e 100644 --- a/src/gadgets/range_check.rs +++ b/src/gadgets/range_check.rs @@ -1,9 +1,9 @@ use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; impl, const D: usize> CircuitBuilder { @@ -56,7 +56,7 @@ impl SimpleGenerator for LowHighGenerator { vec![self.integer] } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let integer_value = witness.get_target(self.integer).to_canonical_u64(); let low = integer_value & ((1 << self.n_log) - 1); let high = integer_value >> self.n_log; diff --git a/src/gadgets/split_base.rs b/src/gadgets/split_base.rs index cca2a166..716472f5 100644 --- a/src/gadgets/split_base.rs +++ b/src/gadgets/split_base.rs @@ -3,9 +3,9 @@ use std::borrow::Borrow; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; impl, const D: usize> CircuitBuilder { @@ -68,7 +68,7 @@ impl SimpleGenerator for BaseSumGenerator { self.limbs.iter().map(|b| b.target).collect() } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let sum = self .limbs .iter() diff --git a/src/gadgets/split_join.rs b/src/gadgets/split_join.rs index 875ead00..45c87de9 100644 --- a/src/gadgets/split_join.rs +++ b/src/gadgets/split_join.rs @@ -1,9 +1,9 @@ use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::ceil_div_usize; @@ -68,7 +68,7 @@ impl SimpleGenerator for SplitGenerator { vec![self.integer] } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let mut integer_value = witness.get_target(self.integer).to_canonical_u64(); for &b in &self.bits { @@ -96,7 +96,7 @@ impl SimpleGenerator for WireSplitGenerator { vec![self.integer] } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let mut integer_value = witness.get_target(self.integer).to_canonical_u64(); for &gate in &self.gates { diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 159628e1..12be0bc2 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -4,9 +4,9 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -157,7 +157,7 @@ impl, const D: usize> SimpleGenerator for ArithmeticExtensio .collect() } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let extract_extension = |range: Range| -> F::Extension { let t = ExtensionTarget::from_range(self.gate_index, range); witness.get_extension_target(t) diff --git a/src/gates/base_sum.rs b/src/gates/base_sum.rs index c46bfee1..e53b72f6 100644 --- a/src/gates/base_sum.rs +++ b/src/gates/base_sum.rs @@ -4,9 +4,9 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_recursive}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -132,7 +132,7 @@ impl SimpleGenerator for BaseSplitGenerator { vec![Target::wire(self.gate_index, BaseSumGate::::WIRE_SUM)] } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let sum_value = witness .get_target(Target::wire(self.gate_index, BaseSumGate::::WIRE_SUM)) .to_canonical_u64() as usize; diff --git a/src/gates/constant.rs b/src/gates/constant.rs index 94d5fa03..eb4b5b12 100644 --- a/src/gates/constant.rs +++ b/src/gates/constant.rs @@ -2,10 +2,10 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -85,7 +85,7 @@ impl SimpleGenerator for ConstantGenerator { Vec::new() } - fn run_once(&self, _witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let wire = Wire { gate: self.gate_index, input: ConstantGate::WIRE_OUTPUT, diff --git a/src/gates/exponentiation.rs b/src/gates/exponentiation.rs index 69827907..e85c361e 100644 --- a/src/gates/exponentiation.rs +++ b/src/gates/exponentiation.rs @@ -4,10 +4,10 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -218,7 +218,7 @@ impl, const D: usize> SimpleGenerator for ExponentiationGene deps } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 2e0f652f..6bf868c0 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -5,10 +5,10 @@ use crate::field::extension_field::Extendable; use crate::field::field_types::Field; use crate::gates::gate::Gate; use crate::hash::gmimc::gmimc_automatic_constants; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -264,7 +264,7 @@ impl, const D: usize, const R: usize> SimpleGenerator .collect() } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let mut state = (0..W) .map(|i| { witness.get_wire(Wire { diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index d1c2ea22..91d71d2e 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -6,10 +6,10 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -261,7 +261,7 @@ impl, const D: usize> SimpleGenerator for InsertionGenerator deps } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index a9cd7d38..4eabbe31 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -8,10 +8,10 @@ use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::interpolation::interpolant; use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::polynomial::polynomial::PolynomialCoeffs; @@ -240,7 +240,7 @@ impl, const D: usize> SimpleGenerator for InterpolationGener deps } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let n = self.gate.num_points; let local_wire = |input| Wire { diff --git a/src/gates/random_access.rs b/src/gates/random_access.rs index 561bfbfd..85da3eaf 100644 --- a/src/gates/random_access.rs +++ b/src/gates/random_access.rs @@ -5,10 +5,10 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -208,7 +208,7 @@ impl, const D: usize> SimpleGenerator for RandomAccessGenera deps } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let local_wire = |input| Wire { gate: self.gate_index, input, diff --git a/src/gates/reducing.rs b/src/gates/reducing.rs index 64987e79..01c05306 100644 --- a/src/gates/reducing.rs +++ b/src/gates/reducing.rs @@ -4,9 +4,9 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator, Yo}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -174,7 +174,7 @@ impl, const D: usize> SimpleGenerator for ReducingGenerator< .collect() } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let extract_extension = |range: Range| -> F::Extension { let t = ExtensionTarget::from_range(self.gate_index, range); witness.get_extension_target(t) diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 62fe4d26..b6d89c5d 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -9,173 +9,15 @@ use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; -use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; +use crate::iop::witness::{MatrixWitness, PartialWitness, PartitionWitness, Witness}; use crate::plonk::permutation_argument::ForestNode; use crate::timed; use crate::util::timing::TimingTree; -pub struct Yo( - pub Vec>, - pub Box usize>, -); -impl Yo { - pub fn get_target(&self, target: Target) -> F { - self.0[self.0[self.1(target)].parent].value.unwrap() - } - - pub fn get_targets(&self, targets: &[Target]) -> Vec { - targets.iter().map(|&t| self.get_target(t)).collect() - } - - pub fn get_extension_target(&self, et: ExtensionTarget) -> F::Extension - where - F: Extendable, - { - F::Extension::from_basefield_array( - self.get_targets(&et.to_target_array()).try_into().unwrap(), - ) - } - - pub fn get_extension_targets( - &self, - ets: &[ExtensionTarget], - ) -> Vec - where - F: Extendable, - { - ets.iter() - .map(|&et| self.get_extension_target(et)) - .collect() - } - - pub fn get_bool_target(&self, target: BoolTarget) -> bool { - let value = self.get_target(target.target).to_canonical_u64(); - match value { - 0 => false, - 1 => true, - _ => panic!("not a bool"), - } - } - - pub fn get_hash_target(&self, ht: HashOutTarget) -> HashOut { - HashOut { - elements: self.get_targets(&ht.elements).try_into().unwrap(), - } - } - - pub fn try_get_target(&self, target: Target) -> Option { - self.0[self.0[self.1(target)].parent].value - } - - pub fn get_wire(&self, wire: Wire) -> F { - self.get_target(Target::Wire(wire)) - } - - pub fn try_get_wire(&self, wire: Wire) -> Option { - self.try_get_target(Target::Wire(wire)) - } - - pub fn contains(&self, target: Target) -> bool { - self.0[self.0[self.1(target)].parent].value.is_some() - } - - pub fn contains_all(&self, targets: &[Target]) -> bool { - targets.iter().all(|&t| self.contains(t)) - } - - pub fn set_target(&mut self, target: Target, value: F) { - let i = self.0[self.1(target)].parent; - self.0[i].value = Some(value); - } - - pub fn set_hash_target(&mut self, ht: HashOutTarget, value: HashOut) { - ht.elements - .iter() - .zip(value.elements) - .for_each(|(&t, x)| self.set_target(t, x)); - } - - pub fn set_cap_target(&mut self, ct: &MerkleCapTarget, value: &MerkleCap) { - for (ht, h) in ct.0.iter().zip(&value.0) { - self.set_hash_target(*ht, *h); - } - } - - pub fn set_extension_target( - &mut self, - et: ExtensionTarget, - value: F::Extension, - ) where - F: Extendable, - { - let limbs = value.to_basefield_array(); - (0..D).for_each(|i| { - self.set_target(et.0[i], limbs[i]); - }); - } - - 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_bool_target(&mut self, target: BoolTarget, value: bool) { - self.set_target(target.target, F::from_bool(value)) - } - - pub fn set_wire(&mut self, wire: Wire, value: F) { - self.set_target(Target::Wire(wire), value) - } - - pub fn set_wires(&mut self, wires: W, values: &[F]) - where - W: IntoIterator, - { - // If we used itertools, we could use zip_eq for extra safety. - for (wire, &value) in wires.into_iter().zip(values) { - self.set_wire(wire, value); - } - } - - pub fn set_ext_wires(&mut self, wires: W, value: F::Extension) - where - F: Extendable, - W: IntoIterator, - { - self.set_wires(wires, &value.to_basefield_array()); - } - - pub fn extend>(&mut self, pairs: I) { - for (t, v) in pairs { - self.set_target(t, v); - } - } - - pub fn full_witness(self, degree: usize, num_wires: usize) -> MatrixWitness { - let mut wire_values = vec![vec![F::ZERO; degree]; num_wires]; - // assert!(self.wire_values.len() <= degree); - for i in 0..degree { - for j in 0..num_wires { - let t = Target::Wire(Wire { gate: i, input: j }); - wire_values[j][i] = self.0[self.0[self.1(t)].parent].value.unwrap_or(F::ZERO); - } - } - MatrixWitness { wire_values } - } -} - /// Given a `PartialWitness` that has only inputs set, populates the rest of the witness using the /// given set of generators. pub(crate) fn generate_partial_witness( - witness: &mut Yo, + witness: &mut PartitionWitness, generators: &[Box>], num_wires: usize, degree: usize, @@ -271,7 +113,7 @@ pub trait WitnessGenerator: 'static + Send + Sync + Debug { /// Run this generator, returning a flag indicating whether the generator is finished. If the /// flag is true, the generator will never be run again, otherwise it will be queued for another /// run next time a target in its watch list is populated. - fn run(&self, witness: &Yo, out_buffer: &mut GeneratedValues) -> bool; + fn run(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) -> bool; } /// Values generated by a generator invocation. @@ -370,7 +212,7 @@ impl GeneratedValues { pub trait SimpleGenerator: 'static + Send + Sync + Debug { fn dependencies(&self) -> Vec; - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues); + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues); } impl> WitnessGenerator for SG { @@ -378,7 +220,7 @@ impl> WitnessGenerator for SG { self.dependencies() } - fn run(&self, witness: &Yo, out_buffer: &mut GeneratedValues) -> bool { + fn run(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) -> bool { if witness.contains_all(&self.dependencies()) { self.run_once(witness, out_buffer); true @@ -400,7 +242,7 @@ impl SimpleGenerator for CopyGenerator { vec![self.src] } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let value = witness.get_target(self.src); out_buffer.set_target(self.dst, value); } @@ -417,7 +259,7 @@ impl SimpleGenerator for RandomValueGenerator { Vec::new() } - fn run_once(&self, _witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let random_value = F::rand(); out_buffer.set_target(self.target, random_value); @@ -436,7 +278,7 @@ impl SimpleGenerator for NonzeroTestGenerator { vec![self.to_test] } - fn run_once(&self, witness: &Yo, out_buffer: &mut GeneratedValues) { + fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { let to_test_value = witness.get_target(self.to_test); let dummy_value = if to_test_value == F::ZERO { diff --git a/src/iop/witness.rs b/src/iop/witness.rs index 5d1441ff..e65f8c40 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -12,6 +12,7 @@ use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; use crate::plonk::copy_constraint::CopyConstraint; +use crate::plonk::permutation_argument::ForestNode; pub trait Witness { fn try_get_target(&self, target: Target) -> Option; @@ -215,3 +216,33 @@ impl Witness for PartialWitness { self.set_targets.push((target, value)); } } + +pub struct PartitionWitness( + pub Vec>, + pub Box usize>, +); + +impl Witness for PartitionWitness { + fn try_get_target(&self, target: Target) -> Option { + self.0[self.0[self.1(target)].parent].value + } + + fn set_target(&mut self, target: Target, value: F) { + let i = self.0[self.1(target)].parent; + self.0[i].value = Some(value); + } +} + +impl PartitionWitness { + pub fn full_witness(self, degree: usize, num_wires: usize) -> MatrixWitness { + let mut wire_values = vec![vec![F::ZERO; degree]; num_wires]; + // assert!(self.wire_values.len() <= degree); + for i in 0..degree { + for j in 0..num_wires { + let t = Target::Wire(Wire { gate: i, input: j }); + wire_values[j][i] = self.0[self.0[self.1(t)].parent].value.unwrap_or(F::ZERO); + } + } + MatrixWitness { wire_values } + } +} diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 49b93190..1f44547e 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -7,10 +7,10 @@ use crate::fri::commitment::PolynomialBatchCommitment; use crate::hash::hash_types::HashOut; use crate::hash::hashing::hash_n_to_hash; use crate::iop::challenger::Challenger; -use crate::iop::generator::{generate_partial_witness, Yo}; +use crate::iop::generator::generate_partial_witness; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; +use crate::iop::witness::{MatrixWitness, PartialWitness, PartitionWitness, Witness}; use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; use crate::plonk::permutation_argument::ForestNode; use crate::plonk::plonk_common::PlonkPolynomials; @@ -79,7 +79,7 @@ pub(crate) fn prove, const D: usize>( // dbg!(t); // dbg!(partial_witness[t.parent]); // let mut partial_witness = inputs; - let mut partial_witness = Yo(partial_witness, Box::new(target_index)); + let mut partial_witness = PartitionWitness(partial_witness, Box::new(target_index)); timed!( timing, &format!("run {} generators", prover_data.generators.len()), From 6584734928a3ca60c15059956b634d3613e07c5c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 10:44:19 +0200 Subject: [PATCH 06/19] Cleaning --- src/iop/generator.rs | 8 +-- src/iop/witness.rs | 46 ++++++++++++----- src/lib.rs | 1 + src/plonk/circuit_builder.rs | 13 +++-- src/plonk/circuit_data.rs | 4 +- src/plonk/permutation_argument.rs | 86 +++++++++++++------------------ src/plonk/prover.rs | 68 +++++------------------- src/util/marking.rs | 6 +-- 8 files changed, 100 insertions(+), 132 deletions(-) diff --git a/src/iop/generator.rs b/src/iop/generator.rs index b6d89c5d..4aa5d6e1 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -30,13 +30,13 @@ pub(crate) fn generate_partial_witness( // Target::VirtualTarget { index } => degree * num_wires + index, // } // }; - let max_target_index = witness.0.len(); + let max_target_index = witness.nodes.len(); // Index generator indices by their watched targets. let mut generator_indices_by_watches = vec![Vec::new(); max_target_index]; timed!(timing, "index generators by their watched targets", { for (i, generator) in generators.iter().enumerate() { for watch in generator.watch_list() { - generator_indices_by_watches[witness.1(watch)].push(i); + generator_indices_by_watches[witness.target_index(watch)].push(i); } } }); @@ -71,7 +71,9 @@ pub(crate) fn generate_partial_witness( // Enqueue unfinished generators that were watching one of the newly populated targets. for &(watch, _) in &buffer.target_values { - for &watching_generator_idx in &generator_indices_by_watches[witness.1(watch)] { + for &watching_generator_idx in + &generator_indices_by_watches[witness.target_index(watch)] + { if !generator_is_expired[watching_generator_idx] { next_pending_generator_indices.push(watching_generator_idx); } diff --git a/src/iop/witness.rs b/src/iop/witness.rs index e65f8c40..8241c7d5 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -217,32 +217,50 @@ impl Witness for PartialWitness { } } -pub struct PartitionWitness( - pub Vec>, - pub Box usize>, -); +#[derive(Clone)] +pub struct PartitionWitness { + pub nodes: Vec>, + pub num_wires: usize, + pub num_routed_wires: usize, + pub degree: usize, +} impl Witness for PartitionWitness { fn try_get_target(&self, target: Target) -> Option { - self.0[self.0[self.1(target)].parent].value + self.nodes[self.nodes[self.target_index(target)].parent].value } fn set_target(&mut self, target: Target, value: F) { - let i = self.0[self.1(target)].parent; - self.0[i].value = Some(value); + let i = self.nodes[self.target_index(target)].parent; + self.nodes[i].value = Some(value); } } impl PartitionWitness { - pub fn full_witness(self, degree: usize, num_wires: usize) -> MatrixWitness { - let mut wire_values = vec![vec![F::ZERO; degree]; num_wires]; - // assert!(self.wire_values.len() <= degree); - for i in 0..degree { - for j in 0..num_wires { - let t = Target::Wire(Wire { gate: i, input: j }); - wire_values[j][i] = self.0[self.0[self.1(t)].parent].value.unwrap_or(F::ZERO); + pub const fn target_index(&self, target: Target) -> usize { + match target { + Target::Wire(Wire { gate, input }) => gate * self.num_wires + input, + Target::VirtualTarget { index } => self.degree * self.num_wires + index, + } + } + + pub fn full_witness(self) -> MatrixWitness { + let mut wire_values = vec![vec![]; self.num_wires]; + for j in 0..self.num_wires { + wire_values[j].reserve_exact(self.degree); + unsafe { + // After .reserve_exact(l), wire_values[i] will have capacity at least l. Hence, set_len + // will not cause the buffer to overrun. + wire_values[j].set_len(self.degree); } } + for i in 0..self.degree { + for j in 0..self.num_wires { + let t = Target::Wire(Wire { gate: i, input: j }); + wire_values[j][i] = self.try_get_target(t).unwrap_or(F::ZERO); + } + } + MatrixWitness { wire_values } } } diff --git a/src/lib.rs b/src/lib.rs index 1249e9db..56fd179f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![feature(destructuring_assignment)] +#![feature(const_fn_trait_bound)] pub mod field; pub mod fri; diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 1fb70bad..b9a6ec6e 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -19,12 +19,13 @@ use crate::hash::hashing::hash_n_to_hash; use crate::iop::generator::{CopyGenerator, RandomValueGenerator, WitnessGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; +use crate::iop::witness::{PartialWitness, PartitionWitness}; use crate::plonk::circuit_data::{ CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, VerifierCircuitData, VerifierOnlyCircuitData, }; use crate::plonk::copy_constraint::CopyConstraint; -use crate::plonk::permutation_argument::{ForestNode, TargetPartition}; +use crate::plonk::permutation_argument::ForestNode; use crate::plonk::plonk_common::PlonkPolynomials; use crate::polynomial::polynomial::PolynomialValues; use crate::util::context_tree::ContextTree; @@ -510,16 +511,14 @@ impl, const D: usize> CircuitBuilder { &self, k_is: &[F], subgroup: &[F], - ) -> (Vec>, Vec>) { + ) -> (Vec>, PartitionWitness) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); - let mut target_partition = TargetPartition::new(|t| match t { - Target::Wire(Wire { gate, input }) => gate * self.config.num_routed_wires + input, - Target::VirtualTarget { index } => degree * self.config.num_routed_wires + index, - }); + let mut target_partition = + PartitionWitness::new(self.config.num_wires, self.config.num_routed_wires, degree); for gate in 0..degree { - for input in 0..self.config.num_routed_wires { + for input in 0..self.config.num_wires { target_partition.add(Target::Wire(Wire { gate, input })); } } diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index f3d13fb4..379e0d61 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -11,7 +11,7 @@ use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; +use crate::iop::witness::{PartialWitness, PartitionWitness}; use crate::plonk::copy_constraint::CopyConstraint; use crate::plonk::permutation_argument::ForestNode; use crate::plonk::proof::ProofWithPublicInputs; @@ -157,7 +157,7 @@ pub(crate) struct ProverOnlyCircuitData, const D: usize> { /// Number of virtual targets used in the circuit. pub num_virtual_targets: usize, - pub partition: Vec>, + pub partition: PartitionWitness, } /// Circuit data required by the verifier, but not the prover. diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index 3a9a93aa..ec8f3629 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -7,6 +7,7 @@ use rayon::prelude::*; use crate::field::field_types::Field; use crate::iop::target::Target; use crate::iop::wire::Wire; +use crate::iop::witness::PartitionWitness; use crate::polynomial::polynomial::PolynomialValues; /// Node in the Disjoint Set Forest. @@ -20,27 +21,21 @@ pub struct ForestNode { } /// Disjoint Set Forest data-structure following https://en.wikipedia.org/wiki/Disjoint-set_data_structure. -#[derive(Debug, Clone)] -pub struct TargetPartition usize> { - forest: Vec>, - /// Function to compute a node's index in the forest. - indices: F, -} - -impl usize> - TargetPartition -{ - pub fn new(f: F) -> Self { +impl PartitionWitness { + pub fn new(num_wires: usize, num_routed_wires: usize, degree: usize) -> Self { Self { - forest: Vec::new(), - indices: f, + nodes: vec![], + num_wires, + num_routed_wires, + degree, } } + /// Add a new partition with a single member. - pub fn add(&mut self, t: T) { - let index = self.forest.len(); - debug_assert_eq!((self.indices)(t), index); - self.forest.push(ForestNode { + pub fn add(&mut self, t: Target) { + let index = self.nodes.len(); + debug_assert_eq!(self.target_index(t), index); + self.nodes.push(ForestNode { t, parent: index, size: 1, @@ -50,10 +45,10 @@ impl usize> } /// Path compression method, see https://en.wikipedia.org/wiki/Disjoint-set_data_structure#Finding_set_representatives. - pub fn find(&mut self, x: ForestNode) -> ForestNode { + pub fn find(&mut self, x: ForestNode) -> ForestNode { if x.parent != x.index { - let root = self.find(self.forest[x.parent]); - self.forest[x.index].parent = root.index; + let root = self.find(self.nodes[x.parent]); + self.nodes[x.index].parent = root.index; root } else { x @@ -61,9 +56,9 @@ impl usize> } /// Merge two sets. - pub fn merge(&mut self, tx: T, ty: T) { - let mut x = self.forest[(self.indices)(tx)]; - let mut y = self.forest[(self.indices)(ty)]; + pub fn merge(&mut self, tx: Target, ty: Target) { + let mut x = self.nodes[self.target_index(tx)]; + let mut y = self.nodes[self.target_index(ty)]; x = self.find(x); y = self.find(y); @@ -80,39 +75,32 @@ impl usize> y.size += x.size; } - self.forest[x.index] = x; - self.forest[y.index] = y; + self.nodes[x.index] = x; + self.nodes[y.index] = y; } } -impl usize> TargetPartition { - pub fn wire_partition(mut self) -> (WirePartitions, Vec>) { +impl PartitionWitness { + pub fn wire_partition(mut self) -> (WirePartitions, Self) { let mut partition = HashMap::<_, Vec<_>>::new(); - let nodes = self.forest.clone(); - for x in nodes { - let v = partition.entry(self.find(x).t).or_default(); - v.push(x.t); + for gate in 0..self.degree { + for input in 0..self.num_routed_wires { + let w = Wire { gate, input }; + let t = Target::Wire(w); + let x = self.nodes[self.target_index(t)]; + partition.entry(self.find(x).t).or_default().push(w); + } + } + // I'm not 100% sure this loop is needed, but I'm afraid removing it might lead to subtle bugs. + for index in 0..self.nodes.len() - self.degree * self.num_wires { + let t = Target::VirtualTarget { index }; + let x = self.nodes[self.target_index(t)]; + self.find(x); } - // let mut indices = HashMap::new(); // Here we keep just the Wire targets, filtering out everything else. - let partition = partition - .into_values() - .map(|v| { - v.into_iter() - .filter_map(|t| match t { - Target::Wire(w) => Some(w), - _ => None, - }) - .collect::>() - }) - .collect::>(); - // partition.iter().enumerate().for_each(|(i, v)| { - // v.iter().for_each(|t| { - // indices.insert(*t, i); - // }); - // }); + let partition = partition.into_values().collect::>(); - (WirePartitions { partition }, self.forest) + (WirePartitions { partition }, self) } } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 1f44547e..d27c2443 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -35,58 +35,23 @@ pub(crate) fn prove, const D: usize>( let num_challenges = config.num_challenges; let quotient_degree = common_data.quotient_degree(); let degree = common_data.degree(); - // for i in 0..prover_data.gate_instances.len() { - // println!("{}: {}", i, prover_data.gate_instances[i].gate_ref.0.id()); - // } - let nrw = config.num_routed_wires; - let nw = config.num_wires; - let nvt = prover_data.num_virtual_targets; - let target_index = move |t: Target| -> usize { - match t { - Target::Wire(Wire { gate, input }) if input < nrw => gate * nrw + input, - Target::Wire(Wire { gate, input }) if input >= nrw => { - degree * nrw + nvt + gate * (nw - nrw) + input - nrw - } - Target::VirtualTarget { index } => degree * nrw + index, - _ => unreachable!(), - } - }; let mut partial_witness = prover_data.partition.clone(); - let n = partial_witness.len(); - timed!(timing, "fill partition", { - partial_witness.reserve_exact(degree * (config.num_wires - config.num_routed_wires)); - for i in 0..degree * (config.num_wires - config.num_routed_wires) { - partial_witness.push(ForestNode { - t: Target::Wire(Wire { gate: 0, input: 0 }), - parent: n + i, - size: 0, - index: n + i, - value: None, - }) - } + timed!( + timing, + "fill partition", for &(t, v) in &inputs.set_targets { - // println!("{:?} {} {}", t, target_index(t), partial_witness.len()); - let parent = partial_witness[target_index(t)].parent; - // println!("{} {}", parent, partial_witness.len()); - partial_witness[parent].value = Some(v); + partial_witness.set_target(t, v); } - }); - // let t = partial_witness[target_index(Target::Wire(Wire { - // gate: 14, - // input: 16, - // }))]; - // dbg!(t); - // dbg!(partial_witness[t.parent]); - // let mut partial_witness = inputs; - let mut partial_witness = PartitionWitness(partial_witness, Box::new(target_index)); + ); + timed!( timing, &format!("run {} generators", prover_data.generators.len()), generate_partial_witness( &mut partial_witness, &prover_data.generators, - config.num_wires, + num_wires, degree, prover_data.num_virtual_targets, &mut timing @@ -96,22 +61,17 @@ pub(crate) fn prove, const D: usize>( let public_inputs = partial_witness.get_targets(&prover_data.public_inputs); let public_inputs_hash = hash_n_to_hash(public_inputs.clone(), true); - // // Display the marked targets for debugging purposes. - // for m in &prover_data.marked_targets { - // m.display(&partial_witness); - // } - // - // timed!( - // timing, - // "check copy constraints", - // partial_witness - // .check_copy_constraints(&prover_data.copy_constraints, &prover_data.gate_instances)? - // ); + if cfg!(debug_assertions) { + // Display the marked targets for debugging purposes. + for m in &prover_data.marked_targets { + m.display(&partial_witness); + } + } let witness = timed!( timing, "compute full witness", - partial_witness.full_witness(degree, num_wires) + partial_witness.full_witness() ); let wires_values: Vec> = timed!( diff --git a/src/util/marking.rs b/src/util/marking.rs index 6e0ad993..5019511a 100644 --- a/src/util/marking.rs +++ b/src/util/marking.rs @@ -2,7 +2,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::hash::hash_types::HashOutTarget; use crate::iop::target::Target; -use crate::iop::witness::{PartialWitness, Witness}; +use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; /// Enum representing all types of targets, so that they can be marked. #[derive(Clone)] @@ -36,7 +36,7 @@ impl>, const D: usize> From> for Markable { impl Markable { /// Display a `Markable` by querying a partial witness. - fn print_markable>(&self, pw: &PartialWitness) { + fn print_markable>(&self, pw: &PartitionWitness) { match self { Markable::Target(t) => println!("{}", pw.get_target(*t)), Markable::ExtensionTarget(et) => println!("{}", pw.get_extension_target(*et)), @@ -55,7 +55,7 @@ pub struct MarkedTargets { impl MarkedTargets { /// Display the collection of targets along with its name by querying a partial witness. - pub fn display>(&self, pw: &PartialWitness) { + pub fn display>(&self, pw: &PartitionWitness) { println!("Values for {}:", self.name); self.targets.print_markable(pw); println!("End of values for {}", self.name); From c53d05040868577223b1d0592e7afcc16931d7eb Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 11:03:55 +0200 Subject: [PATCH 07/19] More cleaning --- src/iop/generator.rs | 49 +++++++++++--------------------------------- src/plonk/prover.rs | 19 ++++++----------- 2 files changed, 18 insertions(+), 50 deletions(-) diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 4aa5d6e1..8cbc35ca 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -14,22 +14,13 @@ use crate::plonk::permutation_argument::ForestNode; use crate::timed; use crate::util::timing::TimingTree; -/// Given a `PartialWitness` that has only inputs set, populates the rest of the witness using the +/// Given a `PartitionWitness` that has only inputs set, populates the rest of the witness using the /// given set of generators. pub(crate) fn generate_partial_witness( witness: &mut PartitionWitness, generators: &[Box>], - num_wires: usize, - degree: usize, - max_virtual_target: usize, timing: &mut TimingTree, ) { - // let target_index = |t: Target| -> usize { - // match t { - // Target::Wire(Wire { gate, input }) => gate * num_wires + input, - // Target::VirtualTarget { index } => degree * num_wires + index, - // } - // }; let max_target_index = witness.nodes.len(); // Index generator indices by their watched targets. let mut generator_indices_by_watches = vec![Vec::new(); max_target_index]; @@ -47,13 +38,12 @@ pub(crate) fn generate_partial_witness( // We also track a list of "expired" generators which have already returned false. let mut generator_is_expired = vec![false; generators.len()]; + let mut remaining_generators = generators.len(); let mut buffer = GeneratedValues::empty(); - let mut count = 0; - // Keep running generators until no generators are queued. - // while !pending_generator_indices.is_empty() { - while !generator_is_expired.iter().all(|&x| x) { + // Keep running generators until all generators have run. + while remaining_generators > 0 { let mut next_pending_generator_indices = Vec::new(); for &generator_idx in &pending_generator_indices { @@ -62,11 +52,9 @@ pub(crate) fn generate_partial_witness( } let finished = generators[generator_idx].run(&witness, &mut buffer); - // dbg!(&generators[generator_idx], &buffer); if finished { generator_is_expired[generator_idx] = true; - } else { - count += 1; + remaining_generators -= 1; } // Enqueue unfinished generators that were watching one of the newly populated targets. @@ -83,27 +71,14 @@ pub(crate) fn generate_partial_witness( witness.extend(buffer.target_values.drain(..)); } - // pending_generator_indices = next_pending_generator_indices; - pending_generator_indices = if next_pending_generator_indices.is_empty() { - (0..generators.len()).collect() - } else { - next_pending_generator_indices - }; + // If we still need to run som generators, but none were enqueued, we enqueue all generators. + pending_generator_indices = + if remaining_generators > 0 && next_pending_generator_indices.is_empty() { + (0..generators.len()).collect() + } else { + next_pending_generator_indices + }; } - - dbg!(count); - // for i in 0..generator_is_expired.len() { - // if !generator_is_expired[i] { - // println!("{}: {:?}", i, generators[i]); - // for a in generators[i].watch_list() { - // println!("{:?} {}", a, witness.contains(a)); - // } - // } - // } - assert!( - generator_is_expired.into_iter().all(identity), - "Some generators weren't run." - ); } /// A generator participates in the generation of the witness. diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index d27c2443..1a68953c 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -36,42 +36,35 @@ pub(crate) fn prove, const D: usize>( let quotient_degree = common_data.quotient_degree(); let degree = common_data.degree(); - let mut partial_witness = prover_data.partition.clone(); + let mut partition_witness = prover_data.partition.clone(); timed!( timing, "fill partition", for &(t, v) in &inputs.set_targets { - partial_witness.set_target(t, v); + partition_witness.set_target(t, v); } ); timed!( timing, &format!("run {} generators", prover_data.generators.len()), - generate_partial_witness( - &mut partial_witness, - &prover_data.generators, - num_wires, - degree, - prover_data.num_virtual_targets, - &mut timing - ) + generate_partial_witness(&mut partition_witness, &prover_data.generators, &mut timing) ); - let public_inputs = partial_witness.get_targets(&prover_data.public_inputs); + let public_inputs = partition_witness.get_targets(&prover_data.public_inputs); let public_inputs_hash = hash_n_to_hash(public_inputs.clone(), true); if cfg!(debug_assertions) { // Display the marked targets for debugging purposes. for m in &prover_data.marked_targets { - m.display(&partial_witness); + m.display(&partition_witness); } } let witness = timed!( timing, "compute full witness", - partial_witness.full_witness() + partition_witness.full_witness() ); let wires_values: Vec> = timed!( From e81001b9ba294170fb073d876aebde70c336162f Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 11:13:40 +0200 Subject: [PATCH 08/19] Clippy --- src/gadgets/arithmetic_extension.rs | 2 +- src/gadgets/range_check.rs | 2 +- src/gadgets/split_base.rs | 2 +- src/gadgets/split_join.rs | 2 +- src/gates/arithmetic.rs | 2 +- src/gates/base_sum.rs | 2 +- src/gates/constant.rs | 2 +- src/gates/exponentiation.rs | 2 +- src/gates/gmimc.rs | 2 +- src/gates/insertion.rs | 2 +- src/gates/interpolation.rs | 2 +- src/gates/random_access.rs | 2 +- src/gates/reducing.rs | 2 +- src/iop/generator.rs | 10 +++------- src/iop/witness.rs | 4 ---- src/plonk/circuit_builder.rs | 7 ++----- src/plonk/circuit_data.rs | 9 ++------- src/plonk/permutation_argument.rs | 1 - src/plonk/prover.rs | 23 ++++++++--------------- src/util/marking.rs | 2 +- 20 files changed, 29 insertions(+), 53 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index b53f03a6..394975cb 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -7,7 +7,7 @@ use crate::field::field_types::Field; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; diff --git a/src/gadgets/range_check.rs b/src/gadgets/range_check.rs index 4be8f80e..c878e799 100644 --- a/src/gadgets/range_check.rs +++ b/src/gadgets/range_check.rs @@ -3,7 +3,7 @@ use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; impl, const D: usize> CircuitBuilder { diff --git a/src/gadgets/split_base.rs b/src/gadgets/split_base.rs index 716472f5..20bd50a2 100644 --- a/src/gadgets/split_base.rs +++ b/src/gadgets/split_base.rs @@ -5,7 +5,7 @@ use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; impl, const D: usize> CircuitBuilder { diff --git a/src/gadgets/split_join.rs b/src/gadgets/split_join.rs index 45c87de9..fe3d724a 100644 --- a/src/gadgets/split_join.rs +++ b/src/gadgets/split_join.rs @@ -3,7 +3,7 @@ use crate::field::field_types::Field; use crate::gates::base_sum::BaseSumGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::ceil_div_usize; diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 12be0bc2..8bbacf3a 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -6,7 +6,7 @@ use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/gates/base_sum.rs b/src/gates/base_sum.rs index e53b72f6..641a8150 100644 --- a/src/gates/base_sum.rs +++ b/src/gates/base_sum.rs @@ -6,7 +6,7 @@ use crate::field::field_types::Field; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_recursive}; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/gates/constant.rs b/src/gates/constant.rs index eb4b5b12..894016d6 100644 --- a/src/gates/constant.rs +++ b/src/gates/constant.rs @@ -5,7 +5,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, PartitionWitness}; +use crate::iop::witness::PartitionWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/gates/exponentiation.rs b/src/gates/exponentiation.rs index e85c361e..d57c9001 100644 --- a/src/gates/exponentiation.rs +++ b/src/gates/exponentiation.rs @@ -7,7 +7,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 6bf868c0..837b64c2 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -8,7 +8,7 @@ use crate::hash::gmimc::gmimc_automatic_constants; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/gates/insertion.rs b/src/gates/insertion.rs index 91d71d2e..4c1e6fdf 100644 --- a/src/gates/insertion.rs +++ b/src/gates/insertion.rs @@ -9,7 +9,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 4eabbe31..56924742 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -11,7 +11,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; use crate::polynomial::polynomial::PolynomialCoeffs; diff --git a/src/gates/random_access.rs b/src/gates/random_access.rs index 85da3eaf..4b8c913a 100644 --- a/src/gates/random_access.rs +++ b/src/gates/random_access.rs @@ -8,7 +8,7 @@ use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/gates/reducing.rs b/src/gates/reducing.rs index 01c05306..ee3232b2 100644 --- a/src/gates/reducing.rs +++ b/src/gates/reducing.rs @@ -6,7 +6,7 @@ use crate::field::extension_field::FieldExtension; use crate::gates::gate::Gate; use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; use crate::iop::target::Target; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 8cbc35ca..f71a1826 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -1,16 +1,12 @@ -use std::collections::HashMap; -use std::convert::{identity, TryInto}; use std::fmt::Debug; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; -use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget}; -use crate::hash::merkle_tree::MerkleCap; -use crate::iop::target::{BoolTarget, Target}; +use crate::hash::hash_types::{HashOut, HashOutTarget}; +use crate::iop::target::Target; use crate::iop::wire::Wire; -use crate::iop::witness::{MatrixWitness, PartialWitness, PartitionWitness, Witness}; -use crate::plonk::permutation_argument::ForestNode; +use crate::iop::witness::{PartitionWitness, Witness}; use crate::timed; use crate::util::timing::TimingTree; diff --git a/src/iop/witness.rs b/src/iop/witness.rs index 8241c7d5..daab0df6 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -1,17 +1,13 @@ use std::convert::TryInto; -use anyhow::{ensure, Result}; - use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field_types::Field; -use crate::gates::gate::GateInstance; use crate::hash::hash_types::HashOutTarget; use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; -use crate::plonk::copy_constraint::CopyConstraint; use crate::plonk::permutation_argument::ForestNode; pub trait Witness { diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index b9a6ec6e..171ba9c4 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -19,13 +19,12 @@ use crate::hash::hashing::hash_n_to_hash; use crate::iop::generator::{CopyGenerator, RandomValueGenerator, WitnessGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; -use crate::iop::witness::{PartialWitness, PartitionWitness}; +use crate::iop::witness::PartitionWitness; use crate::plonk::circuit_data::{ CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, VerifierCircuitData, VerifierOnlyCircuitData, }; use crate::plonk::copy_constraint::CopyConstraint; -use crate::plonk::permutation_argument::ForestNode; use crate::plonk::plonk_common::PlonkPolynomials; use crate::polynomial::polynomial::PolynomialValues; use crate::util::context_tree::ContextTree; @@ -645,12 +644,10 @@ impl, const D: usize> CircuitBuilder { constants_sigmas_commitment, sigmas: transpose_poly_values(sigma_vecs), subgroup, - copy_constraints: self.copy_constraints, gate_instances: self.gate_instances, public_inputs: self.public_inputs, marked_targets: self.marked_targets, - num_virtual_targets: self.virtual_target_index, - partition, + partition_witness: partition, }; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 379e0d61..869b91b5 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -13,7 +13,6 @@ use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; use crate::iop::witness::{PartialWitness, PartitionWitness}; use crate::plonk::copy_constraint::CopyConstraint; -use crate::plonk::permutation_argument::ForestNode; use crate::plonk::proof::ProofWithPublicInputs; use crate::plonk::prover::prove; use crate::plonk::verifier::verify; @@ -146,18 +145,14 @@ pub(crate) struct ProverOnlyCircuitData, const D: usize> { pub sigmas: Vec>, /// Subgroup of order `degree`. pub subgroup: Vec, - /// The circuit's copy constraints. - pub copy_constraints: Vec, /// The concrete placement of each gate in the circuit. pub gate_instances: Vec>, /// Targets to be made public. pub public_inputs: Vec, /// A vector of marked targets. The values assigned to these targets will be displayed by the prover. pub marked_targets: Vec>, - /// Number of virtual targets used in the circuit. - pub num_virtual_targets: usize, - - pub partition: PartitionWitness, + /// Partial witness holding the copy constraints information. + pub partition_witness: PartitionWitness, } /// Circuit data required by the verifier, but not the prover. diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index ec8f3629..9dca05c6 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; use std::fmt::Debug; -use std::hash::Hash; use rayon::prelude::*; diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 1a68953c..c292295c 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -8,11 +8,8 @@ use crate::hash::hash_types::HashOut; use crate::hash::hashing::hash_n_to_hash; use crate::iop::challenger::Challenger; use crate::iop::generator::generate_partial_witness; -use crate::iop::target::Target; -use crate::iop::wire::Wire; -use crate::iop::witness::{MatrixWitness, PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; -use crate::plonk::permutation_argument::ForestNode; use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::plonk_common::ZeroPolyOnCoset; use crate::plonk::proof::{Proof, ProofWithPublicInputs}; @@ -31,12 +28,11 @@ pub(crate) fn prove, const D: usize>( ) -> Result> { let mut timing = TimingTree::new("prove", Level::Debug); let config = &common_data.config; - let num_wires = config.num_wires; let num_challenges = config.num_challenges; let quotient_degree = common_data.quotient_degree(); let degree = common_data.degree(); - let mut partition_witness = prover_data.partition.clone(); + let mut partition_witness = prover_data.partition_witness.clone(); timed!( timing, "fill partition", @@ -258,14 +254,12 @@ fn wires_permutation_partial_products, const D: usize>( .enumerate() .map(|(i, &x)| { let s_sigmas = &prover_data.sigmas[i]; - let numerators = (0..common_data.config.num_routed_wires) - .map(|j| { - let wire_value = witness.get_wire(i, j); - let k_i = k_is[j]; - let s_id = k_i * x; - wire_value + beta * s_id + gamma - }) - .collect::>(); + let numerators = (0..common_data.config.num_routed_wires).map(|j| { + let wire_value = witness.get_wire(i, j); + let k_i = k_is[j]; + let s_id = k_i * x; + wire_value + beta * s_id + gamma + }); let denominators = (0..common_data.config.num_routed_wires) .map(|j| { let wire_value = witness.get_wire(i, j); @@ -275,7 +269,6 @@ fn wires_permutation_partial_products, const D: usize>( .collect::>(); let denominator_invs = F::batch_multiplicative_inverse(&denominators); let quotient_values = numerators - .into_iter() .zip(denominator_invs) .map(|(num, den_inv)| num * den_inv) .collect::>(); diff --git a/src/util/marking.rs b/src/util/marking.rs index 5019511a..acbf8543 100644 --- a/src/util/marking.rs +++ b/src/util/marking.rs @@ -2,7 +2,7 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::hash::hash_types::HashOutTarget; use crate::iop::target::Target; -use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; +use crate::iop::witness::{PartitionWitness, Witness}; /// Enum representing all types of targets, so that they can be marked. #[derive(Clone)] From a90ea6ec7950333470ee17f51d54d218aa804fc7 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 11:56:57 +0200 Subject: [PATCH 09/19] PartialWitness back to HashMap --- src/bin/bench_recursion.rs | 2 +- src/gadgets/arithmetic_extension.rs | 6 +-- src/gadgets/insert.rs | 2 +- src/gadgets/interpolation.rs | 2 +- src/gadgets/random_access.rs | 2 +- src/gadgets/select.rs | 2 +- src/gadgets/split_base.rs | 4 +- src/gates/gate_testing.rs | 2 +- src/hash/merkle_proofs.rs | 2 +- src/iop/witness.rs | 70 ++++++++--------------------- src/plonk/circuit_data.rs | 1 - src/plonk/prover.rs | 2 +- src/plonk/recursive_verifier.rs | 10 ++--- src/util/reducing.rs | 4 +- 14 files changed, 38 insertions(+), 73 deletions(-) diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 5222bbfe..7d1b6c57 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -35,7 +35,7 @@ fn bench_prove, const D: usize>() -> Result<()> { }, }; - let inputs = PartialWitness::new(config.num_wires); + let inputs = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let zero = builder.zero(); diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 394975cb..e63b520a 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -517,7 +517,7 @@ mod tests { let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let vs = FF::rand_vec(3); @@ -552,7 +552,7 @@ mod tests { let config = CircuitConfig::large_zk_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = FF::rand(); @@ -580,7 +580,7 @@ mod tests { let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = FF::rand_vec(4); diff --git a/src/gadgets/insert.rs b/src/gadgets/insert.rs index bdc8bde7..4018644d 100644 --- a/src/gadgets/insert.rs +++ b/src/gadgets/insert.rs @@ -64,7 +64,7 @@ mod tests { type FF = QuarticCrandallField; let len = 1 << len_log; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let v = (0..len - 1) .map(|_| builder.constant_extension(FF::rand())) diff --git a/src/gadgets/interpolation.rs b/src/gadgets/interpolation.rs index 8901b9f8..2175d0ce 100644 --- a/src/gadgets/interpolation.rs +++ b/src/gadgets/interpolation.rs @@ -49,7 +49,7 @@ mod tests { type F = CrandallField; type FF = QuarticCrandallField; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let len = 4; diff --git a/src/gadgets/random_access.rs b/src/gadgets/random_access.rs index 6c34c0be..0e57c666 100644 --- a/src/gadgets/random_access.rs +++ b/src/gadgets/random_access.rs @@ -66,7 +66,7 @@ mod tests { type FF = QuarticCrandallField; let len = 1 << len_log; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let vec = FF::rand_vec(len); let v: Vec<_> = vec.iter().map(|x| builder.constant_extension(*x)).collect(); diff --git a/src/gadgets/select.rs b/src/gadgets/select.rs index 3f0e001d..a888d105 100644 --- a/src/gadgets/select.rs +++ b/src/gadgets/select.rs @@ -53,7 +53,7 @@ mod tests { type F = CrandallField; type FF = QuarticCrandallField; let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let (x, y) = (FF::rand(), FF::rand()); diff --git a/src/gadgets/split_base.rs b/src/gadgets/split_base.rs index 20bd50a2..453a8c7e 100644 --- a/src/gadgets/split_base.rs +++ b/src/gadgets/split_base.rs @@ -101,7 +101,7 @@ mod tests { fn test_split_base() -> Result<()> { type F = CrandallField; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = F::from_canonical_usize(0b110100000); // 416 = 1532 in base 6. let xt = builder.constant(x); @@ -127,7 +127,7 @@ mod tests { fn test_base_sum() -> Result<()> { type F = CrandallField; let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let n = thread_rng().gen_range(0..(1 << 10)); diff --git a/src/gates/gate_testing.rs b/src/gates/gate_testing.rs index 0e773aa0..b45cb745 100644 --- a/src/gates/gate_testing.rs +++ b/src/gates/gate_testing.rs @@ -124,7 +124,7 @@ pub(crate) fn test_eval_fns, G: Gate, const D: usize>( let constants = F::Extension::rand_vec(gate.num_constants()); let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let wires_t = builder.add_virtual_extension_targets(wires.len()); diff --git a/src/hash/merkle_proofs.rs b/src/hash/merkle_proofs.rs index 5f333f4e..c0fc3afa 100644 --- a/src/hash/merkle_proofs.rs +++ b/src/hash/merkle_proofs.rs @@ -234,7 +234,7 @@ mod tests { fn test_recursive_merkle_proof() -> Result<()> { type F = CrandallField; let config = CircuitConfig::large_config(); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let log_n = 8; diff --git a/src/iop/witness.rs b/src/iop/witness.rs index daab0df6..b1d69610 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::convert::TryInto; use crate::field::extension_field::target::ExtensionTarget; @@ -154,62 +155,33 @@ impl MatrixWitness { #[derive(Clone, Debug)] pub struct PartialWitness { - pub(crate) wire_values: Vec>>, - pub(crate) virtual_target_values: Vec>, - pub(crate) set_targets: Vec<(Target, F)>, + // pub(crate) wire_values: Vec>>, + // pub(crate) virtual_target_values: Vec>, + pub(crate) target_values: HashMap, } impl PartialWitness { - pub fn new(num_wires: usize) -> Self { + pub fn new() -> Self { PartialWitness { - wire_values: vec![vec![None; num_wires]], - virtual_target_values: vec![], - set_targets: vec![], + target_values: HashMap::new(), } } } impl Witness for PartialWitness { fn try_get_target(&self, target: Target) -> Option { - match target { - Target::Wire(Wire { gate, input }) => *self.wire_values.get(gate)?.get(input)?, - Target::VirtualTarget { index } => *self.virtual_target_values.get(index)?, - } + self.target_values.get(&target).copied() } fn set_target(&mut self, target: Target, value: F) { - match target { - Target::Wire(Wire { gate, input }) => { - if gate >= self.wire_values.len() { - self.wire_values - .resize(gate + 1, vec![None; self.wire_values[0].len()]); - } - if let Some(old_value) = self.wire_values[gate][input] { - assert_eq!( - old_value, value, - "Target was set twice with different values: {:?}", - target - ); - } else { - self.wire_values[gate][input] = Some(value); - } - } - Target::VirtualTarget { index } => { - if index >= self.virtual_target_values.len() { - self.virtual_target_values.resize(index + 1, None); - } - if let Some(old_value) = self.virtual_target_values[index] { - assert_eq!( - old_value, value, - "Target was set twice with different values: {:?}", - target - ); - } else { - self.virtual_target_values[index] = Some(value); - } - } + let opt_old_value = self.target_values.insert(target, value); + if let Some(old_value) = opt_old_value { + assert_eq!( + old_value, value, + "Target {:?} was set twice with different values", + target + ); } - self.set_targets.push((target, value)); } } @@ -241,19 +213,13 @@ impl PartitionWitness { } pub fn full_witness(self) -> MatrixWitness { - let mut wire_values = vec![vec![]; self.num_wires]; - for j in 0..self.num_wires { - wire_values[j].reserve_exact(self.degree); - unsafe { - // After .reserve_exact(l), wire_values[i] will have capacity at least l. Hence, set_len - // will not cause the buffer to overrun. - wire_values[j].set_len(self.degree); - } - } + let mut wire_values = vec![vec![F::ZERO; self.degree]; self.num_wires]; for i in 0..self.degree { for j in 0..self.num_wires { let t = Target::Wire(Wire { gate: i, input: j }); - wire_values[j][i] = self.try_get_target(t).unwrap_or(F::ZERO); + if let Some(x) = self.try_get_target(t) { + wire_values[j][i] = x; + } } } diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 869b91b5..bbc08c0d 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -12,7 +12,6 @@ use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; use crate::iop::witness::{PartialWitness, PartitionWitness}; -use crate::plonk::copy_constraint::CopyConstraint; use crate::plonk::proof::ProofWithPublicInputs; use crate::plonk::prover::prove; use crate::plonk::verifier::verify; diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index c292295c..f310259c 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -36,7 +36,7 @@ pub(crate) fn prove, const D: usize>( timed!( timing, "fill partition", - for &(t, v) in &inputs.set_targets { + for (t, v) in inputs.target_values.into_iter() { partition_witness.set_target(t, v); } ); diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 97ebd84c..14a60df3 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -386,7 +386,7 @@ mod tests { } let data = builder.build(); ( - data.prove(PartialWitness::new(config.num_wires))?, + data.prove(PartialWitness::new())?, data.verifier_only, data.common, ) @@ -394,7 +394,7 @@ mod tests { verify(proof_with_pis.clone(), &vd, &cd)?; let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let pt = proof_to_proof_target(&proof_with_pis, &mut builder); set_proof_target(&proof_with_pis, &pt, &mut pw); @@ -442,7 +442,7 @@ mod tests { } let data = builder.build(); ( - data.prove(PartialWitness::new(config.num_wires))?, + data.prove(PartialWitness::new())?, data.verifier_only, data.common, ) @@ -450,7 +450,7 @@ mod tests { verify(proof_with_pis.clone(), &vd, &cd)?; let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let pt = proof_to_proof_target(&proof_with_pis, &mut builder); set_proof_target(&proof_with_pis, &pt, &mut pw); @@ -468,7 +468,7 @@ mod tests { verify(proof_with_pis.clone(), &vd, &cd)?; let mut builder = CircuitBuilder::::new(config.clone()); - let mut pw = PartialWitness::new(config.num_wires); + let mut pw = PartialWitness::new(); let pt = proof_to_proof_target(&proof_with_pis, &mut builder); set_proof_target(&proof_with_pis, &pt, &mut pw); diff --git a/src/util/reducing.rs b/src/util/reducing.rs index ca0dd9e8..0c11f467 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -220,7 +220,7 @@ mod tests { let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let alpha = FF::rand(); @@ -248,7 +248,7 @@ mod tests { let config = CircuitConfig::large_config(); - let pw = PartialWitness::new(config.num_wires); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let alpha = FF::rand(); From 1d368782f23b49eccb423a1b594a144b5ae0a7be Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 12:15:15 +0200 Subject: [PATCH 10/19] Fix tests --- src/gates/gmimc.rs | 177 ++++++++++++++++++++++-------------------- src/iop/challenger.rs | 169 ++++++++++++++++++++-------------------- 2 files changed, 174 insertions(+), 172 deletions(-) diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 837b64c2..1cb823bf 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -317,89 +317,94 @@ impl, const D: usize, const R: usize> SimpleGenerator } } -// #[cfg(test)] -// mod tests { -// use std::convert::TryInto; -// use std::sync::Arc; -// -// use anyhow::Result; -// -// use crate::field::crandall_field::CrandallField; -// use crate::field::field_types::Field; -// use crate::gates::gate::Gate; -// 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::iop::generator::generate_partial_witness; -// use crate::iop::wire::Wire; -// use crate::iop::witness::PartialWitness; -// use crate::util::timing::TimingTree; -// -// #[test] -// fn generated_output() { -// type F = CrandallField; -// const R: usize = 101; -// let constants = Arc::new([F::TWO; R]); -// type Gate = GMiMCGate; -// let gate = Gate::new(constants.clone()); -// -// let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::>(); -// -// let mut witness = PartialWitness::new(gate.num_wires()); -// witness.set_wire( -// Wire { -// gate: 0, -// input: Gate::WIRE_SWAP, -// }, -// F::ZERO, -// ); -// for i in 0..W { -// witness.set_wire( -// Wire { -// gate: 0, -// input: Gate::wire_input(i), -// }, -// permutation_inputs[i], -// ); -// } -// -// let generators = gate.generators(0, &[]); -// generate_partial_witness( -// &mut witness, -// &generators, -// gate.num_wires(), -// 1, -// 1, -// &mut TimingTree::default(), -// ); -// -// let expected_outputs: [F; W] = -// gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); -// -// for i in 0..W { -// let out = witness.get_wire(Wire { -// gate: 0, -// input: Gate::wire_output(i), -// }); -// assert_eq!(out, expected_outputs[i]); -// } -// } -// -// #[test] -// fn low_degree() { -// type F = CrandallField; -// const R: usize = 101; -// let constants = Arc::new([F::TWO; R]); -// let gate = GMiMCGate::::new(constants); -// test_low_degree(gate) -// } -// -// #[test] -// fn eval_fns() -> Result<()> { -// type F = CrandallField; -// const R: usize = 101; -// let constants = Arc::new([F::TWO; R]); -// let gate = GMiMCGate::::new(constants); -// test_eval_fns(gate) -// } -// } +#[cfg(test)] +mod tests { + use std::convert::TryInto; + use std::sync::Arc; + + use anyhow::Result; + + use crate::field::crandall_field::CrandallField; + use crate::field::field_types::Field; + use crate::gates::gate::Gate; + 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::iop::generator::generate_partial_witness; + use crate::iop::target::Target; + use crate::iop::wire::Wire; + use crate::iop::witness::{PartialWitness, PartitionWitness, Witness}; + use crate::util::timing::TimingTree; + + #[test] + fn generated_output() { + type F = CrandallField; + const R: usize = 101; + let constants = Arc::new([F::TWO; R]); + type Gate = GMiMCGate; + let gate = Gate::new(constants.clone()); + + let permutation_inputs = (0..W).map(F::from_canonical_usize).collect::>(); + + let mut witness = PartialWitness::new(); + witness.set_wire( + Wire { + gate: 0, + input: Gate::WIRE_SWAP, + }, + F::ZERO, + ); + for i in 0..W { + witness.set_wire( + Wire { + gate: 0, + input: Gate::wire_input(i), + }, + permutation_inputs[i], + ); + } + + let mut partition_witness = PartitionWitness::new(gate.num_wires(), gate.num_wires(), 1); + for input in 0..gate.num_wires() { + partition_witness.add(Target::Wire(Wire { gate: 0, input })); + } + for (&t, &v) in witness.target_values.iter() { + partition_witness.set_target(t, v); + } + let generators = gate.generators(0, &[]); + generate_partial_witness( + &mut partition_witness, + &generators, + &mut TimingTree::default(), + ); + + let expected_outputs: [F; W] = + gmimc_permute_naive(permutation_inputs.try_into().unwrap(), constants); + + for i in 0..W { + let out = partition_witness.get_wire(Wire { + gate: 0, + input: Gate::wire_output(i), + }); + assert_eq!(out, expected_outputs[i]); + } + } + + #[test] + fn low_degree() { + type F = CrandallField; + const R: usize = 101; + let constants = Arc::new([F::TWO; R]); + let gate = GMiMCGate::::new(constants); + test_low_degree(gate) + } + + #[test] + fn eval_fns() -> Result<()> { + type F = CrandallField; + const R: usize = 101; + let constants = Arc::new([F::TWO; R]); + let gate = GMiMCGate::::new(constants); + test_eval_fns(gate) + } +} diff --git a/src/iop/challenger.rs b/src/iop/challenger.rs index 13e16035..29df093b 100644 --- a/src/iop/challenger.rs +++ b/src/iop/challenger.rs @@ -353,89 +353,86 @@ impl RecursiveChallenger { } } -// #[cfg(test)] -// mod tests { -// use crate::field::crandall_field::CrandallField; -// use crate::field::field_types::Field; -// use crate::iop::challenger::{Challenger, RecursiveChallenger}; -// use crate::iop::generator::generate_partial_witness; -// use crate::iop::target::Target; -// use crate::iop::witness::PartialWitness; -// use crate::plonk::circuit_builder::CircuitBuilder; -// use crate::plonk::circuit_data::CircuitConfig; -// use crate::util::timing::TimingTree; -// -// #[test] -// fn no_duplicate_challenges() { -// type F = CrandallField; -// let mut challenger = Challenger::new(); -// let mut challenges = Vec::new(); -// -// for i in 1..10 { -// challenges.extend(challenger.get_n_challenges(i)); -// challenger.observe_element(F::rand()); -// } -// -// let dedup_challenges = { -// let mut dedup = challenges.clone(); -// dedup.dedup(); -// dedup -// }; -// assert_eq!(dedup_challenges, challenges); -// } -// -// /// Tests for consistency between `Challenger` and `RecursiveChallenger`. -// #[test] -// fn test_consistency() { -// type F = CrandallField; -// -// // These are mostly arbitrary, but we want to test some rounds with enough inputs/outputs to -// // trigger multiple absorptions/squeezes. -// let num_inputs_per_round = vec![2, 5, 3]; -// let num_outputs_per_round = vec![1, 2, 4]; -// -// // Generate random input messages. -// let inputs_per_round: Vec> = num_inputs_per_round -// .iter() -// .map(|&n| F::rand_vec(n)) -// .collect(); -// -// let mut challenger = Challenger::new(); -// let mut outputs_per_round: Vec> = Vec::new(); -// for (r, inputs) in inputs_per_round.iter().enumerate() { -// challenger.observe_elements(inputs); -// outputs_per_round.push(challenger.get_n_challenges(num_outputs_per_round[r])); -// } -// -// let config = CircuitConfig { -// num_wires: 12 + 12 + 1 + 101, -// num_routed_wires: 27, -// ..CircuitConfig::default() -// }; -// let mut witness = PartialWitness::new(config.num_wires); -// let mut builder = CircuitBuilder::::new(config.clone()); -// let mut recursive_challenger = RecursiveChallenger::new(&mut builder); -// let mut recursive_outputs_per_round: Vec> = Vec::new(); -// for (r, inputs) in inputs_per_round.iter().enumerate() { -// recursive_challenger.observe_elements(&builder.constants(inputs)); -// recursive_outputs_per_round.push( -// recursive_challenger.get_n_challenges(&mut builder, num_outputs_per_round[r]), -// ); -// } -// let circuit = builder.build(); -// generate_partial_witness( -// &mut witness, -// &circuit.prover_only.generators, -// config.num_wires, -// circuit.common.degree(), -// circuit.prover_only.num_virtual_targets, -// &mut TimingTree::default(), -// ); -// let recursive_output_values_per_round: Vec> = recursive_outputs_per_round -// .iter() -// .map(|outputs| witness.get_targets(outputs)) -// .collect(); -// -// assert_eq!(outputs_per_round, recursive_output_values_per_round); -// } -// } +#[cfg(test)] +mod tests { + use crate::field::crandall_field::CrandallField; + use crate::field::field_types::Field; + use crate::iop::challenger::{Challenger, RecursiveChallenger}; + use crate::iop::generator::generate_partial_witness; + use crate::iop::target::Target; + use crate::iop::witness::{PartialWitness, Witness}; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::util::timing::TimingTree; + + #[test] + fn no_duplicate_challenges() { + type F = CrandallField; + let mut challenger = Challenger::new(); + let mut challenges = Vec::new(); + + for i in 1..10 { + challenges.extend(challenger.get_n_challenges(i)); + challenger.observe_element(F::rand()); + } + + let dedup_challenges = { + let mut dedup = challenges.clone(); + dedup.dedup(); + dedup + }; + assert_eq!(dedup_challenges, challenges); + } + + /// Tests for consistency between `Challenger` and `RecursiveChallenger`. + #[test] + fn test_consistency() { + type F = CrandallField; + + // These are mostly arbitrary, but we want to test some rounds with enough inputs/outputs to + // trigger multiple absorptions/squeezes. + let num_inputs_per_round = vec![2, 5, 3]; + let num_outputs_per_round = vec![1, 2, 4]; + + // Generate random input messages. + let inputs_per_round: Vec> = num_inputs_per_round + .iter() + .map(|&n| F::rand_vec(n)) + .collect(); + + let mut challenger = Challenger::new(); + let mut outputs_per_round: Vec> = Vec::new(); + for (r, inputs) in inputs_per_round.iter().enumerate() { + challenger.observe_elements(inputs); + outputs_per_round.push(challenger.get_n_challenges(num_outputs_per_round[r])); + } + + let config = CircuitConfig { + num_wires: 12 + 12 + 1 + 101, + num_routed_wires: 27, + ..CircuitConfig::default() + }; + let mut builder = CircuitBuilder::::new(config.clone()); + let mut recursive_challenger = RecursiveChallenger::new(&mut builder); + let mut recursive_outputs_per_round: Vec> = Vec::new(); + for (r, inputs) in inputs_per_round.iter().enumerate() { + recursive_challenger.observe_elements(&builder.constants(inputs)); + recursive_outputs_per_round.push( + recursive_challenger.get_n_challenges(&mut builder, num_outputs_per_round[r]), + ); + } + let circuit = builder.build(); + let mut partition_witness = circuit.prover_only.partition_witness.clone(); + generate_partial_witness( + &mut partition_witness, + &circuit.prover_only.generators, + &mut TimingTree::default(), + ); + let recursive_output_values_per_round: Vec> = recursive_outputs_per_round + .iter() + .map(|outputs| partition_witness.get_targets(outputs)) + .collect(); + + assert_eq!(outputs_per_round, recursive_output_values_per_round); + } +} From 507577b7ad253d6b98dc58b8573af132701b35fc Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 12:55:59 +0200 Subject: [PATCH 11/19] Comments --- src/hash/merkle_proofs.rs | 2 +- src/iop/generator.rs | 2 +- src/iop/witness.rs | 13 +++++++------ src/plonk/permutation_argument.rs | 24 ++++++++++++------------ 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/hash/merkle_proofs.rs b/src/hash/merkle_proofs.rs index c0fc3afa..cb782f41 100644 --- a/src/hash/merkle_proofs.rs +++ b/src/hash/merkle_proofs.rs @@ -83,7 +83,7 @@ impl, const D: usize> CircuitBuilder { gate, input: swap_wire, }); - self.generate_copy(bit.target, swap_wire); + self.route(bit.target, swap_wire); let input_wires = (0..12) .map(|i| { diff --git a/src/iop/generator.rs b/src/iop/generator.rs index f71a1826..1d0227c8 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -17,7 +17,7 @@ pub(crate) fn generate_partial_witness( generators: &[Box>], timing: &mut TimingTree, ) { - let max_target_index = witness.nodes.len(); + let max_target_index = witness.forest.len(); // Index generator indices by their watched targets. let mut generator_indices_by_watches = vec![Vec::new(); max_target_index]; timed!(timing, "index generators by their watched targets", { diff --git a/src/iop/witness.rs b/src/iop/witness.rs index b1d69610..ad61dde5 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -11,6 +11,7 @@ use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; use crate::plonk::permutation_argument::ForestNode; +/// A witness holds information on the values of targets in a circuit. pub trait Witness { fn try_get_target(&self, target: Target) -> Option; @@ -155,8 +156,6 @@ impl MatrixWitness { #[derive(Clone, Debug)] pub struct PartialWitness { - // pub(crate) wire_values: Vec>>, - // pub(crate) virtual_target_values: Vec>, pub(crate) target_values: HashMap, } @@ -185,9 +184,11 @@ impl Witness for PartialWitness { } } +/// `PartitionWitness` holds a disjoint-set forest of the targets respecting a ciruit's copy constraints. +/// The value of a target is defined to be the value of its root in the forest. #[derive(Clone)] pub struct PartitionWitness { - pub nodes: Vec>, + pub forest: Vec>, pub num_wires: usize, pub num_routed_wires: usize, pub degree: usize, @@ -195,12 +196,12 @@ pub struct PartitionWitness { impl Witness for PartitionWitness { fn try_get_target(&self, target: Target) -> Option { - self.nodes[self.nodes[self.target_index(target)].parent].value + self.forest[self.forest[self.target_index(target)].parent].value } fn set_target(&mut self, target: Target, value: F) { - let i = self.nodes[self.target_index(target)].parent; - self.nodes[i].value = Some(value); + let i = self.forest[self.target_index(target)].parent; + self.forest[i].value = Some(value); } } diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index 9dca05c6..4fbbf0ec 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -23,7 +23,7 @@ pub struct ForestNode { impl PartitionWitness { pub fn new(num_wires: usize, num_routed_wires: usize, degree: usize) -> Self { Self { - nodes: vec![], + forest: vec![], num_wires, num_routed_wires, degree, @@ -32,9 +32,9 @@ impl PartitionWitness { /// Add a new partition with a single member. pub fn add(&mut self, t: Target) { - let index = self.nodes.len(); + let index = self.forest.len(); debug_assert_eq!(self.target_index(t), index); - self.nodes.push(ForestNode { + self.forest.push(ForestNode { t, parent: index, size: 1, @@ -46,8 +46,8 @@ impl PartitionWitness { /// Path compression method, see https://en.wikipedia.org/wiki/Disjoint-set_data_structure#Finding_set_representatives. pub fn find(&mut self, x: ForestNode) -> ForestNode { if x.parent != x.index { - let root = self.find(self.nodes[x.parent]); - self.nodes[x.index].parent = root.index; + let root = self.find(self.forest[x.parent]); + self.forest[x.index].parent = root.index; root } else { x @@ -56,8 +56,8 @@ impl PartitionWitness { /// Merge two sets. pub fn merge(&mut self, tx: Target, ty: Target) { - let mut x = self.nodes[self.target_index(tx)]; - let mut y = self.nodes[self.target_index(ty)]; + let mut x = self.forest[self.target_index(tx)]; + let mut y = self.forest[self.target_index(ty)]; x = self.find(x); y = self.find(y); @@ -74,8 +74,8 @@ impl PartitionWitness { y.size += x.size; } - self.nodes[x.index] = x; - self.nodes[y.index] = y; + self.forest[x.index] = x; + self.forest[y.index] = y; } } impl PartitionWitness { @@ -85,14 +85,14 @@ impl PartitionWitness { for input in 0..self.num_routed_wires { let w = Wire { gate, input }; let t = Target::Wire(w); - let x = self.nodes[self.target_index(t)]; + let x = self.forest[self.target_index(t)]; partition.entry(self.find(x).t).or_default().push(w); } } // I'm not 100% sure this loop is needed, but I'm afraid removing it might lead to subtle bugs. - for index in 0..self.nodes.len() - self.degree * self.num_wires { + for index in 0..self.forest.len() - self.degree * self.num_wires { let t = Target::VirtualTarget { index }; - let x = self.nodes[self.target_index(t)]; + let x = self.forest[self.target_index(t)]; self.find(x); } From 5264859a6d03701872ef5f2aa356bb2d7911aff5 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 12:59:25 +0200 Subject: [PATCH 12/19] Minor --- src/plonk/circuit_builder.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 171ba9c4..2451b46b 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -173,16 +173,13 @@ impl, const D: usize> CircuitBuilder { ); } - /// Shorthand for `generate_copy` and `assert_equal`. /// Both elements must be routable, otherwise this method will panic. pub fn route(&mut self, src: Target, dst: Target) { - // self.generate_copy(src, dst); self.assert_equal(src, dst); } /// Same as `route` with a named copy constraint. pub fn named_route(&mut self, src: Target, dst: Target, name: String) { - // self.generate_copy(src, dst); self.named_assert_equal(src, dst, name); } @@ -263,14 +260,10 @@ impl, const D: usize> CircuitBuilder { } pub fn add_generators(&mut self, generators: Vec>>) { - // for g in &generators { - // println!("{:?}", g); - // } self.generators.extend(generators); } pub fn add_generator>(&mut self, generator: G) { - // println!("{:?}", generator); self.generators.push(Box::new(generator)); } From a61d7bc0cc8d11e13802780abf5c922ff2441984 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 13:00:40 +0200 Subject: [PATCH 13/19] Typo --- src/iop/generator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 1d0227c8..8174981c 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -38,7 +38,7 @@ pub(crate) fn generate_partial_witness( let mut buffer = GeneratedValues::empty(); - // Keep running generators until all generators have run. + // Keep running generators until all generators have been run. while remaining_generators > 0 { let mut next_pending_generator_indices = Vec::new(); From 1c07cb1917890ce46376b7c495f30009b4f73ce3 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 13:06:07 +0200 Subject: [PATCH 14/19] Renaming --- src/plonk/circuit_builder.rs | 16 ++++++++-------- src/plonk/permutation_argument.rs | 8 ++++---- src/plonk/prover.rs | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 2451b46b..ac6196bf 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -506,27 +506,27 @@ impl, const D: usize> CircuitBuilder { ) -> (Vec>, PartitionWitness) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); - let mut target_partition = + let mut partition_witness = PartitionWitness::new(self.config.num_wires, self.config.num_routed_wires, degree); for gate in 0..degree { for input in 0..self.config.num_wires { - target_partition.add(Target::Wire(Wire { gate, input })); + partition_witness.add(Target::Wire(Wire { gate, input })); } } for index in 0..self.virtual_target_index { - target_partition.add(Target::VirtualTarget { index }); + partition_witness.add(Target::VirtualTarget { index }); } for &CopyConstraint { pair: (a, b), .. } in &self.copy_constraints { - target_partition.merge(a, b); + partition_witness.merge(a, b); } - let (wire_partition, partition) = target_partition.wire_partition(); + let wire_partition = partition_witness.wire_partition(); ( wire_partition.get_sigma_polys(degree_log, k_is, subgroup), - partition, + partition_witness, ) } @@ -616,7 +616,7 @@ impl, const D: usize> CircuitBuilder { let constant_vecs = self.constant_polys(&prefixed_gates, num_constants); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); - let (sigma_vecs, partition) = self.sigma_vecs(&k_is, &subgroup); + let (sigma_vecs, partition_witness) = self.sigma_vecs(&k_is, &subgroup); let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat(); let constants_sigmas_commitment = PolynomialBatchCommitment::from_values( @@ -640,7 +640,7 @@ impl, const D: usize> CircuitBuilder { gate_instances: self.gate_instances, public_inputs: self.public_inputs, marked_targets: self.marked_targets, - partition_witness: partition, + partition_witness, }; // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index 4fbbf0ec..dbb6bee9 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -79,7 +79,7 @@ impl PartitionWitness { } } impl PartitionWitness { - pub fn wire_partition(mut self) -> (WirePartitions, Self) { + pub fn wire_partition(&mut self) -> WirePartition { let mut partition = HashMap::<_, Vec<_>>::new(); for gate in 0..self.degree { for input in 0..self.num_routed_wires { @@ -99,15 +99,15 @@ impl PartitionWitness { // Here we keep just the Wire targets, filtering out everything else. let partition = partition.into_values().collect::>(); - (WirePartitions { partition }, self) + WirePartition { partition } } } -pub struct WirePartitions { +pub struct WirePartition { partition: Vec>, } -impl WirePartitions { +impl WirePartition { pub(crate) fn get_sigma_polys( &self, degree_log: usize, diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index f310259c..a7a939bc 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -35,7 +35,7 @@ pub(crate) fn prove, const D: usize>( let mut partition_witness = prover_data.partition_witness.clone(); timed!( timing, - "fill partition", + "fill partition witness", for (t, v) in inputs.target_values.into_iter() { partition_witness.set_target(t, v); } From db0ccdd7f4a325eb0b16c41e22a5e11181df0950 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 13:08:20 +0200 Subject: [PATCH 15/19] Unused import --- src/iop/challenger.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iop/challenger.rs b/src/iop/challenger.rs index 29df093b..b2cec1aa 100644 --- a/src/iop/challenger.rs +++ b/src/iop/challenger.rs @@ -360,7 +360,7 @@ mod tests { use crate::iop::challenger::{Challenger, RecursiveChallenger}; use crate::iop::generator::generate_partial_witness; use crate::iop::target::Target; - use crate::iop::witness::{PartialWitness, Witness}; + use crate::iop::witness::Witness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::util::timing::TimingTree; From eeef54c40e1d5746b5813e3f17eef208a847dc2c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 13:22:00 +0200 Subject: [PATCH 16/19] Re-add Clone --- src/gates/arithmetic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 8bbacf3a..3c9dcb18 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -138,7 +138,7 @@ impl, const D: usize> Gate for ArithmeticExtensionGate } } -#[derive(Debug)] +#[derive(Clone, Debug)] struct ArithmeticExtensionGenerator, const D: usize> { gate_index: usize, const_0: F, From 5fba65a3f5532609b5d050164a4757a35a7af609 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 20 Aug 2021 22:42:09 +0200 Subject: [PATCH 17/19] Check old value in `PartitionWitness::set_target` --- src/iop/witness.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/iop/witness.rs b/src/iop/witness.rs index ad61dde5..26b15a24 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -184,7 +184,7 @@ impl Witness for PartialWitness { } } -/// `PartitionWitness` holds a disjoint-set forest of the targets respecting a ciruit's copy constraints. +/// `PartitionWitness` holds a disjoint-set forest of the targets respecting a circuit's copy constraints. /// The value of a target is defined to be the value of its root in the forest. #[derive(Clone)] pub struct PartitionWitness { @@ -200,8 +200,17 @@ impl Witness for PartitionWitness { } fn set_target(&mut self, target: Target, value: F) { - let i = self.forest[self.target_index(target)].parent; - self.forest[i].value = Some(value); + let parent_index = self.forest[self.target_index(target)].parent; + let parent_value = &mut self.forest[parent_index].value; + if let Some(old_value) = *parent_value { + assert_eq!( + value, old_value, + "Partition containing {:?} was set twice with different values", + target + ); + } else { + *parent_value = Some(value); + } } } From 2fcfa230a6ae7b66f50978cdf53aed30015b6df8 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Sun, 22 Aug 2021 10:36:44 +0200 Subject: [PATCH 18/19] Pr feedback --- src/gates/gmimc.rs | 2 +- src/iop/witness.rs | 5 +++-- src/lib.rs | 1 - src/plonk/circuit_builder.rs | 8 ++++++-- src/plonk/permutation_argument.rs | 9 +++++++-- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 1cb823bf..682bd1fa 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -364,7 +364,7 @@ mod tests { ); } - let mut partition_witness = PartitionWitness::new(gate.num_wires(), gate.num_wires(), 1); + let mut partition_witness = PartitionWitness::new(gate.num_wires(), gate.num_wires(), 1, 0); for input in 0..gate.num_wires() { partition_witness.add(Target::Wire(Wire { gate: 0, input })); } diff --git a/src/iop/witness.rs b/src/iop/witness.rs index 26b15a24..f1aca8a1 100644 --- a/src/iop/witness.rs +++ b/src/iop/witness.rs @@ -196,7 +196,8 @@ pub struct PartitionWitness { impl Witness for PartitionWitness { fn try_get_target(&self, target: Target) -> Option { - self.forest[self.forest[self.target_index(target)].parent].value + let parent_index = self.forest[self.target_index(target)].parent; + self.forest[parent_index].value } fn set_target(&mut self, target: Target, value: F) { @@ -215,7 +216,7 @@ impl Witness for PartitionWitness { } impl PartitionWitness { - pub const fn target_index(&self, target: Target) -> usize { + pub fn target_index(&self, target: Target) -> usize { match target { Target::Wire(Wire { gate, input }) => gate * self.num_wires + input, Target::VirtualTarget { index } => self.degree * self.num_wires + index, diff --git a/src/lib.rs b/src/lib.rs index 56fd179f..1249e9db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,4 @@ #![feature(destructuring_assignment)] -#![feature(const_fn_trait_bound)] pub mod field; pub mod fri; diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index ac6196bf..56bee0a5 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -506,8 +506,12 @@ impl, const D: usize> CircuitBuilder { ) -> (Vec>, PartitionWitness) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); - let mut partition_witness = - PartitionWitness::new(self.config.num_wires, self.config.num_routed_wires, degree); + let mut partition_witness = PartitionWitness::new( + self.config.num_wires, + self.config.num_routed_wires, + degree, + self.virtual_target_index, + ); for gate in 0..degree { for input in 0..self.config.num_wires { diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index dbb6bee9..384ac9e1 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -21,9 +21,14 @@ pub struct ForestNode { /// Disjoint Set Forest data-structure following https://en.wikipedia.org/wiki/Disjoint-set_data_structure. impl PartitionWitness { - pub fn new(num_wires: usize, num_routed_wires: usize, degree: usize) -> Self { + pub fn new( + num_wires: usize, + num_routed_wires: usize, + degree: usize, + num_virtual_targets: usize, + ) -> Self { Self { - forest: vec![], + forest: Vec::with_capacity(degree * num_wires + num_virtual_targets), num_wires, num_routed_wires, degree, From 181ddf93ab1934691749672340b1704629864454 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 23 Aug 2021 11:06:33 +0200 Subject: [PATCH 19/19] Merge two impls --- src/plonk/permutation_argument.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plonk/permutation_argument.rs b/src/plonk/permutation_argument.rs index 384ac9e1..3d7d68b8 100644 --- a/src/plonk/permutation_argument.rs +++ b/src/plonk/permutation_argument.rs @@ -82,8 +82,7 @@ impl PartitionWitness { self.forest[x.index] = x; self.forest[y.index] = y; } -} -impl PartitionWitness { + pub fn wire_partition(&mut self) -> WirePartition { let mut partition = HashMap::<_, Vec<_>>::new(); for gate in 0..self.degree {