From 63a3090452befc3799d41b145b8a17d89f6670b4 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 16 Mar 2022 18:09:36 +0100 Subject: [PATCH 01/16] Start selectors --- plonky2/src/gates/mod.rs | 1 + plonky2/src/gates/selectors.rs | 40 ++++++++++++++++++++++++++++ plonky2/src/plonk/circuit_builder.rs | 11 +++++++- plonky2/src/plonk/circuit_data.rs | 2 +- 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 plonky2/src/gates/selectors.rs diff --git a/plonky2/src/gates/mod.rs b/plonky2/src/gates/mod.rs index 18e3e99b..2450492f 100644 --- a/plonky2/src/gates/mod.rs +++ b/plonky2/src/gates/mod.rs @@ -24,6 +24,7 @@ pub mod random_access; pub mod range_check_u32; pub mod reducing; pub mod reducing_extension; +pub(crate) mod selectors; pub mod subtraction_u32; pub mod switch; pub mod util; diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs new file mode 100644 index 00000000..11463512 --- /dev/null +++ b/plonky2/src/gates/selectors.rs @@ -0,0 +1,40 @@ +use plonky2_field::extension_field::Extendable; +use plonky2_field::polynomial::PolynomialValues; + +use crate::gates::gate::{GateInstance, GateRef}; +use crate::hash::hash_types::RichField; + +pub(crate) fn compute_selectors, const D: usize>( + mut gates: Vec>, + instances: &[GateInstance], + max_degree: usize, +) { + let n = instances.len(); + gates.sort_unstable_by_key(|g| g.0.degree()); + + let mut combinations = Vec::new(); + let mut pos = 0; + + while pos < gates.len() { + let mut i = 0; + while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() <= max_degree + 1) { + i += 1; + } + combinations.push((pos, pos + i)); + pos += i; + } + + let num_constants_polynomials = + 0.max(gates.iter().map(|g| g.0.num_constants()).max().unwrap() - combinations.len() - 1); + let mut polynomials = + vec![PolynomialValues::zero(n); combinations.len() + num_constants_polynomials]; + + let index = |id| gates.iter().position(|g| g.0.id() == id).unwrap(); + let combination = |i| combinations.iter().position(|&(a, _)| a <= i).unwrap(); + + for (j, g) in instances.iter().enumerate() { + let i = index(g.gate_ref.0.id()); + let comb = combination(i); + polynomials[comb].values[j] = i - combinations[comb].0; + } +} diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 8e2f2e10..50b5931a 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -23,6 +23,7 @@ use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef, PrefixedGate} use crate::gates::gate_tree::Tree; use crate::gates::noop::NoopGate; use crate::gates::public_input::PublicInputGate; +use crate::gates::selectors::compute_selectors; use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; use crate::hash::merkle_proofs::MerkleProofTarget; use crate::iop::ext_target::ExtensionTarget; @@ -669,7 +670,15 @@ impl, const D: usize> CircuitBuilder { "FRI total reduction arity is too large.", ); - let gates = self.gates.iter().cloned().collect(); + let gates = self.gates.iter().cloned().collect::>(); + for g in &gates { + println!("{} {}", g.0.id(), g.0.num_constants()); + } + dbg!(compute_selectors( + gates.clone(), + &self.gate_instances, + self.config.max_quotient_degree_factor + 1 + )); let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates); let prefixed_gates = PrefixedGate::from_tree(gate_tree); diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 3d4ee2df..f0fa4bd5 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -63,7 +63,7 @@ impl CircuitConfig { Self { num_wires: 135, num_routed_wires: 80, - constant_gate_size: 5, + constant_gate_size: 2, use_base_arithmetic_gate: true, security_bits: 100, num_challenges: 2, From e77383b5593749521151c7d32e97ecf6d175bcd4 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 17 Mar 2022 11:08:25 +0100 Subject: [PATCH 02/16] Progress --- plonky2/src/gates/add_many_u32.rs | 2 +- plonky2/src/gates/arithmetic_u32.rs | 2 +- plonky2/src/gates/assert_le.rs | 4 +- plonky2/src/gates/comparison.rs | 4 +- plonky2/src/gates/exponentiation.rs | 2 +- plonky2/src/gates/gate.rs | 39 +++++--- plonky2/src/gates/gate_testing.rs | 6 +- plonky2/src/gates/interpolation.rs | 2 +- plonky2/src/gates/low_degree_interpolation.rs | 2 +- plonky2/src/gates/random_access.rs | 4 +- plonky2/src/gates/range_check_u32.rs | 2 +- plonky2/src/gates/selectors.rs | 34 ++++++- plonky2/src/gates/subtraction_u32.rs | 2 +- plonky2/src/gates/switch.rs | 2 +- plonky2/src/plonk/circuit_builder.rs | 53 +++++----- plonky2/src/plonk/circuit_data.rs | 9 +- plonky2/src/plonk/recursive_verifier.rs | 1 + plonky2/src/plonk/vanishing_poly.rs | 97 ++++++++++--------- plonky2/src/plonk/vars.rs | 43 ++++---- plonky2/src/plonk/verifier.rs | 2 +- plonky2/src/util/strided_view.rs | 2 +- 21 files changed, 186 insertions(+), 128 deletions(-) diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index 4f9c4293..e6248399 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -448,7 +448,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(addends, carries), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index dc03e296..eac2d23d 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -445,7 +445,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(multiplicands_0, multiplicands_1, addends), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index cec7274b..3e89baf7 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -602,7 +602,7 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), }; @@ -620,7 +620,7 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index b1cf7b98..5207b7ae 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -682,7 +682,7 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), }; @@ -700,7 +700,7 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index 51558a21..8db135ac 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -394,7 +394,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(base, power as u64), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 03bd0a7b..634c71f6 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -38,7 +38,7 @@ pub trait Gate, const D: usize>: 'static + Send + S ) { // Note that this method uses `yield_constr` instead of returning its constraints. // `yield_constr` abstracts out the underlying memory layout. - let local_constants = &vars_base + let local_constants = vars_base .local_constants .iter() .map(|c| F::Extension::from_basefield(*c)) @@ -80,9 +80,18 @@ pub trait Gate, const D: usize>: 'static + Send + S vars: EvaluationTargets, ) -> Vec>; - fn eval_filtered(&self, mut vars: EvaluationVars, prefix: &[bool]) -> Vec { - let filter = compute_filter(prefix, vars.local_constants); - vars.remove_prefix(prefix); + fn eval_filtered( + &self, + mut vars: EvaluationVars, + selector_index: usize, + combination_num: usize, + ) -> Vec { + let filter = compute_filter( + selector_index, + combination_num, + vars.local_constants[selector_index], + ); + vars.remove_prefix(selector_index); self.eval_unfiltered(vars) .into_iter() .map(|c| filter * c) @@ -94,13 +103,20 @@ pub trait Gate, const D: usize>: 'static + Send + S fn eval_filtered_base_batch( &self, mut vars_batch: EvaluationVarsBaseBatch, - prefix: &[bool], + selector_index: usize, + combination_num: usize, ) -> Vec { let filters: Vec<_> = vars_batch .iter() - .map(|vars| compute_filter(prefix, vars.local_constants)) + .map(|vars| { + compute_filter( + selector_index, + combination_num, + vars.local_constants[selector_index], + ) + }) .collect(); - vars_batch.remove_prefix(prefix); + vars_batch.remove_prefix(selector_index); let mut res_batch = self.eval_unfiltered_base_batch(vars_batch); for res_chunk in res_batch.chunks_exact_mut(filters.len()) { batch_multiply_inplace(res_chunk, &filters); @@ -213,11 +229,10 @@ impl, const D: usize> PrefixedGate { /// A gate's filter is computed as `prod b_i*c_i + (1-b_i)*(1-c_i)`, with `(b_i)` the prefix and /// `(c_i)` the local constants, which is one if the prefix of `constants` matches `prefix`. -fn compute_filter<'a, K: Field, T: IntoIterator>(prefix: &[bool], constants: T) -> K { - prefix - .iter() - .zip(constants) - .map(|(&b, &c)| if b { c } else { K::ONE - c }) +fn compute_filter<'a, K: Field>(selector_index: usize, combination_num: usize, constant: K) -> K { + (0..combination_num) + .filter(|&i| i != selector_index) + .map(|i| K::from_canonical_usize(i) - constant) .product() } diff --git a/plonky2/src/gates/gate_testing.rs b/plonky2/src/gates/gate_testing.rs index 51768ba8..20e45e32 100644 --- a/plonky2/src/gates/gate_testing.rs +++ b/plonky2/src/gates/gate_testing.rs @@ -32,7 +32,7 @@ pub fn test_low_degree, G: Gate, const D: usi .iter() .zip(constant_ldes.iter()) .map(|(local_wires, local_constants)| EvaluationVars { - local_constants, + local_constants: local_constants.to_vec(), local_wires, public_inputs_hash, }) @@ -113,7 +113,7 @@ where let vars_base_batch = EvaluationVarsBaseBatch::new(1, &constants_base, &wires_base, &public_inputs_hash); let vars = EvaluationVars { - local_constants: &constants, + local_constants: constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, }; @@ -145,7 +145,7 @@ where pw.set_hash_target(public_inputs_hash_t, public_inputs_hash); let vars = EvaluationVars { - local_constants: &constants, + local_constants: constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, }; diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index 46c42113..4f1f6b33 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -352,7 +352,7 @@ mod tests { let eval_point = FF::rand(); let gate = HighDegreeInterpolationGate::::new(1); let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index 845da5ab..02943106 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -453,7 +453,7 @@ mod tests { let eval_point = FF::rand(); let gate = LowDegreeInterpolationGate::::new(subgroup_bits); let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 6379f99f..0d84fa81 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -413,7 +413,7 @@ mod tests { .map(|(l, &i)| l[i]) .collect(); let good_vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires( bits, lists.clone(), @@ -424,7 +424,7 @@ mod tests { }; let bad_claimed_elements = F::rand_vec(4); let bad_vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(bits, lists, access_indices, bad_claimed_elements), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/range_check_u32.rs b/plonky2/src/gates/range_check_u32.rs index 79e91de8..f51b246e 100644 --- a/plonky2/src/gates/range_check_u32.rs +++ b/plonky2/src/gates/range_check_u32.rs @@ -292,7 +292,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(input_limbs), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 11463512..23db1256 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -8,9 +8,8 @@ pub(crate) fn compute_selectors, const D: usize>( mut gates: Vec>, instances: &[GateInstance], max_degree: usize, -) { +) -> (Vec>, Vec, Vec) { let n = instances.len(); - gates.sort_unstable_by_key(|g| g.0.degree()); let mut combinations = Vec::new(); let mut pos = 0; @@ -25,16 +24,41 @@ pub(crate) fn compute_selectors, const D: usize>( } let num_constants_polynomials = - 0.max(gates.iter().map(|g| g.0.num_constants()).max().unwrap() - combinations.len() - 1); + 0.max(gates.iter().map(|g| g.0.num_constants()).max().unwrap() - combinations.len() + 1); let mut polynomials = vec![PolynomialValues::zero(n); combinations.len() + num_constants_polynomials]; let index = |id| gates.iter().position(|g| g.0.id() == id).unwrap(); let combination = |i| combinations.iter().position(|&(a, _)| a <= i).unwrap(); + let selector_indices = gates + .iter() + .map(|g| combination(index(g.0.id()))) + .collect::>(); + let combination_nums = selector_indices + .iter() + .map(|&i| combinations[i].1 - combinations[i].0) + .collect(); + for (j, g) in instances.iter().enumerate() { - let i = index(g.gate_ref.0.id()); + let GateInstance { + gate_ref, + constants, + } = g; + let i = index(gate_ref.0.id()); let comb = combination(i); - polynomials[comb].values[j] = i - combinations[comb].0; + polynomials[comb].values[j] = F::from_canonical_usize(i - combinations[comb].0); + let mut k = 0; + let mut constant_ind = 0; + while k < constants.len() { + if constant_ind == comb { + constant_ind += 1; + } else { + polynomials[constant_ind].values[j] = constants[k]; + constant_ind += 1; + k += 1; + } + } } + (polynomials, selector_indices, combination_nums) } diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index b1e4d84f..afa212d5 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -437,7 +437,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(inputs_x, inputs_y, borrows), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index bd298762..3cfa3349 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -446,7 +446,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: &[], + local_constants: vec![], local_wires: &get_wires(first_inputs, second_inputs, switch_bools), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 50b5931a..8fe38da8 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -670,34 +670,34 @@ impl, const D: usize> CircuitBuilder { "FRI total reduction arity is too large.", ); - let gates = self.gates.iter().cloned().collect::>(); - for g in &gates { - println!("{} {}", g.0.id(), g.0.num_constants()); - } - dbg!(compute_selectors( + let mut gates = self.gates.iter().cloned().collect::>(); + gates.sort_unstable_by_key(|g| g.0.degree()); + let (constant_vecs, selector_indices, combination_nums) = compute_selectors( gates.clone(), &self.gate_instances, - self.config.max_quotient_degree_factor + 1 - )); - let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates); - let prefixed_gates = PrefixedGate::from_tree(gate_tree); - - // `quotient_degree_factor` has to be between `max_filtered_constraint_degree-1` and `1<, const D: usize> CircuitBuilder { fft_root_table: Some(fft_root_table), }; - // The HashSet of gates will have a non-deterministic order. When converting to a Vec, we - // sort by ID to make the ordering deterministic. - let mut gates = self.gates.iter().cloned().collect::>(); - gates.sort_unstable_by_key(|gate| gate.0.id()); - let num_gate_constraints = gates .iter() .map(|gate| gate.0.num_constraints()) @@ -802,7 +797,9 @@ impl, const D: usize> CircuitBuilder { config: self.config, fri_params, degree_bits, - gates: prefixed_gates, + gates, + selector_indices, + combination_nums, quotient_degree_factor, num_gate_constraints, num_constants, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index f0fa4bd5..c0bf2251 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -12,7 +12,7 @@ use crate::fri::structure::{ FriBatchInfo, FriBatchInfoTarget, FriInstanceInfo, FriInstanceInfoTarget, FriPolynomialInfo, }; use crate::fri::{FriConfig, FriParams}; -use crate::gates::gate::PrefixedGate; +use crate::gates::gate::{Gate, GateRef, PrefixedGate}; use crate::hash::hash_types::{MerkleCapTarget, RichField}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::ext_target::ExtensionTarget; @@ -246,7 +246,10 @@ pub struct CommonCircuitData< pub(crate) degree_bits: usize, /// The types of gates used in this circuit, along with their prefixes. - pub(crate) gates: Vec>, + pub(crate) gates: Vec>, + + pub(crate) selector_indices: Vec, + pub(crate) combination_nums: Vec, /// The degree of the PLONK quotient polynomial. pub(crate) quotient_degree_factor: usize, @@ -290,7 +293,7 @@ impl, C: GenericConfig, const D: usize> pub fn constraint_degree(&self) -> usize { self.gates .iter() - .map(|g| g.gate.0.degree()) + .map(|g| g.0.degree()) .max() .expect("No gates?") } diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index 2fe7d648..fb4238ee 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -224,6 +224,7 @@ mod tests { // Start with a degree 2^14 proof let (proof, vd, cd) = dummy_proof::(&config, 16_000)?; assert_eq!(cd.degree_bits, 14); + test_serialization(&proof, &cd)?; // Shrink it to 2^13. let (proof, vd, cd) = diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 70de5833..c5e0d563 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -3,7 +3,7 @@ use plonky2_field::extension_field::{Extendable, FieldExtension}; use plonky2_field::field_types::Field; use plonky2_field::zero_poly_coset::ZeroPolyOnCoset; -use crate::gates::gate::PrefixedGate; +use crate::gates::gate::{Gate, GateRef, PrefixedGate}; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; @@ -40,8 +40,7 @@ pub(crate) fn eval_vanishing_poly< let max_degree = common_data.quotient_degree_factor; let num_prods = common_data.num_partial_products; - let constraint_terms = - evaluate_gate_constraints(&common_data.gates, common_data.num_gate_constraints, vars); + let constraint_terms = evaluate_gate_constraints(common_data, vars.clone()); // The L_1(x) (Z(x) - 1) vanishing terms. let mut vanishing_z_1_terms = Vec::new(); @@ -129,7 +128,7 @@ pub(crate) fn eval_vanishing_poly_base_batch< let num_gate_constraints = common_data.num_gate_constraints; let constraint_terms_batch = - evaluate_gate_constraints_base_batch(&common_data.gates, num_gate_constraints, vars_batch); + evaluate_gate_constraints_base_batch(&common_data, vars_batch.clone()); debug_assert!(constraint_terms_batch.len() == n * num_gate_constraints); let num_challenges = common_data.config.num_challenges; @@ -153,7 +152,7 @@ pub(crate) fn eval_vanishing_poly_base_batch< let partial_products = partial_products_batch[k]; let s_sigmas = s_sigmas_batch[k]; - let constraint_terms = PackedStridedView::new(&constraint_terms_batch, n, k); + let constraint_terms = PackedStridedView::new(constraint_terms_batch.clone(), n, k); let l1_x = z_h_on_coset.eval_l1(index, x); for i in 0..num_challenges { @@ -208,17 +207,24 @@ pub(crate) fn eval_vanishing_poly_base_batch< /// `num_gate_constraints` is the largest number of constraints imposed by any gate. It is not /// strictly necessary, but it helps performance by ensuring that we allocate a vector with exactly /// the capacity that we need. -pub fn evaluate_gate_constraints, const D: usize>( - gates: &[PrefixedGate], - num_gate_constraints: usize, +pub fn evaluate_gate_constraints< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( + common_data: &CommonCircuitData, vars: EvaluationVars, ) -> Vec { - let mut constraints = vec![F::Extension::ZERO; num_gate_constraints]; - for gate in gates { - let gate_constraints = gate.gate.0.eval_filtered(vars, &gate.prefix); + let mut constraints = vec![F::Extension::ZERO; common_data.num_gate_constraints]; + for (i, gate) in common_data.gates.iter().enumerate() { + let gate_constraints = gate.0.eval_filtered( + vars.clone(), + common_data.selector_indices[i], + common_data.combination_nums[i], + ); for (i, c) in gate_constraints.into_iter().enumerate() { debug_assert!( - i < num_gate_constraints, + i < common_data.num_gate_constraints, "num_constraints() gave too low of a number" ); constraints[i] += c; @@ -232,17 +238,21 @@ pub fn evaluate_gate_constraints, const D: usize>( /// Returns a vector of `num_gate_constraints * vars_batch.len()` field elements. The constraints /// corresponding to `vars_batch[i]` are found in `result[i], result[vars_batch.len() + i], /// result[2 * vars_batch.len() + i], ...`. -pub fn evaluate_gate_constraints_base_batch, const D: usize>( - gates: &[PrefixedGate], - num_gate_constraints: usize, +pub fn evaluate_gate_constraints_base_batch< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( + common_data: &CommonCircuitData, vars_batch: EvaluationVarsBaseBatch, ) -> Vec { - let mut constraints_batch = vec![F::ZERO; num_gate_constraints * vars_batch.len()]; - for gate in gates { - let gate_constraints_batch = gate - .gate - .0 - .eval_filtered_base_batch(vars_batch, &gate.prefix); + let mut constraints_batch = vec![F::ZERO; common_data.num_gate_constraints * vars_batch.len()]; + for (i, gate) in common_data.gates.iter().enumerate() { + let gate_constraints_batch = gate.0.eval_filtered_base_batch( + vars_batch.clone(), + common_data.selector_indices[i], + common_data.combination_nums[i], + ); debug_assert!( gate_constraints_batch.len() <= constraints_batch.len(), "num_constraints() gave too low of a number" @@ -256,26 +266,30 @@ pub fn evaluate_gate_constraints_base_batch, const constraints_batch } -pub fn evaluate_gate_constraints_recursively, const D: usize>( +pub fn evaluate_gate_constraints_recursively< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, +>( builder: &mut CircuitBuilder, - gates: &[PrefixedGate], - num_gate_constraints: usize, + common_data: &CommonCircuitData, vars: EvaluationTargets, ) -> Vec> { - let mut all_gate_constraints = vec![builder.zero_extension(); num_gate_constraints]; - for gate in gates { - with_context!( - builder, - &format!("evaluate {} constraints", gate.gate.0.id()), - gate.gate.0.eval_filtered_recursively( - builder, - vars, - &gate.prefix, - &mut all_gate_constraints - ) - ); - } - all_gate_constraints + todo!(); + // let mut all_gate_constraints = vec![builder.zero_extension(); num_gate_constraints]; + // for gate in gates { + // with_context!( + // builder, + // &format!("evaluate {} constraints", gate.gate.0.id()), + // gate.gate.0.eval_filtered_recursively( + // builder, + // vars, + // &gate.prefix, + // &mut all_gate_constraints + // ) + // ); + // } + // all_gate_constraints } /// Evaluate the vanishing polynomial at `x`. In this context, the vanishing polynomial is a random @@ -308,12 +322,7 @@ pub(crate) fn eval_vanishing_poly_recursively< let constraint_terms = with_context!( builder, "evaluate gate constraints", - evaluate_gate_constraints_recursively( - builder, - &common_data.gates, - common_data.num_gate_constraints, - vars, - ) + evaluate_gate_constraints_recursively(builder, common_data, vars,) ); // The L_1(x) (Z(x) - 1) vanishing terms. diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index e2e52cfb..b9001703 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -9,9 +9,9 @@ use crate::hash::hash_types::{HashOut, HashOutTarget, RichField}; use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::util::strided_view::PackedStridedView; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { - pub local_constants: &'a [F::Extension], + pub local_constants: Vec, pub local_wires: &'a [F::Extension], pub public_inputs_hash: &'a HashOut, } @@ -19,10 +19,10 @@ pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { /// A batch of evaluation vars, in the base field. /// Wires and constants are stored in an evaluation point-major order (that is, wire 0 for all /// evaluation points, then wire 1 for all points, and so on). -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub struct EvaluationVarsBaseBatch<'a, F: Field> { batch_size: usize, - pub local_constants: &'a [F], + pub local_constants: Vec, pub local_wires: &'a [F], pub public_inputs_hash: &'a HashOut, } @@ -55,8 +55,8 @@ impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> ExtensionAlgebra::from_basefield_array(arr) } - pub fn remove_prefix(&mut self, prefix: &[bool]) { - self.local_constants = &self.local_constants[prefix.len()..]; + pub fn remove_prefix(&mut self, selector_index: usize) { + self.local_constants.remove(selector_index); } } @@ -71,14 +71,16 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { assert_eq!(local_wires.len() % batch_size, 0); Self { batch_size, - local_constants, + local_constants: local_constants.to_vec(), local_wires, public_inputs_hash, } } - pub fn remove_prefix(&mut self, prefix: &[bool]) { - self.local_constants = &self.local_constants[prefix.len() * self.len()..]; + pub fn remove_prefix(&mut self, selector_index: usize) { + let mut v = self.local_constants[..self.len() * selector_index].to_vec(); + v.extend(&self.local_constants[self.len() * (selector_index + 1)..]); + self.local_constants = v; } pub fn len(&self) -> usize { @@ -88,8 +90,9 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { pub fn view(&self, index: usize) -> EvaluationVarsBase<'a, F> { // We cannot implement `Index` as `EvaluationVarsBase` is a struct, not a reference. assert!(index < self.len()); - let local_constants = PackedStridedView::new(self.local_constants, self.len(), index); - let local_wires = PackedStridedView::new(self.local_wires, self.len(), index); + let local_constants = + PackedStridedView::new(self.local_constants.clone(), self.len(), index); + let local_wires = PackedStridedView::new(self.local_wires.to_vec(), self.len(), index); EvaluationVarsBase { local_constants, local_wires, @@ -98,7 +101,7 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { } pub fn iter(&self) -> EvaluationVarsBaseBatchIter<'a, F> { - EvaluationVarsBaseBatchIter::new(*self) + EvaluationVarsBaseBatchIter::new(self.clone()) } pub fn pack>( @@ -109,8 +112,11 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { ) { let n_leftovers = self.len() % P::WIDTH; ( - EvaluationVarsBaseBatchIterPacked::new_with_start(*self, 0), - EvaluationVarsBaseBatchIterPacked::new_with_start(*self, self.len() - n_leftovers), + EvaluationVarsBaseBatchIterPacked::new_with_start(self.clone(), 0), + EvaluationVarsBaseBatchIterPacked::new_with_start( + self.clone(), + self.len() - n_leftovers, + ), ) } } @@ -179,12 +185,15 @@ impl<'a, P: PackedField> Iterator for EvaluationVarsBaseBatchIterPacked<'a, P> { fn next(&mut self) -> Option { if self.i + P::WIDTH <= self.vars_batch.len() { let local_constants = PackedStridedView::new( - self.vars_batch.local_constants, + self.vars_batch.local_constants.to_vec(), + self.vars_batch.len(), + self.i, + ); + let local_wires = PackedStridedView::new( + self.vars_batch.local_wires.to_vec(), self.vars_batch.len(), self.i, ); - let local_wires = - PackedStridedView::new(self.vars_batch.local_wires, self.vars_batch.len(), self.i); let res = EvaluationVarsBasePacked { local_constants, local_wires, diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index ee0e976f..6839424c 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -49,7 +49,7 @@ pub(crate) fn verify_with_challenges< where [(); C::Hasher::HASH_SIZE]:, { - let local_constants = &proof.openings.constants; + let local_constants = proof.openings.constants.clone(); let local_wires = &proof.openings.wires; let vars = EvaluationVars { local_constants, diff --git a/plonky2/src/util/strided_view.rs b/plonky2/src/util/strided_view.rs index 6ea270ce..ed877f71 100644 --- a/plonky2/src/util/strided_view.rs +++ b/plonky2/src/util/strided_view.rs @@ -46,7 +46,7 @@ impl<'a, P: PackedField> PackedStridedView<'a, P> { // end of the same allocated object'; the UB results even if the pointer is not dereferenced. #[inline] - pub fn new(data: &'a [P::Scalar], stride: usize, offset: usize) -> Self { + pub fn new(data: Vec, stride: usize, offset: usize) -> Self { assert!( stride >= P::WIDTH, "stride (got {}) must be at least P::WIDTH ({})", From 296b21aed95726c661ef224c623dce536cedd3e3 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 17 Mar 2022 11:48:44 +0100 Subject: [PATCH 03/16] Not working --- plonky2/src/gates/gate.rs | 36 +++++++++++++------------ plonky2/src/gates/gate_testing.rs | 2 +- plonky2/src/plonk/recursive_verifier.rs | 5 ++-- plonky2/src/plonk/vanishing_poly.rs | 32 +++++++++++----------- plonky2/src/plonk/vars.rs | 8 +++--- 5 files changed, 43 insertions(+), 40 deletions(-) diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 634c71f6..82d8a6bb 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -129,11 +129,17 @@ pub trait Gate, const D: usize>: 'static + Send + S &self, builder: &mut CircuitBuilder, mut vars: EvaluationTargets, - prefix: &[bool], + selector_index: usize, + combination_num: usize, combined_gate_constraints: &mut [ExtensionTarget], ) { - let filter = compute_filter_recursively(builder, prefix, vars.local_constants); - vars.remove_prefix(prefix); + let filter = compute_filter_recursively( + builder, + selector_index, + combination_num, + vars.local_constants[selector_index], + ); + vars.remove_prefix(selector_index); let my_constraints = self.eval_unfiltered_recursively(builder, vars); for (acc, c) in combined_gate_constraints.iter_mut().zip(my_constraints) { *acc = builder.mul_add_extension(filter, c, *acc); @@ -238,21 +244,17 @@ fn compute_filter<'a, K: Field>(selector_index: usize, combination_num: usize, c fn compute_filter_recursively, const D: usize>( builder: &mut CircuitBuilder, - prefix: &[bool], - constants: &[ExtensionTarget], + selector_index: usize, + combination_num: usize, + constant: ExtensionTarget, ) -> ExtensionTarget { - let one = builder.one_extension(); - let v = prefix - .iter() - .enumerate() - .map(|(i, &b)| { - if b { - constants[i] - } else { - builder.sub_extension(one, constants[i]) - } - }) + let v = (0..combination_num) + .filter(|&i| i != selector_index) + .map(|i| builder.constant_extension(F::Extension::from_canonical_usize(i))) + .collect::>(); + let v = v + .into_iter() + .map(|x| builder.sub_extension(x, constant)) .collect::>(); - builder.mul_many_extension(&v) } diff --git a/plonky2/src/gates/gate_testing.rs b/plonky2/src/gates/gate_testing.rs index 20e45e32..2b40b37d 100644 --- a/plonky2/src/gates/gate_testing.rs +++ b/plonky2/src/gates/gate_testing.rs @@ -152,7 +152,7 @@ where let evals = gate.eval_unfiltered(vars); let vars_t = EvaluationTargets { - local_constants: &constants_t, + local_constants: constants_t, local_wires: &wires_t, public_inputs_hash: &public_inputs_hash_t, }; diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index fb4238ee..ce29c7a9 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -53,7 +53,7 @@ impl, const D: usize> CircuitBuilder { { let one = self.one_extension(); - let local_constants = &proof.openings.constants; + let local_constants = proof.openings.constants.clone(); let local_wires = &proof.openings.wires; let vars = EvaluationTargets { local_constants, @@ -230,6 +230,7 @@ mod tests { let (proof, vd, cd) = recursive_proof::(proof, vd, cd, &config, Some(13), false, false)?; assert_eq!(cd.degree_bits, 13); + test_serialization(&proof, &cd)?; // Shrink it to 2^12. let (proof, _vd, cd) = @@ -403,7 +404,7 @@ mod tests { timing.print(); } - data.verify(proof.clone())?; + // data.verify(proof.clone())?; Ok((proof, data.verifier_only, data.common)) } diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index c5e0d563..5caaef1c 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -275,21 +275,21 @@ pub fn evaluate_gate_constraints_recursively< common_data: &CommonCircuitData, vars: EvaluationTargets, ) -> Vec> { - todo!(); - // let mut all_gate_constraints = vec![builder.zero_extension(); num_gate_constraints]; - // for gate in gates { - // with_context!( - // builder, - // &format!("evaluate {} constraints", gate.gate.0.id()), - // gate.gate.0.eval_filtered_recursively( - // builder, - // vars, - // &gate.prefix, - // &mut all_gate_constraints - // ) - // ); - // } - // all_gate_constraints + let mut all_gate_constraints = vec![builder.zero_extension(); common_data.num_gate_constraints]; + for (i, gate) in common_data.gates.iter().enumerate() { + with_context!( + builder, + &format!("evaluate {} constraints", gate.0.id()), + gate.0.eval_filtered_recursively( + builder, + vars.clone(), + common_data.selector_indices[i], + common_data.combination_nums[i], + &mut all_gate_constraints + ) + ); + } + all_gate_constraints } /// Evaluate the vanishing polynomial at `x`. In this context, the vanishing polynomial is a random @@ -322,7 +322,7 @@ pub(crate) fn eval_vanishing_poly_recursively< let constraint_terms = with_context!( builder, "evaluate gate constraints", - evaluate_gate_constraints_recursively(builder, common_data, vars,) + evaluate_gate_constraints_recursively(builder, common_data, vars.clone()) ); // The L_1(x) (Z(x) - 1) vanishing terms. diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index b9001703..10110d81 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -218,14 +218,14 @@ impl<'a, P: PackedField> ExactSizeIterator for EvaluationVarsBaseBatchIterPacked } impl<'a, const D: usize> EvaluationTargets<'a, D> { - pub fn remove_prefix(&mut self, prefix: &[bool]) { - self.local_constants = &self.local_constants[prefix.len()..]; + pub fn remove_prefix(&mut self, selector_index: usize) { + self.local_constants.remove(selector_index); } } -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct EvaluationTargets<'a, const D: usize> { - pub local_constants: &'a [ExtensionTarget], + pub local_constants: Vec>, pub local_wires: &'a [ExtensionTarget], pub public_inputs_hash: &'a HashOutTarget, } From dbaa31d818416531298428da1d94454895b89dd9 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Sun, 20 Mar 2022 10:13:01 +0100 Subject: [PATCH 04/16] Back to slice --- plonky2/src/gates/gate_testing.rs | 2 +- plonky2/src/plonk/recursive_verifier.rs | 4 ++-- plonky2/src/plonk/vanishing_poly.rs | 2 +- plonky2/src/plonk/vars.rs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plonky2/src/gates/gate_testing.rs b/plonky2/src/gates/gate_testing.rs index 2b40b37d..20e45e32 100644 --- a/plonky2/src/gates/gate_testing.rs +++ b/plonky2/src/gates/gate_testing.rs @@ -152,7 +152,7 @@ where let evals = gate.eval_unfiltered(vars); let vars_t = EvaluationTargets { - local_constants: constants_t, + local_constants: &constants_t, local_wires: &wires_t, public_inputs_hash: &public_inputs_hash_t, }; diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index ce29c7a9..bfe9aeb6 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -53,7 +53,7 @@ impl, const D: usize> CircuitBuilder { { let one = self.one_extension(); - let local_constants = proof.openings.constants.clone(); + let local_constants = &proof.openings.constants; let local_wires = &proof.openings.wires; let vars = EvaluationTargets { local_constants, @@ -404,7 +404,7 @@ mod tests { timing.print(); } - // data.verify(proof.clone())?; + data.verify(proof.clone())?; Ok((proof, data.verifier_only, data.common)) } diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 5caaef1c..77f7ff43 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -322,7 +322,7 @@ pub(crate) fn eval_vanishing_poly_recursively< let constraint_terms = with_context!( builder, "evaluate gate constraints", - evaluate_gate_constraints_recursively(builder, common_data, vars.clone()) + evaluate_gate_constraints_recursively(builder, common_data, vars,) ); // The L_1(x) (Z(x) - 1) vanishing terms. diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index 10110d81..f71c5d6d 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -219,13 +219,13 @@ impl<'a, P: PackedField> ExactSizeIterator for EvaluationVarsBaseBatchIterPacked impl<'a, const D: usize> EvaluationTargets<'a, D> { pub fn remove_prefix(&mut self, selector_index: usize) { - self.local_constants.remove(selector_index); + todo!() } } #[derive(Clone)] pub struct EvaluationTargets<'a, const D: usize> { - pub local_constants: Vec>, + pub local_constants: &'a [ExtensionTarget], pub local_wires: &'a [ExtensionTarget], pub public_inputs_hash: &'a HashOutTarget, } From 744996ef1c863a09e0c7b66082be4ffc84d5b035 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Sun, 20 Mar 2022 10:19:22 +0100 Subject: [PATCH 05/16] Remove `remove_prefix` --- plonky2/src/gates/add_many_u32.rs | 2 +- plonky2/src/gates/arithmetic_u32.rs | 2 +- plonky2/src/gates/assert_le.rs | 4 +-- plonky2/src/gates/comparison.rs | 4 +-- plonky2/src/gates/exponentiation.rs | 2 +- plonky2/src/gates/gate.rs | 5 +--- plonky2/src/gates/gate_testing.rs | 6 ++-- plonky2/src/gates/interpolation.rs | 2 +- plonky2/src/gates/low_degree_interpolation.rs | 2 +- plonky2/src/gates/random_access.rs | 4 +-- plonky2/src/gates/range_check_u32.rs | 2 +- plonky2/src/gates/subtraction_u32.rs | 2 +- plonky2/src/gates/switch.rs | 2 +- plonky2/src/plonk/vars.rs | 30 +++++-------------- plonky2/src/plonk/verifier.rs | 2 +- 15 files changed, 26 insertions(+), 45 deletions(-) diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index e6248399..4f9c4293 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -448,7 +448,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(addends, carries), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index eac2d23d..dc03e296 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -445,7 +445,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(multiplicands_0, multiplicands_1, addends), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index 3e89baf7..cec7274b 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -602,7 +602,7 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), }; @@ -620,7 +620,7 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index 5207b7ae..b1cf7b98 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -682,7 +682,7 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), }; @@ -700,7 +700,7 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index 8db135ac..51558a21 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -394,7 +394,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(base, power as u64), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 82d8a6bb..b134e58c 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -38,7 +38,7 @@ pub trait Gate, const D: usize>: 'static + Send + S ) { // Note that this method uses `yield_constr` instead of returning its constraints. // `yield_constr` abstracts out the underlying memory layout. - let local_constants = vars_base + let local_constants = &vars_base .local_constants .iter() .map(|c| F::Extension::from_basefield(*c)) @@ -91,7 +91,6 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_num, vars.local_constants[selector_index], ); - vars.remove_prefix(selector_index); self.eval_unfiltered(vars) .into_iter() .map(|c| filter * c) @@ -116,7 +115,6 @@ pub trait Gate, const D: usize>: 'static + Send + S ) }) .collect(); - vars_batch.remove_prefix(selector_index); let mut res_batch = self.eval_unfiltered_base_batch(vars_batch); for res_chunk in res_batch.chunks_exact_mut(filters.len()) { batch_multiply_inplace(res_chunk, &filters); @@ -139,7 +137,6 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_num, vars.local_constants[selector_index], ); - vars.remove_prefix(selector_index); let my_constraints = self.eval_unfiltered_recursively(builder, vars); for (acc, c) in combined_gate_constraints.iter_mut().zip(my_constraints) { *acc = builder.mul_add_extension(filter, c, *acc); diff --git a/plonky2/src/gates/gate_testing.rs b/plonky2/src/gates/gate_testing.rs index 20e45e32..51768ba8 100644 --- a/plonky2/src/gates/gate_testing.rs +++ b/plonky2/src/gates/gate_testing.rs @@ -32,7 +32,7 @@ pub fn test_low_degree, G: Gate, const D: usi .iter() .zip(constant_ldes.iter()) .map(|(local_wires, local_constants)| EvaluationVars { - local_constants: local_constants.to_vec(), + local_constants, local_wires, public_inputs_hash, }) @@ -113,7 +113,7 @@ where let vars_base_batch = EvaluationVarsBaseBatch::new(1, &constants_base, &wires_base, &public_inputs_hash); let vars = EvaluationVars { - local_constants: constants, + local_constants: &constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, }; @@ -145,7 +145,7 @@ where pw.set_hash_target(public_inputs_hash_t, public_inputs_hash); let vars = EvaluationVars { - local_constants: constants, + local_constants: &constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, }; diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index 4f1f6b33..46c42113 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -352,7 +352,7 @@ mod tests { let eval_point = FF::rand(); let gate = HighDegreeInterpolationGate::::new(1); let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index 02943106..845da5ab 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -453,7 +453,7 @@ mod tests { let eval_point = FF::rand(); let gate = LowDegreeInterpolationGate::::new(subgroup_bits); let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 0d84fa81..6379f99f 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -413,7 +413,7 @@ mod tests { .map(|(l, &i)| l[i]) .collect(); let good_vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires( bits, lists.clone(), @@ -424,7 +424,7 @@ mod tests { }; let bad_claimed_elements = F::rand_vec(4); let bad_vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(bits, lists, access_indices, bad_claimed_elements), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/range_check_u32.rs b/plonky2/src/gates/range_check_u32.rs index f51b246e..79e91de8 100644 --- a/plonky2/src/gates/range_check_u32.rs +++ b/plonky2/src/gates/range_check_u32.rs @@ -292,7 +292,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(input_limbs), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index afa212d5..b1e4d84f 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -437,7 +437,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(inputs_x, inputs_y, borrows), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index 3cfa3349..bd298762 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -446,7 +446,7 @@ mod tests { }; let vars = EvaluationVars { - local_constants: vec![], + local_constants: &[], local_wires: &get_wires(first_inputs, second_inputs, switch_bools), public_inputs_hash: &HashOut::rand(), }; diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index f71c5d6d..8ecf66a6 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -9,9 +9,9 @@ use crate::hash::hash_types::{HashOut, HashOutTarget, RichField}; use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::util::strided_view::PackedStridedView; -#[derive(Debug, Clone)] +#[derive(Debug, Copy, Clone)] pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { - pub local_constants: Vec, + pub local_constants: &'a [F::Extension], pub local_wires: &'a [F::Extension], pub public_inputs_hash: &'a HashOut, } @@ -19,10 +19,10 @@ pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { /// A batch of evaluation vars, in the base field. /// Wires and constants are stored in an evaluation point-major order (that is, wire 0 for all /// evaluation points, then wire 1 for all points, and so on). -#[derive(Debug, Clone)] +#[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBaseBatch<'a, F: Field> { batch_size: usize, - pub local_constants: Vec, + pub local_constants: &'a [F], pub local_wires: &'a [F], pub public_inputs_hash: &'a HashOut, } @@ -54,10 +54,6 @@ impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> let arr = self.local_wires[wire_range].try_into().unwrap(); ExtensionAlgebra::from_basefield_array(arr) } - - pub fn remove_prefix(&mut self, selector_index: usize) { - self.local_constants.remove(selector_index); - } } impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { @@ -71,18 +67,12 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { assert_eq!(local_wires.len() % batch_size, 0); Self { batch_size, - local_constants: local_constants.to_vec(), + local_constants, local_wires, public_inputs_hash, } } - pub fn remove_prefix(&mut self, selector_index: usize) { - let mut v = self.local_constants[..self.len() * selector_index].to_vec(); - v.extend(&self.local_constants[self.len() * (selector_index + 1)..]); - self.local_constants = v; - } - pub fn len(&self) -> usize { self.batch_size } @@ -91,7 +81,7 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { // We cannot implement `Index` as `EvaluationVarsBase` is a struct, not a reference. assert!(index < self.len()); let local_constants = - PackedStridedView::new(self.local_constants.clone(), self.len(), index); + PackedStridedView::new(self.local_constants.to_vec(), self.len(), index); let local_wires = PackedStridedView::new(self.local_wires.to_vec(), self.len(), index); EvaluationVarsBase { local_constants, @@ -217,13 +207,7 @@ impl<'a, P: PackedField> ExactSizeIterator for EvaluationVarsBaseBatchIterPacked } } -impl<'a, const D: usize> EvaluationTargets<'a, D> { - pub fn remove_prefix(&mut self, selector_index: usize) { - todo!() - } -} - -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct EvaluationTargets<'a, const D: usize> { pub local_constants: &'a [ExtensionTarget], pub local_wires: &'a [ExtensionTarget], diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index 6839424c..ee0e976f 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -49,7 +49,7 @@ pub(crate) fn verify_with_challenges< where [(); C::Hasher::HASH_SIZE]:, { - let local_constants = proof.openings.constants.clone(); + let local_constants = &proof.openings.constants; let local_wires = &proof.openings.wires; let vars = EvaluationVars { local_constants, From 68bd0f4b3d62b015c38af8056e8c4135022c3699 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Mar 2022 07:27:06 +0100 Subject: [PATCH 06/16] Not working --- insertion/src/insertion_gate.rs | 1 + plonky2/src/gadgets/arithmetic_extension.rs | 49 +++++++++-- plonky2/src/gates/add_many_u32.rs | 85 ++++++++++--------- plonky2/src/gates/arithmetic_base.rs | 12 +-- plonky2/src/gates/arithmetic_extension.rs | 12 +-- plonky2/src/gates/arithmetic_u32.rs | 1 + plonky2/src/gates/assert_le.rs | 2 + plonky2/src/gates/comparison.rs | 2 + plonky2/src/gates/constant.rs | 48 +++++------ plonky2/src/gates/exponentiation.rs | 1 + plonky2/src/gates/gate.rs | 4 + plonky2/src/gates/gate_testing.rs | 13 ++- plonky2/src/gates/interpolation.rs | 1 + plonky2/src/gates/low_degree_interpolation.rs | 1 + plonky2/src/gates/multiplication_extension.rs | 36 ++++---- plonky2/src/gates/random_access.rs | 2 + plonky2/src/gates/range_check_u32.rs | 1 + plonky2/src/gates/subtraction_u32.rs | 1 + plonky2/src/gates/switch.rs | 1 + plonky2/src/plonk/circuit_builder.rs | 5 ++ plonky2/src/plonk/mod.rs | 1 + plonky2/src/plonk/prover.rs | 1 + plonky2/src/plonk/recursive_verifier.rs | 1 + plonky2/src/plonk/vanishing_poly.rs | 2 +- plonky2/src/plonk/vars.rs | 52 ++++++++---- plonky2/src/plonk/verifier.rs | 1 + plonky2/src/util/strided_view.rs | 2 +- 27 files changed, 215 insertions(+), 123 deletions(-) diff --git a/insertion/src/insertion_gate.rs b/insertion/src/insertion_gate.rs index 442416d3..c4e5e233 100644 --- a/insertion/src/insertion_gate.rs +++ b/insertion/src/insertion_gate.rs @@ -415,6 +415,7 @@ mod tests { _phantom: PhantomData, }; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(orig_vec, insertion_index, element_to_insert), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index ea3e8b13..37ccc2d6 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -613,16 +613,20 @@ mod tests { type FF = >::FE; let config = CircuitConfig::standard_recursion_zk_config(); + let config = CircuitConfig::standard_recursion_config(); - let pw = PartialWitness::new(); + let mut pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = FF::rand(); let y = FF::rand(); let z = x / y; - let xt = builder.constant_extension(x); - let yt = builder.constant_extension(y); - let zt = builder.constant_extension(z); + let xt = builder.add_virtual_extension_target(); + pw.set_extension_target(xt, x); + let yt = builder.add_virtual_extension_target(); + pw.set_extension_target(yt, y); + let zt = builder.add_virtual_extension_target(); + pw.set_extension_target(zt, z); let comp_zt = builder.div_extension(xt, yt); builder.connect_extension(zt, comp_zt); @@ -635,7 +639,7 @@ mod tests { #[test] fn test_mul_algebra() -> Result<()> { const D: usize = 2; - type C = KeccakGoldilocksConfig; + type C = PoseidonGoldilocksConfig; type F = >::F; type FF = >::FE; @@ -650,14 +654,15 @@ mod tests { ExtensionAlgebraTarget(builder.add_virtual_extension_targets(D).try_into().unwrap()); let zt = ExtensionAlgebraTarget(builder.add_virtual_extension_targets(D).try_into().unwrap()); - let comp_zt = builder.mul_ext_algebra(xt, yt); + // let comp_zt = builder.mul_ext_algebra(xt, yt); + let comp_zt = builder.add_ext_algebra(xt, yt); for i in 0..D { builder.connect_extension(zt.0[i], comp_zt.0[i]); } let x = ExtensionAlgebra::(FF::rand_arr()); let y = ExtensionAlgebra::(FF::rand_arr()); - let z = x * y; + let z = x + y; for i in 0..D { pw.set_extension_target(xt.0[i], x.0[i]); pw.set_extension_target(yt.0[i], y.0[i]); @@ -669,4 +674,34 @@ mod tests { verify(proof, &data.verifier_only, &data.common) } + + #[test] + fn test_yo() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + type FF = >::FE; + + let config = CircuitConfig::standard_recursion_config(); + + let mut pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let xt = builder.add_virtual_extension_target(); + let yt = builder.add_virtual_extension_target(); + let zt = builder.add_virtual_extension_target(); + let comp_zt = builder.mul_extension(xt, yt); + builder.connect_extension(zt, comp_zt); + + let x = FF::rand(); + let y = FF::rand(); + let z = x * y; + pw.set_extension_target(xt, x); + pw.set_extension_target(yt, y); + + let data = builder.build::(); + let proof = data.prove(pw)?; + + verify(proof, &data.verifier_only, &data.common) + } } diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index 4f9c4293..30ca2c56 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -130,48 +130,48 @@ impl, const D: usize> Gate for U32AddManyGate constraints } - fn eval_unfiltered_base_one( - &self, - vars: EvaluationVarsBase, - mut yield_constr: StridedConstraintConsumer, - ) { - for i in 0..self.num_ops { - let addends: Vec = (0..self.num_addends) - .map(|j| vars.local_wires[self.wire_ith_op_jth_addend(i, j)]) - .collect(); - let carry = vars.local_wires[self.wire_ith_carry(i)]; - - let computed_output = addends.iter().fold(F::ZERO, |x, &y| x + y) + carry; - - let output_result = vars.local_wires[self.wire_ith_output_result(i)]; - let output_carry = vars.local_wires[self.wire_ith_output_carry(i)]; - - let base = F::from_canonical_u64(1 << 32u64); - let combined_output = output_carry * base + output_result; - - yield_constr.one(combined_output - computed_output); - - let mut combined_result_limbs = F::ZERO; - let mut combined_carry_limbs = F::ZERO; - let base = F::from_canonical_u64(1u64 << Self::limb_bits()); - for j in (0..Self::num_limbs()).rev() { - let this_limb = vars.local_wires[self.wire_ith_output_jth_limb(i, j)]; - let max_limb = 1 << Self::limb_bits(); - let product = (0..max_limb) - .map(|x| this_limb - F::from_canonical_usize(x)) - .product(); - yield_constr.one(product); - - if j < Self::num_result_limbs() { - combined_result_limbs = base * combined_result_limbs + this_limb; - } else { - combined_carry_limbs = base * combined_carry_limbs + this_limb; - } - } - yield_constr.one(combined_result_limbs - output_result); - yield_constr.one(combined_carry_limbs - output_carry); - } - } + // fn eval_unfiltered_base_one( + // &self, + // vars: EvaluationVarsBase, + // mut yield_constr: StridedConstraintConsumer, + // ) { + // for i in 0..self.num_ops { + // let addends: Vec = (0..self.num_addends) + // .map(|j| vars.local_wires[self.wire_ith_op_jth_addend(i, j)]) + // .collect(); + // let carry = vars.local_wires[self.wire_ith_carry(i)]; + // + // let computed_output = addends.iter().fold(F::ZERO, |x, &y| x + y) + carry; + // + // let output_result = vars.local_wires[self.wire_ith_output_result(i)]; + // let output_carry = vars.local_wires[self.wire_ith_output_carry(i)]; + // + // let base = F::from_canonical_u64(1 << 32u64); + // let combined_output = output_carry * base + output_result; + // + // yield_constr.one(combined_output - computed_output); + // + // let mut combined_result_limbs = F::ZERO; + // let mut combined_carry_limbs = F::ZERO; + // let base = F::from_canonical_u64(1u64 << Self::limb_bits()); + // for j in (0..Self::num_limbs()).rev() { + // let this_limb = vars.local_wires[self.wire_ith_output_jth_limb(i, j)]; + // let max_limb = 1 << Self::limb_bits(); + // let product = (0..max_limb) + // .map(|x| this_limb - F::from_canonical_usize(x)) + // .product(); + // yield_constr.one(product); + // + // if j < Self::num_result_limbs() { + // combined_result_limbs = base * combined_result_limbs + this_limb; + // } else { + // combined_carry_limbs = base * combined_carry_limbs + this_limb; + // } + // } + // yield_constr.one(combined_result_limbs - output_result); + // yield_constr.one(combined_carry_limbs - output_carry); + // } + // } fn eval_unfiltered_recursively( &self, @@ -448,6 +448,7 @@ mod tests { }; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(addends, carries), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs index 5f73fef0..9106f169 100644 --- a/plonky2/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -57,8 +57,8 @@ impl, const D: usize> Gate for ArithmeticGate } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let const_0 = vars.local_constants[0]; - let const_1 = vars.local_constants[1]; + let const_0 = vars.get_constant(0); + let const_1 = vars.get_constant(1); let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -91,8 +91,8 @@ impl, const D: usize> Gate for ArithmeticGate builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - let const_0 = vars.local_constants[0]; - let const_1 = vars.local_constants[1]; + let const_0 = vars.get_constant(0); + let const_1 = vars.get_constant(1); let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -157,8 +157,8 @@ impl, const D: usize> PackedEvaluableBase for vars: EvaluationVarsBasePacked

, mut yield_constr: StridedConstraintConsumer

, ) { - let const_0 = vars.local_constants[0]; - let const_1 = vars.local_constants[1]; + let const_0 = vars.get_constant(0); + let const_1 = vars.get_constant(1); for i in 0..self.num_ops { let multiplicand_0 = vars.local_wires[Self::wire_ith_multiplicand_0(i)]; diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index 6b5af067..e74587db 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -55,8 +55,8 @@ impl, const D: usize> Gate for ArithmeticExte } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let const_0 = vars.local_constants[0]; - let const_1 = vars.local_constants[1]; + let const_0 = vars.get_constant(0); + let const_1 = vars.get_constant(1); let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -78,8 +78,8 @@ impl, const D: usize> Gate for ArithmeticExte vars: EvaluationVarsBase, mut yield_constr: StridedConstraintConsumer, ) { - let const_0 = vars.local_constants[0]; - let const_1 = vars.local_constants[1]; + let const_0 = vars.get_constant(0); + let const_1 = vars.get_constant(1); for i in 0..self.num_ops { let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i)); @@ -98,8 +98,8 @@ impl, const D: usize> Gate for ArithmeticExte builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - let const_0 = vars.local_constants[0]; - let const_1 = vars.local_constants[1]; + let const_0 = vars.get_constant(0); + let const_1 = vars.get_constant(1); let mut constraints = Vec::new(); for i in 0..self.num_ops { diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index dc03e296..088c1af4 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -445,6 +445,7 @@ mod tests { }; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(multiplicands_0, multiplicands_1, addends), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index cec7274b..52bdf3ec 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -602,6 +602,7 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), @@ -620,6 +621,7 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index b1cf7b98..001d22f3 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -682,6 +682,7 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), @@ -700,6 +701,7 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 990a4df8..73cdd86b 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -42,23 +42,21 @@ impl, const D: usize> Gate for ConstantGate { fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { (0..self.num_consts) - .map(|i| { - vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)] - }) + .map(|i| vars.get_constant(self.const_input(i)) - vars.local_wires[self.wire_output(i)]) .collect() } - fn eval_unfiltered_base_one( - &self, - _vars: EvaluationVarsBase, - _yield_constr: StridedConstraintConsumer, - ) { - panic!("use eval_unfiltered_base_packed instead"); - } + // fn eval_unfiltered_base_one( + // &self, + // _vars: EvaluationVarsBase, + // _yield_constr: StridedConstraintConsumer, + // ) { + // panic!("use eval_unfiltered_base_packed instead"); + // } - fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { - self.eval_unfiltered_base_batch_packed(vars_base) - } + // fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { + // self.eval_unfiltered_base_batch_packed(vars_base) + // } fn eval_unfiltered_recursively( &self, @@ -68,7 +66,7 @@ impl, const D: usize> Gate for ConstantGate { (0..self.num_consts) .map(|i| { builder.sub_extension( - vars.local_constants[self.const_input(i)], + vars.get_constant(self.const_input(i)), vars.local_wires[self.wire_output(i)], ) }) @@ -113,17 +111,17 @@ impl, const D: usize> Gate for ConstantGate { } } -impl, const D: usize> PackedEvaluableBase for ConstantGate { - fn eval_unfiltered_base_packed>( - &self, - vars: EvaluationVarsBasePacked

, - mut yield_constr: StridedConstraintConsumer

, - ) { - yield_constr.many((0..self.num_consts).map(|i| { - vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)] - })); - } -} +// impl, const D: usize> PackedEvaluableBase for ConstantGate { +// fn eval_unfiltered_base_packed>( +// &self, +// vars: EvaluationVarsBasePacked

, +// mut yield_constr: StridedConstraintConsumer

, +// ) { +// yield_constr.many((0..self.num_consts).map(|i| { +// vars.get_constant(self.const_input(i)) - vars.local_wires[self.wire_output(i)] +// })); +// } +// } #[derive(Debug)] struct ConstantGenerator { diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index 51558a21..bc0100ea 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -394,6 +394,7 @@ mod tests { }; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(base, power as u64), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index b134e58c..0803d3ae 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -50,6 +50,7 @@ pub trait Gate, const D: usize>: 'static + Send + S .collect::>(); let public_inputs_hash = &vars_base.public_inputs_hash; let vars = EvaluationVars { + selector_index: vars_base.selector_index, local_constants, local_wires, public_inputs_hash, @@ -91,6 +92,7 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_num, vars.local_constants[selector_index], ); + vars.selector_index = selector_index; self.eval_unfiltered(vars) .into_iter() .map(|c| filter * c) @@ -115,6 +117,7 @@ pub trait Gate, const D: usize>: 'static + Send + S ) }) .collect(); + vars_batch.selector_index = selector_index; let mut res_batch = self.eval_unfiltered_base_batch(vars_batch); for res_chunk in res_batch.chunks_exact_mut(filters.len()) { batch_multiply_inplace(res_chunk, &filters); @@ -137,6 +140,7 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_num, vars.local_constants[selector_index], ); + vars.selector_index = selector_index; let my_constraints = self.eval_unfiltered_recursively(builder, vars); for (acc, c) in combined_gate_constraints.iter_mut().zip(my_constraints) { *acc = builder.mul_add_extension(filter, c, *acc); diff --git a/plonky2/src/gates/gate_testing.rs b/plonky2/src/gates/gate_testing.rs index 51768ba8..e37c921b 100644 --- a/plonky2/src/gates/gate_testing.rs +++ b/plonky2/src/gates/gate_testing.rs @@ -32,6 +32,7 @@ pub fn test_low_degree, G: Gate, const D: usi .iter() .zip(constant_ldes.iter()) .map(|(local_wires, local_constants)| EvaluationVars { + selector_index: usize::MAX, local_constants, local_wires, public_inputs_hash, @@ -110,9 +111,15 @@ where let public_inputs_hash = HashOut::rand(); // Batch of 1. - let vars_base_batch = - EvaluationVarsBaseBatch::new(1, &constants_base, &wires_base, &public_inputs_hash); + let vars_base_batch = EvaluationVarsBaseBatch::new( + usize::MAX, + 1, + &constants_base, + &wires_base, + &public_inputs_hash, + ); let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, @@ -145,6 +152,7 @@ where pw.set_hash_target(public_inputs_hash_t, public_inputs_hash); let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, @@ -152,6 +160,7 @@ where let evals = gate.eval_unfiltered(vars); let vars_t = EvaluationTargets { + selector_index: usize::MAX, local_constants: &constants_t, local_wires: &wires_t, public_inputs_hash: &public_inputs_hash_t, diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index 46c42113..b77617b9 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -352,6 +352,7 @@ mod tests { let eval_point = FF::rand(); let gate = HighDegreeInterpolationGate::::new(1); let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index 845da5ab..11fadb93 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -453,6 +453,7 @@ mod tests { let eval_point = FF::rand(); let gate = LowDegreeInterpolationGate::::new(subgroup_bits); let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index 09701260..df020273 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -52,7 +52,7 @@ impl, const D: usize> Gate for MulExtensionGa } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let const_0 = vars.local_constants[0]; + let const_0 = vars.get_constant(0); let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -67,29 +67,29 @@ impl, const D: usize> Gate for MulExtensionGa constraints } - fn eval_unfiltered_base_one( - &self, - vars: EvaluationVarsBase, - mut yield_constr: StridedConstraintConsumer, - ) { - let const_0 = vars.local_constants[0]; - - for i in 0..self.num_ops { - let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i)); - let multiplicand_1 = vars.get_local_ext(Self::wires_ith_multiplicand_1(i)); - let output = vars.get_local_ext(Self::wires_ith_output(i)); - let computed_output = (multiplicand_0 * multiplicand_1).scalar_mul(const_0); - - yield_constr.many((output - computed_output).to_basefield_array()); - } - } + // fn eval_unfiltered_base_one( + // &self, + // vars: EvaluationVarsBase, + // mut yield_constr: StridedConstraintConsumer, + // ) { + // let const_0 = vars.get_constant(0); + // + // for i in 0..self.num_ops { + // let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i)); + // let multiplicand_1 = vars.get_local_ext(Self::wires_ith_multiplicand_1(i)); + // let output = vars.get_local_ext(Self::wires_ith_output(i)); + // let computed_output = (multiplicand_0 * multiplicand_1).scalar_mul(const_0); + // + // yield_constr.many((output - computed_output).to_basefield_array()); + // } + // } fn eval_unfiltered_recursively( &self, builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - let const_0 = vars.local_constants[0]; + let const_0 = vars.get_constant(0); let mut constraints = Vec::new(); for i in 0..self.num_ops { diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 6379f99f..c628255c 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -413,6 +413,7 @@ mod tests { .map(|(l, &i)| l[i]) .collect(); let good_vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires( bits, @@ -424,6 +425,7 @@ mod tests { }; let bad_claimed_elements = F::rand_vec(4); let bad_vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(bits, lists, access_indices, bad_claimed_elements), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/range_check_u32.rs b/plonky2/src/gates/range_check_u32.rs index 79e91de8..7aa3e6c5 100644 --- a/plonky2/src/gates/range_check_u32.rs +++ b/plonky2/src/gates/range_check_u32.rs @@ -292,6 +292,7 @@ mod tests { }; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(input_limbs), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index b1e4d84f..3a53091b 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -437,6 +437,7 @@ mod tests { }; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(inputs_x, inputs_y, borrows), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index bd298762..524bda3e 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -446,6 +446,7 @@ mod tests { }; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_inputs, second_inputs, switch_bools), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 8fe38da8..0eaccc0c 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -637,6 +637,9 @@ impl, const D: usize> CircuitBuilder { where [(); C::Hasher::HASH_SIZE]:, { + for g in &self.gate_instances { + dbg!(&g.gate_ref.0.id()); + } let mut timing = TimingTree::new("preprocess", Level::Trace); let start = Instant::now(); let rate_bits = self.config.fri_config.rate_bits; @@ -672,11 +675,13 @@ impl, const D: usize> CircuitBuilder { let mut gates = self.gates.iter().cloned().collect::>(); gates.sort_unstable_by_key(|g| g.0.degree()); + dbg!(&gates); let (constant_vecs, selector_indices, combination_nums) = compute_selectors( gates.clone(), &self.gate_instances, self.config.max_quotient_degree_factor + 1, ); + dbg!(&constant_vecs, &selector_indices, &combination_nums); let num_constants = constant_vecs.len(); // let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates); // let prefixed_gates = PrefixedGate::from_tree(gate_tree); diff --git a/plonky2/src/plonk/mod.rs b/plonky2/src/plonk/mod.rs index 4f2fa4e1..6306d209 100644 --- a/plonky2/src/plonk/mod.rs +++ b/plonky2/src/plonk/mod.rs @@ -1,6 +1,7 @@ pub mod circuit_builder; pub mod circuit_data; pub mod config; +mod constest; pub(crate) mod copy_constraint; mod get_challenges; pub(crate) mod permutation_argument; diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index 1d99b60a..69baf038 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -427,6 +427,7 @@ fn compute_quotient_polys< } let vars_batch = EvaluationVarsBaseBatch::new( + usize::MAX, xs_batch.len(), &local_constants_batch, &local_wires_batch, diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index bfe9aeb6..52b44bd1 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -56,6 +56,7 @@ impl, const D: usize> CircuitBuilder { let local_constants = &proof.openings.constants; let local_wires = &proof.openings.wires; let vars = EvaluationTargets { + selector_index: usize::MAX, local_constants, local_wires, public_inputs_hash: &public_inputs_hash, diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 77f7ff43..2ad1bf70 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -152,7 +152,7 @@ pub(crate) fn eval_vanishing_poly_base_batch< let partial_products = partial_products_batch[k]; let s_sigmas = s_sigmas_batch[k]; - let constraint_terms = PackedStridedView::new(constraint_terms_batch.clone(), n, k); + let constraint_terms = PackedStridedView::new(&constraint_terms_batch, n, k); let l1_x = z_h_on_coset.eval_l1(index, x); for i in 0..num_challenges { diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index 8ecf66a6..fa6e9927 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -1,4 +1,5 @@ use std::ops::Range; +use std::os::unix::raw::uid_t; use plonky2_field::extension_field::algebra::ExtensionAlgebra; use plonky2_field::extension_field::{Extendable, FieldExtension}; @@ -11,6 +12,7 @@ use crate::util::strided_view::PackedStridedView; #[derive(Debug, Copy, Clone)] pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { + pub selector_index: usize, pub local_constants: &'a [F::Extension], pub local_wires: &'a [F::Extension], pub public_inputs_hash: &'a HashOut, @@ -21,6 +23,7 @@ pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { /// evaluation points, then wire 1 for all points, and so on). #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBaseBatch<'a, F: Field> { + pub selector_index: usize, batch_size: usize, pub local_constants: &'a [F], pub local_wires: &'a [F], @@ -30,6 +33,7 @@ pub struct EvaluationVarsBaseBatch<'a, F: Field> { /// A view into `EvaluationVarsBaseBatch` for a particular evaluation point. Does not copy the data. #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBase<'a, F: Field> { + pub selector_index: usize, pub local_constants: PackedStridedView<'a, F>, pub local_wires: PackedStridedView<'a, F>, pub public_inputs_hash: &'a HashOut, @@ -40,12 +44,22 @@ pub struct EvaluationVarsBase<'a, F: Field> { // have packed extension fields. #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBasePacked<'a, P: PackedField> { + pub selector_index: usize, pub local_constants: PackedStridedView<'a, P>, pub local_wires: PackedStridedView<'a, P>, pub public_inputs_hash: &'a HashOut, } +impl<'a, P: PackedField> EvaluationVarsBasePacked<'a, P> { + pub fn get_constant(&self, i: usize) -> P { + self.local_constants[if i < self.selector_index { i } else { i + 1 }] + } +} impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> { + pub fn get_constant(&self, i: usize) -> F::Extension { + self.local_constants[if i < self.selector_index { i } else { i + 1 }] + } + pub fn get_local_ext_algebra( &self, wire_range: Range, @@ -58,6 +72,7 @@ impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { pub fn new( + selector_index: usize, batch_size: usize, local_constants: &'a [F], local_wires: &'a [F], @@ -66,6 +81,7 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { assert_eq!(local_constants.len() % batch_size, 0); assert_eq!(local_wires.len() % batch_size, 0); Self { + selector_index, batch_size, local_constants, local_wires, @@ -80,10 +96,10 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { pub fn view(&self, index: usize) -> EvaluationVarsBase<'a, F> { // We cannot implement `Index` as `EvaluationVarsBase` is a struct, not a reference. assert!(index < self.len()); - let local_constants = - PackedStridedView::new(self.local_constants.to_vec(), self.len(), index); - let local_wires = PackedStridedView::new(self.local_wires.to_vec(), self.len(), index); + let local_constants = PackedStridedView::new(self.local_constants, self.len(), index); + let local_wires = PackedStridedView::new(self.local_wires, self.len(), index); EvaluationVarsBase { + selector_index: self.selector_index, local_constants, local_wires, public_inputs_hash: self.public_inputs_hash, @@ -91,7 +107,7 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { } pub fn iter(&self) -> EvaluationVarsBaseBatchIter<'a, F> { - EvaluationVarsBaseBatchIter::new(self.clone()) + EvaluationVarsBaseBatchIter::new(*self) } pub fn pack>( @@ -102,16 +118,17 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { ) { let n_leftovers = self.len() % P::WIDTH; ( - EvaluationVarsBaseBatchIterPacked::new_with_start(self.clone(), 0), - EvaluationVarsBaseBatchIterPacked::new_with_start( - self.clone(), - self.len() - n_leftovers, - ), + EvaluationVarsBaseBatchIterPacked::new_with_start(*self, 0), + EvaluationVarsBaseBatchIterPacked::new_with_start(*self, self.len() - n_leftovers), ) } } impl<'a, F: Field> EvaluationVarsBase<'a, F> { + pub fn get_constant(&self, i: usize) -> F { + self.local_constants[if i < self.selector_index { i } else { i + 1 }] + } + pub fn get_local_ext(&self, wire_range: Range) -> F::Extension where F: RichField + Extendable, @@ -151,6 +168,7 @@ impl<'a, F: Field> Iterator for EvaluationVarsBaseBatchIter<'a, F> { /// Note: if the length of `EvaluationVarsBaseBatch` is not a multiple of `P::WIDTH`, then the /// leftovers at the end are ignored. pub struct EvaluationVarsBaseBatchIterPacked<'a, P: PackedField> { + selector_index: usize, /// Index to yield next, in units of `P::Scalar`. E.g. if `P::WIDTH == 4`, then we will yield /// the vars for points `i`, `i + 1`, `i + 2`, and `i + 3`, packed. i: usize, @@ -164,6 +182,7 @@ impl<'a, P: PackedField> EvaluationVarsBaseBatchIterPacked<'a, P> { ) -> Self { assert!(start <= vars_batch.len()); EvaluationVarsBaseBatchIterPacked { + selector_index: vars_batch.selector_index, i: start, vars_batch, } @@ -175,16 +194,14 @@ impl<'a, P: PackedField> Iterator for EvaluationVarsBaseBatchIterPacked<'a, P> { fn next(&mut self) -> Option { if self.i + P::WIDTH <= self.vars_batch.len() { let local_constants = PackedStridedView::new( - self.vars_batch.local_constants.to_vec(), - self.vars_batch.len(), - self.i, - ); - let local_wires = PackedStridedView::new( - self.vars_batch.local_wires.to_vec(), + self.vars_batch.local_constants, self.vars_batch.len(), self.i, ); + let local_wires = + PackedStridedView::new(self.vars_batch.local_wires, self.vars_batch.len(), self.i); let res = EvaluationVarsBasePacked { + selector_index: self.selector_index, local_constants, local_wires, public_inputs_hash: self.vars_batch.public_inputs_hash, @@ -209,12 +226,17 @@ impl<'a, P: PackedField> ExactSizeIterator for EvaluationVarsBaseBatchIterPacked #[derive(Copy, Clone)] pub struct EvaluationTargets<'a, const D: usize> { + pub selector_index: usize, pub local_constants: &'a [ExtensionTarget], pub local_wires: &'a [ExtensionTarget], pub public_inputs_hash: &'a HashOutTarget, } impl<'a, const D: usize> EvaluationTargets<'a, D> { + pub fn get_constant(&self, i: usize) -> ExtensionTarget { + self.local_constants[if i < self.selector_index { i } else { i + 1 }] + } + pub fn get_local_ext_algebra(&self, wire_range: Range) -> ExtensionAlgebraTarget { debug_assert_eq!(wire_range.len(), D); let arr = self.local_wires[wire_range].try_into().unwrap(); diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index ee0e976f..e79d51b7 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -52,6 +52,7 @@ where let local_constants = &proof.openings.constants; let local_wires = &proof.openings.wires; let vars = EvaluationVars { + selector_index: usize::MAX, local_constants, local_wires, public_inputs_hash: &public_inputs_hash, diff --git a/plonky2/src/util/strided_view.rs b/plonky2/src/util/strided_view.rs index ed877f71..6ea270ce 100644 --- a/plonky2/src/util/strided_view.rs +++ b/plonky2/src/util/strided_view.rs @@ -46,7 +46,7 @@ impl<'a, P: PackedField> PackedStridedView<'a, P> { // end of the same allocated object'; the UB results even if the pointer is not dereferenced. #[inline] - pub fn new(data: Vec, stride: usize, offset: usize) -> Self { + pub fn new(data: &'a [P::Scalar], stride: usize, offset: usize) -> Self { assert!( stride >= P::WIDTH, "stride (got {}) must be at least P::WIDTH ({})", From 185d8faef64897509c21fd37470b36524cf8ed8b Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Mar 2022 14:06:09 +0100 Subject: [PATCH 07/16] Progress --- plonky2/src/gates/arithmetic_u32.rs | 22 +++++++++---------- plonky2/src/gates/gate.rs | 32 +++++++++++++++++----------- plonky2/src/gates/public_input.rs | 22 +++++++++---------- plonky2/src/gates/selectors.rs | 17 +++++++++------ plonky2/src/plonk/circuit_builder.rs | 2 +- plonky2/src/plonk/circuit_data.rs | 2 +- plonky2/src/plonk/vanishing_poly.rs | 8 ++++--- 7 files changed, 59 insertions(+), 46 deletions(-) diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index 088c1af4..97180f6b 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -125,17 +125,17 @@ impl, const D: usize> Gate for U32ArithmeticG constraints } - fn eval_unfiltered_base_one( - &self, - _vars: EvaluationVarsBase, - _yield_constr: StridedConstraintConsumer, - ) { - panic!("use eval_unfiltered_base_packed instead"); - } - - fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { - self.eval_unfiltered_base_batch_packed(vars_base) - } + // fn eval_unfiltered_base_one( + // &self, + // _vars: EvaluationVarsBase, + // _yield_constr: StridedConstraintConsumer, + // ) { + // panic!("use eval_unfiltered_base_packed instead"); + // } + // + // fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { + // self.eval_unfiltered_base_batch_packed(vars_base) + // } fn eval_unfiltered_recursively( &self, diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 0803d3ae..d871d830 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -84,12 +84,13 @@ pub trait Gate, const D: usize>: 'static + Send + S fn eval_filtered( &self, mut vars: EvaluationVars, + gate_index: usize, selector_index: usize, - combination_num: usize, + combination_range: (usize, usize), ) -> Vec { let filter = compute_filter( - selector_index, - combination_num, + gate_index, + combination_range, vars.local_constants[selector_index], ); vars.selector_index = selector_index; @@ -104,15 +105,16 @@ pub trait Gate, const D: usize>: 'static + Send + S fn eval_filtered_base_batch( &self, mut vars_batch: EvaluationVarsBaseBatch, + gate_index: usize, selector_index: usize, - combination_num: usize, + combination_range: (usize, usize), ) -> Vec { let filters: Vec<_> = vars_batch .iter() .map(|vars| { compute_filter( - selector_index, - combination_num, + gate_index, + combination_range, vars.local_constants[selector_index], ) }) @@ -131,13 +133,13 @@ pub trait Gate, const D: usize>: 'static + Send + S builder: &mut CircuitBuilder, mut vars: EvaluationTargets, selector_index: usize, - combination_num: usize, + combination_range: (usize, usize), combined_gate_constraints: &mut [ExtensionTarget], ) { let filter = compute_filter_recursively( builder, selector_index, - combination_num, + combination_range, vars.local_constants[selector_index], ); vars.selector_index = selector_index; @@ -236,9 +238,13 @@ impl, const D: usize> PrefixedGate { /// A gate's filter is computed as `prod b_i*c_i + (1-b_i)*(1-c_i)`, with `(b_i)` the prefix and /// `(c_i)` the local constants, which is one if the prefix of `constants` matches `prefix`. -fn compute_filter<'a, K: Field>(selector_index: usize, combination_num: usize, constant: K) -> K { - (0..combination_num) - .filter(|&i| i != selector_index) +fn compute_filter<'a, K: Field>( + gate_index: usize, + combination_range: (usize, usize), + constant: K, +) -> K { + (combination_range.0..combination_range.1) + .filter(|&i| i != gate_index) .map(|i| K::from_canonical_usize(i) - constant) .product() } @@ -246,10 +252,10 @@ fn compute_filter<'a, K: Field>(selector_index: usize, combination_num: usize, c fn compute_filter_recursively, const D: usize>( builder: &mut CircuitBuilder, selector_index: usize, - combination_num: usize, + combination_range: (usize, usize), constant: ExtensionTarget, ) -> ExtensionTarget { - let v = (0..combination_num) + let v = (combination_range.0..combination_range.1) .filter(|&i| i != selector_index) .map(|i| builder.constant_extension(F::Extension::from_canonical_usize(i))) .collect::>(); diff --git a/plonky2/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs index 20fc59c8..e827cc9b 100644 --- a/plonky2/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -36,17 +36,17 @@ impl, const D: usize> Gate for PublicInputGat .collect() } - fn eval_unfiltered_base_one( - &self, - _vars: EvaluationVarsBase, - _yield_constr: StridedConstraintConsumer, - ) { - panic!("use eval_unfiltered_base_packed instead"); - } - - fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { - self.eval_unfiltered_base_batch_packed(vars_base) - } + // fn eval_unfiltered_base_one( + // &self, + // _vars: EvaluationVarsBase, + // _yield_constr: StridedConstraintConsumer, + // ) { + // panic!("use eval_unfiltered_base_packed instead"); + // } + // + // fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { + // self.eval_unfiltered_base_batch_packed(vars_base) + // } fn eval_unfiltered_recursively( &self, diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 23db1256..c1461c09 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -8,7 +8,7 @@ pub(crate) fn compute_selectors, const D: usize>( mut gates: Vec>, instances: &[GateInstance], max_degree: usize, -) -> (Vec>, Vec, Vec) { +) -> (Vec>, Vec, Vec<(usize, usize)>) { let n = instances.len(); let mut combinations = Vec::new(); @@ -29,15 +29,20 @@ pub(crate) fn compute_selectors, const D: usize>( vec![PolynomialValues::zero(n); combinations.len() + num_constants_polynomials]; let index = |id| gates.iter().position(|g| g.0.id() == id).unwrap(); - let combination = |i| combinations.iter().position(|&(a, _)| a <= i).unwrap(); + let combination = |i| { + combinations + .iter() + .position(|&(a, b)| a <= i && i < b) + .unwrap() + }; let selector_indices = gates .iter() .map(|g| combination(index(g.0.id()))) .collect::>(); - let combination_nums = selector_indices + let combination_ranges = selector_indices .iter() - .map(|&i| combinations[i].1 - combinations[i].0) + .map(|&i| (combinations[i].0, combinations[i].1)) .collect(); for (j, g) in instances.iter().enumerate() { @@ -47,7 +52,7 @@ pub(crate) fn compute_selectors, const D: usize>( } = g; let i = index(gate_ref.0.id()); let comb = combination(i); - polynomials[comb].values[j] = F::from_canonical_usize(i - combinations[comb].0); + polynomials[comb].values[j] = F::from_canonical_usize(i); let mut k = 0; let mut constant_ind = 0; while k < constants.len() { @@ -60,5 +65,5 @@ pub(crate) fn compute_selectors, const D: usize>( } } } - (polynomials, selector_indices, combination_nums) + (polynomials, selector_indices, combination_ranges) } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 0eaccc0c..ffa253c1 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -804,7 +804,7 @@ impl, const D: usize> CircuitBuilder { degree_bits, gates, selector_indices, - combination_nums, + combination_ranges, quotient_degree_factor, num_gate_constraints, num_constants, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index c0bf2251..4ce51b3a 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -249,7 +249,7 @@ pub struct CommonCircuitData< pub(crate) gates: Vec>, pub(crate) selector_indices: Vec, - pub(crate) combination_nums: Vec, + pub(crate) combination_ranges: Vec<(usize, usize)>, /// The degree of the PLONK quotient polynomial. pub(crate) quotient_degree_factor: usize, diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 2ad1bf70..3ba968af 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -219,8 +219,9 @@ pub fn evaluate_gate_constraints< for (i, gate) in common_data.gates.iter().enumerate() { let gate_constraints = gate.0.eval_filtered( vars.clone(), + i, common_data.selector_indices[i], - common_data.combination_nums[i], + common_data.combination_ranges[i], ); for (i, c) in gate_constraints.into_iter().enumerate() { debug_assert!( @@ -250,8 +251,9 @@ pub fn evaluate_gate_constraints_base_batch< for (i, gate) in common_data.gates.iter().enumerate() { let gate_constraints_batch = gate.0.eval_filtered_base_batch( vars_batch.clone(), + i, common_data.selector_indices[i], - common_data.combination_nums[i], + common_data.combination_ranges[i], ); debug_assert!( gate_constraints_batch.len() <= constraints_batch.len(), @@ -284,7 +286,7 @@ pub fn evaluate_gate_constraints_recursively< builder, vars.clone(), common_data.selector_indices[i], - common_data.combination_nums[i], + common_data.combination_ranges[i], &mut all_gate_constraints ) ); From 7cf322043982d05caac7163ea5f2f6a3a5a58007 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Mar 2022 14:16:02 +0100 Subject: [PATCH 08/16] Rollback --- insertion/src/insertion_gate.rs | 1 - plonky2/src/gadgets/arithmetic_extension.rs | 49 +++---------------- plonky2/src/gates/add_many_u32.rs | 1 - plonky2/src/gates/arithmetic_base.rs | 12 ++--- plonky2/src/gates/arithmetic_extension.rs | 12 ++--- plonky2/src/gates/arithmetic_u32.rs | 1 - plonky2/src/gates/assert_le.rs | 2 - plonky2/src/gates/comparison.rs | 2 - plonky2/src/gates/constant.rs | 6 ++- plonky2/src/gates/exponentiation.rs | 1 - plonky2/src/gates/gate.rs | 7 ++- plonky2/src/gates/gate_testing.rs | 13 +---- plonky2/src/gates/interpolation.rs | 1 - plonky2/src/gates/low_degree_interpolation.rs | 1 - plonky2/src/gates/multiplication_extension.rs | 4 +- plonky2/src/gates/random_access.rs | 2 - plonky2/src/gates/range_check_u32.rs | 1 - plonky2/src/gates/subtraction_u32.rs | 1 - plonky2/src/gates/switch.rs | 1 - plonky2/src/plonk/mod.rs | 1 - plonky2/src/plonk/prover.rs | 1 - plonky2/src/plonk/recursive_verifier.rs | 1 - plonky2/src/plonk/vanishing_poly.rs | 5 +- plonky2/src/plonk/vars.rs | 43 ++++++---------- plonky2/src/plonk/verifier.rs | 1 - 25 files changed, 46 insertions(+), 124 deletions(-) diff --git a/insertion/src/insertion_gate.rs b/insertion/src/insertion_gate.rs index c4e5e233..442416d3 100644 --- a/insertion/src/insertion_gate.rs +++ b/insertion/src/insertion_gate.rs @@ -415,7 +415,6 @@ mod tests { _phantom: PhantomData, }; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(orig_vec, insertion_index, element_to_insert), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index 37ccc2d6..ea3e8b13 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -613,20 +613,16 @@ mod tests { type FF = >::FE; let config = CircuitConfig::standard_recursion_zk_config(); - let config = CircuitConfig::standard_recursion_config(); - let mut pw = PartialWitness::new(); + let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); let x = FF::rand(); let y = FF::rand(); let z = x / y; - let xt = builder.add_virtual_extension_target(); - pw.set_extension_target(xt, x); - let yt = builder.add_virtual_extension_target(); - pw.set_extension_target(yt, y); - let zt = builder.add_virtual_extension_target(); - pw.set_extension_target(zt, z); + let xt = builder.constant_extension(x); + let yt = builder.constant_extension(y); + let zt = builder.constant_extension(z); let comp_zt = builder.div_extension(xt, yt); builder.connect_extension(zt, comp_zt); @@ -639,7 +635,7 @@ mod tests { #[test] fn test_mul_algebra() -> Result<()> { const D: usize = 2; - type C = PoseidonGoldilocksConfig; + type C = KeccakGoldilocksConfig; type F = >::F; type FF = >::FE; @@ -654,15 +650,14 @@ mod tests { ExtensionAlgebraTarget(builder.add_virtual_extension_targets(D).try_into().unwrap()); let zt = ExtensionAlgebraTarget(builder.add_virtual_extension_targets(D).try_into().unwrap()); - // let comp_zt = builder.mul_ext_algebra(xt, yt); - let comp_zt = builder.add_ext_algebra(xt, yt); + let comp_zt = builder.mul_ext_algebra(xt, yt); for i in 0..D { builder.connect_extension(zt.0[i], comp_zt.0[i]); } let x = ExtensionAlgebra::(FF::rand_arr()); let y = ExtensionAlgebra::(FF::rand_arr()); - let z = x + y; + let z = x * y; for i in 0..D { pw.set_extension_target(xt.0[i], x.0[i]); pw.set_extension_target(yt.0[i], y.0[i]); @@ -674,34 +669,4 @@ mod tests { verify(proof, &data.verifier_only, &data.common) } - - #[test] - fn test_yo() -> Result<()> { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - type FF = >::FE; - - let config = CircuitConfig::standard_recursion_config(); - - let mut pw = PartialWitness::new(); - let mut builder = CircuitBuilder::::new(config); - - let xt = builder.add_virtual_extension_target(); - let yt = builder.add_virtual_extension_target(); - let zt = builder.add_virtual_extension_target(); - let comp_zt = builder.mul_extension(xt, yt); - builder.connect_extension(zt, comp_zt); - - let x = FF::rand(); - let y = FF::rand(); - let z = x * y; - pw.set_extension_target(xt, x); - pw.set_extension_target(yt, y); - - let data = builder.build::(); - let proof = data.prove(pw)?; - - verify(proof, &data.verifier_only, &data.common) - } } diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index 30ca2c56..faea2a81 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -448,7 +448,6 @@ mod tests { }; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(addends, carries), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs index 9106f169..5f73fef0 100644 --- a/plonky2/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -57,8 +57,8 @@ impl, const D: usize> Gate for ArithmeticGate } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let const_0 = vars.get_constant(0); - let const_1 = vars.get_constant(1); + let const_0 = vars.local_constants[0]; + let const_1 = vars.local_constants[1]; let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -91,8 +91,8 @@ impl, const D: usize> Gate for ArithmeticGate builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - let const_0 = vars.get_constant(0); - let const_1 = vars.get_constant(1); + let const_0 = vars.local_constants[0]; + let const_1 = vars.local_constants[1]; let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -157,8 +157,8 @@ impl, const D: usize> PackedEvaluableBase for vars: EvaluationVarsBasePacked

, mut yield_constr: StridedConstraintConsumer

, ) { - let const_0 = vars.get_constant(0); - let const_1 = vars.get_constant(1); + let const_0 = vars.local_constants[0]; + let const_1 = vars.local_constants[1]; for i in 0..self.num_ops { let multiplicand_0 = vars.local_wires[Self::wire_ith_multiplicand_0(i)]; diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index e74587db..6b5af067 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -55,8 +55,8 @@ impl, const D: usize> Gate for ArithmeticExte } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let const_0 = vars.get_constant(0); - let const_1 = vars.get_constant(1); + let const_0 = vars.local_constants[0]; + let const_1 = vars.local_constants[1]; let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -78,8 +78,8 @@ impl, const D: usize> Gate for ArithmeticExte vars: EvaluationVarsBase, mut yield_constr: StridedConstraintConsumer, ) { - let const_0 = vars.get_constant(0); - let const_1 = vars.get_constant(1); + let const_0 = vars.local_constants[0]; + let const_1 = vars.local_constants[1]; for i in 0..self.num_ops { let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i)); @@ -98,8 +98,8 @@ impl, const D: usize> Gate for ArithmeticExte builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - let const_0 = vars.get_constant(0); - let const_1 = vars.get_constant(1); + let const_0 = vars.local_constants[0]; + let const_1 = vars.local_constants[1]; let mut constraints = Vec::new(); for i in 0..self.num_ops { diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index 97180f6b..65c33844 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -445,7 +445,6 @@ mod tests { }; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(multiplicands_0, multiplicands_1, addends), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index 52bdf3ec..cec7274b 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -602,7 +602,6 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), @@ -621,7 +620,6 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index 001d22f3..b1cf7b98 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -682,7 +682,6 @@ mod tests { _phantom: PhantomData, }; let less_than_vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, second_input), public_inputs_hash: &HashOut::rand(), @@ -701,7 +700,6 @@ mod tests { _phantom: PhantomData, }; let equal_vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_input, first_input), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 73cdd86b..2ef99dfc 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -42,7 +42,9 @@ impl, const D: usize> Gate for ConstantGate { fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { (0..self.num_consts) - .map(|i| vars.get_constant(self.const_input(i)) - vars.local_wires[self.wire_output(i)]) + .map(|i| { + vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)] + }) .collect() } @@ -66,7 +68,7 @@ impl, const D: usize> Gate for ConstantGate { (0..self.num_consts) .map(|i| { builder.sub_extension( - vars.get_constant(self.const_input(i)), + vars.local_constants[self.const_input(i)], vars.local_wires[self.wire_output(i)], ) }) diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index bc0100ea..51558a21 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -394,7 +394,6 @@ mod tests { }; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(base, power as u64), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index d871d830..168dab71 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -50,7 +50,6 @@ pub trait Gate, const D: usize>: 'static + Send + S .collect::>(); let public_inputs_hash = &vars_base.public_inputs_hash; let vars = EvaluationVars { - selector_index: vars_base.selector_index, local_constants, local_wires, public_inputs_hash, @@ -93,7 +92,7 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_range, vars.local_constants[selector_index], ); - vars.selector_index = selector_index; + vars.remove_prefix(prefix); self.eval_unfiltered(vars) .into_iter() .map(|c| filter * c) @@ -119,7 +118,7 @@ pub trait Gate, const D: usize>: 'static + Send + S ) }) .collect(); - vars_batch.selector_index = selector_index; + vars_batch.remove_prefix(prefix); let mut res_batch = self.eval_unfiltered_base_batch(vars_batch); for res_chunk in res_batch.chunks_exact_mut(filters.len()) { batch_multiply_inplace(res_chunk, &filters); @@ -142,7 +141,7 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_range, vars.local_constants[selector_index], ); - vars.selector_index = selector_index; + vars.remove_prefix(prefix); let my_constraints = self.eval_unfiltered_recursively(builder, vars); for (acc, c) in combined_gate_constraints.iter_mut().zip(my_constraints) { *acc = builder.mul_add_extension(filter, c, *acc); diff --git a/plonky2/src/gates/gate_testing.rs b/plonky2/src/gates/gate_testing.rs index e37c921b..51768ba8 100644 --- a/plonky2/src/gates/gate_testing.rs +++ b/plonky2/src/gates/gate_testing.rs @@ -32,7 +32,6 @@ pub fn test_low_degree, G: Gate, const D: usi .iter() .zip(constant_ldes.iter()) .map(|(local_wires, local_constants)| EvaluationVars { - selector_index: usize::MAX, local_constants, local_wires, public_inputs_hash, @@ -111,15 +110,9 @@ where let public_inputs_hash = HashOut::rand(); // Batch of 1. - let vars_base_batch = EvaluationVarsBaseBatch::new( - usize::MAX, - 1, - &constants_base, - &wires_base, - &public_inputs_hash, - ); + let vars_base_batch = + EvaluationVarsBaseBatch::new(1, &constants_base, &wires_base, &public_inputs_hash); let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, @@ -152,7 +145,6 @@ where pw.set_hash_target(public_inputs_hash_t, public_inputs_hash); let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &constants, local_wires: &wires, public_inputs_hash: &public_inputs_hash, @@ -160,7 +152,6 @@ where let evals = gate.eval_unfiltered(vars); let vars_t = EvaluationTargets { - selector_index: usize::MAX, local_constants: &constants_t, local_wires: &wires_t, public_inputs_hash: &public_inputs_hash_t, diff --git a/plonky2/src/gates/interpolation.rs b/plonky2/src/gates/interpolation.rs index b77617b9..46c42113 100644 --- a/plonky2/src/gates/interpolation.rs +++ b/plonky2/src/gates/interpolation.rs @@ -352,7 +352,6 @@ mod tests { let eval_point = FF::rand(); let gate = HighDegreeInterpolationGate::::new(1); let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/low_degree_interpolation.rs b/plonky2/src/gates/low_degree_interpolation.rs index 11fadb93..845da5ab 100644 --- a/plonky2/src/gates/low_degree_interpolation.rs +++ b/plonky2/src/gates/low_degree_interpolation.rs @@ -453,7 +453,6 @@ mod tests { let eval_point = FF::rand(); let gate = LowDegreeInterpolationGate::::new(subgroup_bits); let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(&gate, shift, coeffs, eval_point), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index df020273..52d32ab0 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -52,7 +52,7 @@ impl, const D: usize> Gate for MulExtensionGa } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let const_0 = vars.get_constant(0); + let const_0 = vars.local_constants[0]; let mut constraints = Vec::new(); for i in 0..self.num_ops { @@ -89,7 +89,7 @@ impl, const D: usize> Gate for MulExtensionGa builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - let const_0 = vars.get_constant(0); + let const_0 = vars.local_constants[0]; let mut constraints = Vec::new(); for i in 0..self.num_ops { diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index c628255c..6379f99f 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -413,7 +413,6 @@ mod tests { .map(|(l, &i)| l[i]) .collect(); let good_vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires( bits, @@ -425,7 +424,6 @@ mod tests { }; let bad_claimed_elements = F::rand_vec(4); let bad_vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(bits, lists, access_indices, bad_claimed_elements), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/range_check_u32.rs b/plonky2/src/gates/range_check_u32.rs index 7aa3e6c5..79e91de8 100644 --- a/plonky2/src/gates/range_check_u32.rs +++ b/plonky2/src/gates/range_check_u32.rs @@ -292,7 +292,6 @@ mod tests { }; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(input_limbs), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index 3a53091b..b1e4d84f 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -437,7 +437,6 @@ mod tests { }; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(inputs_x, inputs_y, borrows), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/gates/switch.rs b/plonky2/src/gates/switch.rs index 524bda3e..bd298762 100644 --- a/plonky2/src/gates/switch.rs +++ b/plonky2/src/gates/switch.rs @@ -446,7 +446,6 @@ mod tests { }; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants: &[], local_wires: &get_wires(first_inputs, second_inputs, switch_bools), public_inputs_hash: &HashOut::rand(), diff --git a/plonky2/src/plonk/mod.rs b/plonky2/src/plonk/mod.rs index 6306d209..4f2fa4e1 100644 --- a/plonky2/src/plonk/mod.rs +++ b/plonky2/src/plonk/mod.rs @@ -1,7 +1,6 @@ pub mod circuit_builder; pub mod circuit_data; pub mod config; -mod constest; pub(crate) mod copy_constraint; mod get_challenges; pub(crate) mod permutation_argument; diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index 69baf038..1d99b60a 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -427,7 +427,6 @@ fn compute_quotient_polys< } let vars_batch = EvaluationVarsBaseBatch::new( - usize::MAX, xs_batch.len(), &local_constants_batch, &local_wires_batch, diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index 52b44bd1..bfe9aeb6 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -56,7 +56,6 @@ impl, const D: usize> CircuitBuilder { let local_constants = &proof.openings.constants; let local_wires = &proof.openings.wires; let vars = EvaluationTargets { - selector_index: usize::MAX, local_constants, local_wires, public_inputs_hash: &public_inputs_hash, diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 3ba968af..7be35e4f 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -40,7 +40,7 @@ pub(crate) fn eval_vanishing_poly< let max_degree = common_data.quotient_degree_factor; let num_prods = common_data.num_partial_products; - let constraint_terms = evaluate_gate_constraints(common_data, vars.clone()); + let constraint_terms = evaluate_gate_constraints(common_data, vars); // The L_1(x) (Z(x) - 1) vanishing terms. let mut vanishing_z_1_terms = Vec::new(); @@ -127,8 +127,7 @@ pub(crate) fn eval_vanishing_poly_base_batch< let num_gate_constraints = common_data.num_gate_constraints; - let constraint_terms_batch = - evaluate_gate_constraints_base_batch(&common_data, vars_batch.clone()); + let constraint_terms_batch = evaluate_gate_constraints_base_batch(&common_data, vars_batch); debug_assert!(constraint_terms_batch.len() == n * num_gate_constraints); let num_challenges = common_data.config.num_challenges; diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index fa6e9927..e2e52cfb 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -1,5 +1,4 @@ use std::ops::Range; -use std::os::unix::raw::uid_t; use plonky2_field::extension_field::algebra::ExtensionAlgebra; use plonky2_field::extension_field::{Extendable, FieldExtension}; @@ -12,7 +11,6 @@ use crate::util::strided_view::PackedStridedView; #[derive(Debug, Copy, Clone)] pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { - pub selector_index: usize, pub local_constants: &'a [F::Extension], pub local_wires: &'a [F::Extension], pub public_inputs_hash: &'a HashOut, @@ -23,7 +21,6 @@ pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { /// evaluation points, then wire 1 for all points, and so on). #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBaseBatch<'a, F: Field> { - pub selector_index: usize, batch_size: usize, pub local_constants: &'a [F], pub local_wires: &'a [F], @@ -33,7 +30,6 @@ pub struct EvaluationVarsBaseBatch<'a, F: Field> { /// A view into `EvaluationVarsBaseBatch` for a particular evaluation point. Does not copy the data. #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBase<'a, F: Field> { - pub selector_index: usize, pub local_constants: PackedStridedView<'a, F>, pub local_wires: PackedStridedView<'a, F>, pub public_inputs_hash: &'a HashOut, @@ -44,22 +40,12 @@ pub struct EvaluationVarsBase<'a, F: Field> { // have packed extension fields. #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBasePacked<'a, P: PackedField> { - pub selector_index: usize, pub local_constants: PackedStridedView<'a, P>, pub local_wires: PackedStridedView<'a, P>, pub public_inputs_hash: &'a HashOut, } -impl<'a, P: PackedField> EvaluationVarsBasePacked<'a, P> { - pub fn get_constant(&self, i: usize) -> P { - self.local_constants[if i < self.selector_index { i } else { i + 1 }] - } -} impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> { - pub fn get_constant(&self, i: usize) -> F::Extension { - self.local_constants[if i < self.selector_index { i } else { i + 1 }] - } - pub fn get_local_ext_algebra( &self, wire_range: Range, @@ -68,11 +54,14 @@ impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> let arr = self.local_wires[wire_range].try_into().unwrap(); ExtensionAlgebra::from_basefield_array(arr) } + + pub fn remove_prefix(&mut self, prefix: &[bool]) { + self.local_constants = &self.local_constants[prefix.len()..]; + } } impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { pub fn new( - selector_index: usize, batch_size: usize, local_constants: &'a [F], local_wires: &'a [F], @@ -81,7 +70,6 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { assert_eq!(local_constants.len() % batch_size, 0); assert_eq!(local_wires.len() % batch_size, 0); Self { - selector_index, batch_size, local_constants, local_wires, @@ -89,6 +77,10 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { } } + pub fn remove_prefix(&mut self, prefix: &[bool]) { + self.local_constants = &self.local_constants[prefix.len() * self.len()..]; + } + pub fn len(&self) -> usize { self.batch_size } @@ -99,7 +91,6 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { let local_constants = PackedStridedView::new(self.local_constants, self.len(), index); let local_wires = PackedStridedView::new(self.local_wires, self.len(), index); EvaluationVarsBase { - selector_index: self.selector_index, local_constants, local_wires, public_inputs_hash: self.public_inputs_hash, @@ -125,10 +116,6 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { } impl<'a, F: Field> EvaluationVarsBase<'a, F> { - pub fn get_constant(&self, i: usize) -> F { - self.local_constants[if i < self.selector_index { i } else { i + 1 }] - } - pub fn get_local_ext(&self, wire_range: Range) -> F::Extension where F: RichField + Extendable, @@ -168,7 +155,6 @@ impl<'a, F: Field> Iterator for EvaluationVarsBaseBatchIter<'a, F> { /// Note: if the length of `EvaluationVarsBaseBatch` is not a multiple of `P::WIDTH`, then the /// leftovers at the end are ignored. pub struct EvaluationVarsBaseBatchIterPacked<'a, P: PackedField> { - selector_index: usize, /// Index to yield next, in units of `P::Scalar`. E.g. if `P::WIDTH == 4`, then we will yield /// the vars for points `i`, `i + 1`, `i + 2`, and `i + 3`, packed. i: usize, @@ -182,7 +168,6 @@ impl<'a, P: PackedField> EvaluationVarsBaseBatchIterPacked<'a, P> { ) -> Self { assert!(start <= vars_batch.len()); EvaluationVarsBaseBatchIterPacked { - selector_index: vars_batch.selector_index, i: start, vars_batch, } @@ -201,7 +186,6 @@ impl<'a, P: PackedField> Iterator for EvaluationVarsBaseBatchIterPacked<'a, P> { let local_wires = PackedStridedView::new(self.vars_batch.local_wires, self.vars_batch.len(), self.i); let res = EvaluationVarsBasePacked { - selector_index: self.selector_index, local_constants, local_wires, public_inputs_hash: self.vars_batch.public_inputs_hash, @@ -224,19 +208,20 @@ impl<'a, P: PackedField> ExactSizeIterator for EvaluationVarsBaseBatchIterPacked } } +impl<'a, const D: usize> EvaluationTargets<'a, D> { + pub fn remove_prefix(&mut self, prefix: &[bool]) { + self.local_constants = &self.local_constants[prefix.len()..]; + } +} + #[derive(Copy, Clone)] pub struct EvaluationTargets<'a, const D: usize> { - pub selector_index: usize, pub local_constants: &'a [ExtensionTarget], pub local_wires: &'a [ExtensionTarget], pub public_inputs_hash: &'a HashOutTarget, } impl<'a, const D: usize> EvaluationTargets<'a, D> { - pub fn get_constant(&self, i: usize) -> ExtensionTarget { - self.local_constants[if i < self.selector_index { i } else { i + 1 }] - } - pub fn get_local_ext_algebra(&self, wire_range: Range) -> ExtensionAlgebraTarget { debug_assert_eq!(wire_range.len(), D); let arr = self.local_wires[wire_range].try_into().unwrap(); diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index e79d51b7..ee0e976f 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -52,7 +52,6 @@ where let local_constants = &proof.openings.constants; let local_wires = &proof.openings.wires; let vars = EvaluationVars { - selector_index: usize::MAX, local_constants, local_wires, public_inputs_hash: &public_inputs_hash, From c6ebd0690770e6ea1a52fb8becdc68748d532100 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 23 Mar 2022 15:47:22 +0100 Subject: [PATCH 09/16] Not working yet --- plonky2/src/gadgets/arithmetic_extension.rs | 1 + plonky2/src/gates/gate.rs | 18 ++++++---- plonky2/src/gates/selectors.rs | 39 +++++++++++++-------- plonky2/src/plonk/circuit_builder.rs | 14 ++++---- plonky2/src/plonk/circuit_data.rs | 1 + plonky2/src/plonk/vanishing_poly.rs | 10 ++++-- plonky2/src/plonk/vars.rs | 12 +++---- 7 files changed, 59 insertions(+), 36 deletions(-) diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index ea3e8b13..3b8b11c7 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -613,6 +613,7 @@ mod tests { type FF = >::FE; let config = CircuitConfig::standard_recursion_zk_config(); + let config = CircuitConfig::standard_recursion_config(); let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 168dab71..b5fc7772 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -86,13 +86,14 @@ pub trait Gate, const D: usize>: 'static + Send + S gate_index: usize, selector_index: usize, combination_range: (usize, usize), + num_selectors: usize, ) -> Vec { let filter = compute_filter( gate_index, combination_range, vars.local_constants[selector_index], ); - vars.remove_prefix(prefix); + vars.remove_prefix(num_selectors); self.eval_unfiltered(vars) .into_iter() .map(|c| filter * c) @@ -107,6 +108,7 @@ pub trait Gate, const D: usize>: 'static + Send + S gate_index: usize, selector_index: usize, combination_range: (usize, usize), + num_selectors: usize, ) -> Vec { let filters: Vec<_> = vars_batch .iter() @@ -118,7 +120,7 @@ pub trait Gate, const D: usize>: 'static + Send + S ) }) .collect(); - vars_batch.remove_prefix(prefix); + vars_batch.remove_prefix(num_selectors); let mut res_batch = self.eval_unfiltered_base_batch(vars_batch); for res_chunk in res_batch.chunks_exact_mut(filters.len()) { batch_multiply_inplace(res_chunk, &filters); @@ -131,17 +133,19 @@ pub trait Gate, const D: usize>: 'static + Send + S &self, builder: &mut CircuitBuilder, mut vars: EvaluationTargets, + gate_index: usize, selector_index: usize, combination_range: (usize, usize), combined_gate_constraints: &mut [ExtensionTarget], + num_selectors: usize, ) { let filter = compute_filter_recursively( builder, - selector_index, + gate_index, combination_range, vars.local_constants[selector_index], ); - vars.remove_prefix(prefix); + vars.remove_prefix(num_selectors); let my_constraints = self.eval_unfiltered_recursively(builder, vars); for (acc, c) in combined_gate_constraints.iter_mut().zip(my_constraints) { *acc = builder.mul_add_extension(filter, c, *acc); @@ -244,18 +248,20 @@ fn compute_filter<'a, K: Field>( ) -> K { (combination_range.0..combination_range.1) .filter(|&i| i != gate_index) + .chain(Some(u32::MAX as usize)) .map(|i| K::from_canonical_usize(i) - constant) .product() } fn compute_filter_recursively, const D: usize>( builder: &mut CircuitBuilder, - selector_index: usize, + gate_index: usize, combination_range: (usize, usize), constant: ExtensionTarget, ) -> ExtensionTarget { let v = (combination_range.0..combination_range.1) - .filter(|&i| i != selector_index) + .filter(|&i| i != gate_index) + .chain(Some(u32::MAX as usize)) .map(|i| builder.constant_extension(F::Extension::from_canonical_usize(i))) .collect::>(); let v = v diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index c1461c09..3eb5282e 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -8,7 +8,12 @@ pub(crate) fn compute_selectors, const D: usize>( mut gates: Vec>, instances: &[GateInstance], max_degree: usize, -) -> (Vec>, Vec, Vec<(usize, usize)>) { +) -> ( + Vec>, + Vec, + Vec<(usize, usize)>, + usize, +) { let n = instances.len(); let mut combinations = Vec::new(); @@ -16,15 +21,16 @@ pub(crate) fn compute_selectors, const D: usize>( while pos < gates.len() { let mut i = 0; - while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() <= max_degree + 1) { + while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() <= max_degree) { i += 1; } combinations.push((pos, pos + i)); pos += i; } + dbg!(&combinations); + let bad = F::from_canonical_usize(u32::MAX as usize); - let num_constants_polynomials = - 0.max(gates.iter().map(|g| g.0.num_constants()).max().unwrap() - combinations.len() + 1); + let num_constants_polynomials = gates.iter().map(|g| g.0.num_constants()).max().unwrap(); let mut polynomials = vec![PolynomialValues::zero(n); combinations.len() + num_constants_polynomials]; @@ -53,17 +59,20 @@ pub(crate) fn compute_selectors, const D: usize>( let i = index(gate_ref.0.id()); let comb = combination(i); polynomials[comb].values[j] = F::from_canonical_usize(i); - let mut k = 0; - let mut constant_ind = 0; - while k < constants.len() { - if constant_ind == comb { - constant_ind += 1; - } else { - polynomials[constant_ind].values[j] = constants[k]; - constant_ind += 1; - k += 1; - } + + for combis in (0..combinations.len()).filter(|&combis| combis != comb) { + polynomials[combis].values[j] = bad; + } + + for k in 0..constants.len() { + polynomials[combinations.len() + k].values[j] = constants[k]; } } - (polynomials, selector_indices, combination_ranges) + + ( + polynomials, + selector_indices, + combination_ranges, + combinations.len(), + ) } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index ffa253c1..49acaade 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -676,12 +676,13 @@ impl, const D: usize> CircuitBuilder { let mut gates = self.gates.iter().cloned().collect::>(); gates.sort_unstable_by_key(|g| g.0.degree()); dbg!(&gates); - let (constant_vecs, selector_indices, combination_nums) = compute_selectors( - gates.clone(), - &self.gate_instances, - self.config.max_quotient_degree_factor + 1, - ); - dbg!(&constant_vecs, &selector_indices, &combination_nums); + let (constant_vecs, selector_indices, combination_ranges, num_selectors) = + compute_selectors( + gates.clone(), + &self.gate_instances, + self.config.max_quotient_degree_factor + 1, + ); + dbg!(&constant_vecs, &selector_indices, &combination_ranges); let num_constants = constant_vecs.len(); // let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates); // let prefixed_gates = PrefixedGate::from_tree(gate_tree); @@ -805,6 +806,7 @@ impl, const D: usize> CircuitBuilder { gates, selector_indices, combination_ranges, + num_selectors, quotient_degree_factor, num_gate_constraints, num_constants, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 4ce51b3a..c889def9 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -250,6 +250,7 @@ pub struct CommonCircuitData< pub(crate) selector_indices: Vec, pub(crate) combination_ranges: Vec<(usize, usize)>, + pub(crate) num_selectors: usize, /// The degree of the PLONK quotient polynomial. pub(crate) quotient_degree_factor: usize, diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 7be35e4f..ff578759 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -217,10 +217,11 @@ pub fn evaluate_gate_constraints< let mut constraints = vec![F::Extension::ZERO; common_data.num_gate_constraints]; for (i, gate) in common_data.gates.iter().enumerate() { let gate_constraints = gate.0.eval_filtered( - vars.clone(), + vars, i, common_data.selector_indices[i], common_data.combination_ranges[i], + common_data.num_selectors, ); for (i, c) in gate_constraints.into_iter().enumerate() { debug_assert!( @@ -253,6 +254,7 @@ pub fn evaluate_gate_constraints_base_batch< i, common_data.selector_indices[i], common_data.combination_ranges[i], + common_data.num_selectors, ); debug_assert!( gate_constraints_batch.len() <= constraints_batch.len(), @@ -283,10 +285,12 @@ pub fn evaluate_gate_constraints_recursively< &format!("evaluate {} constraints", gate.0.id()), gate.0.eval_filtered_recursively( builder, - vars.clone(), + vars, + i, common_data.selector_indices[i], common_data.combination_ranges[i], - &mut all_gate_constraints + &mut all_gate_constraints, + common_data.num_selectors ) ); } diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index e2e52cfb..8c7b71e3 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -55,8 +55,8 @@ impl<'a, F: RichField + Extendable, const D: usize> EvaluationVars<'a, F, D> ExtensionAlgebra::from_basefield_array(arr) } - pub fn remove_prefix(&mut self, prefix: &[bool]) { - self.local_constants = &self.local_constants[prefix.len()..]; + pub fn remove_prefix(&mut self, num_selectors: usize) { + self.local_constants = &self.local_constants[num_selectors..]; } } @@ -77,8 +77,8 @@ impl<'a, F: Field> EvaluationVarsBaseBatch<'a, F> { } } - pub fn remove_prefix(&mut self, prefix: &[bool]) { - self.local_constants = &self.local_constants[prefix.len() * self.len()..]; + pub fn remove_prefix(&mut self, num_selectors: usize) { + self.local_constants = &self.local_constants[num_selectors * self.len()..]; } pub fn len(&self) -> usize { @@ -209,8 +209,8 @@ impl<'a, P: PackedField> ExactSizeIterator for EvaluationVarsBaseBatchIterPacked } impl<'a, const D: usize> EvaluationTargets<'a, D> { - pub fn remove_prefix(&mut self, prefix: &[bool]) { - self.local_constants = &self.local_constants[prefix.len()..]; + pub fn remove_prefix(&mut self, num_selectors: usize) { + self.local_constants = &self.local_constants[num_selectors..]; } } From 1d77116ef3ff5186c6599047326ebae6563ed861 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 24 Mar 2022 07:19:48 +0100 Subject: [PATCH 10/16] Working --- plonky2/src/gadgets/biguint.rs | 2 ++ plonky2/src/gates/gate.rs | 7 +++++++ plonky2/src/gates/selectors.rs | 2 +- plonky2/src/plonk/circuit_builder.rs | 28 ++++++++++++++-------------- plonky2/src/plonk/circuit_data.rs | 2 +- plonky2/src/plonk/mod.rs | 1 + plonky2/src/plonk/vars.rs | 2 +- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/plonky2/src/gadgets/biguint.rs b/plonky2/src/gadgets/biguint.rs index c9ad7280..b516bd70 100644 --- a/plonky2/src/gadgets/biguint.rs +++ b/plonky2/src/gadgets/biguint.rs @@ -262,6 +262,7 @@ mod tests { use crate::iop::witness::Witness; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + use crate::plonk::constest::check_constraints; use crate::{ iop::witness::PartialWitness, plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig, verifier::verify}, @@ -352,6 +353,7 @@ mod tests { pw.set_biguint_target(&y, &y_value); pw.set_biguint_target(&expected_z, &expected_z_value); + // check_constraints::(builder, pw) let data = builder.build::(); let proof = data.prove(pw).unwrap(); verify(proof, &data.verifier_only, &data.common) diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index b5fc7772..ccc65512 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -93,6 +93,13 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_range, vars.local_constants[selector_index], ); + // println!( + // "{} {:?} {} {}", + // self.id(), + // combination_range, + // gate_index, + // self.degree() + // ); vars.remove_prefix(num_selectors); self.eval_unfiltered(vars) .into_iter() diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 3eb5282e..9d0145af 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -21,7 +21,7 @@ pub(crate) fn compute_selectors, const D: usize>( while pos < gates.len() { let mut i = 0; - while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() <= max_degree) { + while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() + 1 <= max_degree) { i += 1; } combinations.push((pos, pos + i)); diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 49acaade..fd28f2ea 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -51,16 +51,16 @@ pub struct CircuitBuilder, const D: usize> { pub config: CircuitConfig, /// The types of gates used in this circuit. - gates: HashSet>, + pub(crate) gates: HashSet>, /// The concrete placement of each gate. pub(crate) gate_instances: Vec>, /// Targets to be made public. - public_inputs: Vec, + pub(crate) public_inputs: Vec, /// The next available index for a `VirtualTarget`. - virtual_target_index: usize, + pub(crate) virtual_target_index: usize, copy_constraints: Vec, @@ -68,10 +68,10 @@ pub struct CircuitBuilder, const D: usize> { context_log: ContextTree, /// A vector of marked targets. The values assigned to these targets will be displayed by the prover. - marked_targets: Vec>, + pub(crate) marked_targets: Vec>, /// Generators used to generate the witness. - generators: Vec>>, + pub(crate) generators: Vec>>, constants_to_targets: HashMap, targets_to_constants: HashMap, @@ -83,7 +83,7 @@ pub struct CircuitBuilder, const D: usize> { pub(crate) arithmetic_results: HashMap, ExtensionTarget>, /// Map between gate type and the current gate of this type with available slots. - current_slots: HashMap, CurrentSlot>, + pub(crate) current_slots: HashMap, CurrentSlot>, } impl, const D: usize> CircuitBuilder { @@ -424,7 +424,7 @@ impl, const D: usize> CircuitBuilder { (gate_idx, slot_idx) } - fn fri_params(&self, degree_bits: usize) -> FriParams { + pub(crate) fn fri_params(&self, degree_bits: usize) -> FriParams { self.config .fri_config .fri_params(degree_bits, self.config.zero_knowledge) @@ -493,7 +493,7 @@ impl, const D: usize> CircuitBuilder { } } - fn blind_and_pad(&mut self) { + pub(crate) fn blind_and_pad(&mut self) { if self.config.zero_knowledge { self.blind(); } @@ -580,7 +580,11 @@ impl, const D: usize> CircuitBuilder { .collect() } - fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> (Vec>, Forest) { + pub(crate) fn sigma_vecs( + &self, + k_is: &[F], + subgroup: &[F], + ) -> (Vec>, Forest) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); let config = &self.config; @@ -637,9 +641,6 @@ impl, const D: usize> CircuitBuilder { where [(); C::Hasher::HASH_SIZE]:, { - for g in &self.gate_instances { - dbg!(&g.gate_ref.0.id()); - } let mut timing = TimingTree::new("preprocess", Level::Trace); let start = Instant::now(); let rate_bits = self.config.fri_config.rate_bits; @@ -675,14 +676,13 @@ impl, const D: usize> CircuitBuilder { let mut gates = self.gates.iter().cloned().collect::>(); gates.sort_unstable_by_key(|g| g.0.degree()); - dbg!(&gates); let (constant_vecs, selector_indices, combination_ranges, num_selectors) = compute_selectors( gates.clone(), &self.gate_instances, self.config.max_quotient_degree_factor + 1, ); - dbg!(&constant_vecs, &selector_indices, &combination_ranges); + // dbg!(&constant_vecs, &selector_indices, &combination_ranges); let num_constants = constant_vecs.len(); // let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates); // let prefixed_gates = PrefixedGate::from_tree(gate_tree); diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index c889def9..c5910f0a 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -63,7 +63,7 @@ impl CircuitConfig { Self { num_wires: 135, num_routed_wires: 80, - constant_gate_size: 2, + constant_gate_size: 5, use_base_arithmetic_gate: true, security_bits: 100, num_challenges: 2, diff --git a/plonky2/src/plonk/mod.rs b/plonky2/src/plonk/mod.rs index 4f2fa4e1..fe025898 100644 --- a/plonky2/src/plonk/mod.rs +++ b/plonky2/src/plonk/mod.rs @@ -1,6 +1,7 @@ pub mod circuit_builder; pub mod circuit_data; pub mod config; +pub mod constest; pub(crate) mod copy_constraint; mod get_challenges; pub(crate) mod permutation_argument; diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index 8c7b71e3..91529b15 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -21,7 +21,7 @@ pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { /// evaluation points, then wire 1 for all points, and so on). #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBaseBatch<'a, F: Field> { - batch_size: usize, + pub(crate) batch_size: usize, pub local_constants: &'a [F], pub local_wires: &'a [F], pub public_inputs_hash: &'a HashOut, From d6b99df876ce220537d9f1c7ed47757ba49c4629 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 25 Mar 2022 06:36:04 +0100 Subject: [PATCH 11/16] Cleaning --- plonky2/src/gadgets/arithmetic_extension.rs | 1 - plonky2/src/gadgets/biguint.rs | 2 - plonky2/src/gates/add_many_u32.rs | 84 ++--- plonky2/src/gates/arithmetic_u32.rs | 22 +- plonky2/src/gates/constant.rs | 42 +-- plonky2/src/gates/gate.rs | 19 +- plonky2/src/gates/gate_tree.rs | 294 ------------------ plonky2/src/gates/mod.rs | 1 - plonky2/src/gates/multiplication_extension.rs | 32 +- plonky2/src/gates/public_input.rs | 22 +- plonky2/src/gates/selectors.rs | 5 +- plonky2/src/plonk/circuit_builder.rs | 72 +---- plonky2/src/plonk/circuit_data.rs | 2 +- plonky2/src/plonk/mod.rs | 1 - plonky2/src/plonk/recursive_verifier.rs | 2 - plonky2/src/plonk/vanishing_poly.rs | 5 +- plonky2/src/plonk/vars.rs | 2 +- 17 files changed, 119 insertions(+), 489 deletions(-) delete mode 100644 plonky2/src/gates/gate_tree.rs diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index 3b8b11c7..ea3e8b13 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -613,7 +613,6 @@ mod tests { type FF = >::FE; let config = CircuitConfig::standard_recursion_zk_config(); - let config = CircuitConfig::standard_recursion_config(); let pw = PartialWitness::new(); let mut builder = CircuitBuilder::::new(config); diff --git a/plonky2/src/gadgets/biguint.rs b/plonky2/src/gadgets/biguint.rs index b516bd70..c9ad7280 100644 --- a/plonky2/src/gadgets/biguint.rs +++ b/plonky2/src/gadgets/biguint.rs @@ -262,7 +262,6 @@ mod tests { use crate::iop::witness::Witness; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use crate::plonk::constest::check_constraints; use crate::{ iop::witness::PartialWitness, plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig, verifier::verify}, @@ -353,7 +352,6 @@ mod tests { pw.set_biguint_target(&y, &y_value); pw.set_biguint_target(&expected_z, &expected_z_value); - // check_constraints::(builder, pw) let data = builder.build::(); let proof = data.prove(pw).unwrap(); verify(proof, &data.verifier_only, &data.common) diff --git a/plonky2/src/gates/add_many_u32.rs b/plonky2/src/gates/add_many_u32.rs index faea2a81..4f9c4293 100644 --- a/plonky2/src/gates/add_many_u32.rs +++ b/plonky2/src/gates/add_many_u32.rs @@ -130,48 +130,48 @@ impl, const D: usize> Gate for U32AddManyGate constraints } - // fn eval_unfiltered_base_one( - // &self, - // vars: EvaluationVarsBase, - // mut yield_constr: StridedConstraintConsumer, - // ) { - // for i in 0..self.num_ops { - // let addends: Vec = (0..self.num_addends) - // .map(|j| vars.local_wires[self.wire_ith_op_jth_addend(i, j)]) - // .collect(); - // let carry = vars.local_wires[self.wire_ith_carry(i)]; - // - // let computed_output = addends.iter().fold(F::ZERO, |x, &y| x + y) + carry; - // - // let output_result = vars.local_wires[self.wire_ith_output_result(i)]; - // let output_carry = vars.local_wires[self.wire_ith_output_carry(i)]; - // - // let base = F::from_canonical_u64(1 << 32u64); - // let combined_output = output_carry * base + output_result; - // - // yield_constr.one(combined_output - computed_output); - // - // let mut combined_result_limbs = F::ZERO; - // let mut combined_carry_limbs = F::ZERO; - // let base = F::from_canonical_u64(1u64 << Self::limb_bits()); - // for j in (0..Self::num_limbs()).rev() { - // let this_limb = vars.local_wires[self.wire_ith_output_jth_limb(i, j)]; - // let max_limb = 1 << Self::limb_bits(); - // let product = (0..max_limb) - // .map(|x| this_limb - F::from_canonical_usize(x)) - // .product(); - // yield_constr.one(product); - // - // if j < Self::num_result_limbs() { - // combined_result_limbs = base * combined_result_limbs + this_limb; - // } else { - // combined_carry_limbs = base * combined_carry_limbs + this_limb; - // } - // } - // yield_constr.one(combined_result_limbs - output_result); - // yield_constr.one(combined_carry_limbs - output_carry); - // } - // } + fn eval_unfiltered_base_one( + &self, + vars: EvaluationVarsBase, + mut yield_constr: StridedConstraintConsumer, + ) { + for i in 0..self.num_ops { + let addends: Vec = (0..self.num_addends) + .map(|j| vars.local_wires[self.wire_ith_op_jth_addend(i, j)]) + .collect(); + let carry = vars.local_wires[self.wire_ith_carry(i)]; + + let computed_output = addends.iter().fold(F::ZERO, |x, &y| x + y) + carry; + + let output_result = vars.local_wires[self.wire_ith_output_result(i)]; + let output_carry = vars.local_wires[self.wire_ith_output_carry(i)]; + + let base = F::from_canonical_u64(1 << 32u64); + let combined_output = output_carry * base + output_result; + + yield_constr.one(combined_output - computed_output); + + let mut combined_result_limbs = F::ZERO; + let mut combined_carry_limbs = F::ZERO; + let base = F::from_canonical_u64(1u64 << Self::limb_bits()); + for j in (0..Self::num_limbs()).rev() { + let this_limb = vars.local_wires[self.wire_ith_output_jth_limb(i, j)]; + let max_limb = 1 << Self::limb_bits(); + let product = (0..max_limb) + .map(|x| this_limb - F::from_canonical_usize(x)) + .product(); + yield_constr.one(product); + + if j < Self::num_result_limbs() { + combined_result_limbs = base * combined_result_limbs + this_limb; + } else { + combined_carry_limbs = base * combined_carry_limbs + this_limb; + } + } + yield_constr.one(combined_result_limbs - output_result); + yield_constr.one(combined_carry_limbs - output_carry); + } + } fn eval_unfiltered_recursively( &self, diff --git a/plonky2/src/gates/arithmetic_u32.rs b/plonky2/src/gates/arithmetic_u32.rs index 65c33844..dc03e296 100644 --- a/plonky2/src/gates/arithmetic_u32.rs +++ b/plonky2/src/gates/arithmetic_u32.rs @@ -125,17 +125,17 @@ impl, const D: usize> Gate for U32ArithmeticG constraints } - // fn eval_unfiltered_base_one( - // &self, - // _vars: EvaluationVarsBase, - // _yield_constr: StridedConstraintConsumer, - // ) { - // panic!("use eval_unfiltered_base_packed instead"); - // } - // - // fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { - // self.eval_unfiltered_base_batch_packed(vars_base) - // } + fn eval_unfiltered_base_one( + &self, + _vars: EvaluationVarsBase, + _yield_constr: StridedConstraintConsumer, + ) { + panic!("use eval_unfiltered_base_packed instead"); + } + + fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { + self.eval_unfiltered_base_batch_packed(vars_base) + } fn eval_unfiltered_recursively( &self, diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index 2ef99dfc..990a4df8 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -48,17 +48,17 @@ impl, const D: usize> Gate for ConstantGate { .collect() } - // fn eval_unfiltered_base_one( - // &self, - // _vars: EvaluationVarsBase, - // _yield_constr: StridedConstraintConsumer, - // ) { - // panic!("use eval_unfiltered_base_packed instead"); - // } + fn eval_unfiltered_base_one( + &self, + _vars: EvaluationVarsBase, + _yield_constr: StridedConstraintConsumer, + ) { + panic!("use eval_unfiltered_base_packed instead"); + } - // fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { - // self.eval_unfiltered_base_batch_packed(vars_base) - // } + fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { + self.eval_unfiltered_base_batch_packed(vars_base) + } fn eval_unfiltered_recursively( &self, @@ -113,17 +113,17 @@ impl, const D: usize> Gate for ConstantGate { } } -// impl, const D: usize> PackedEvaluableBase for ConstantGate { -// fn eval_unfiltered_base_packed>( -// &self, -// vars: EvaluationVarsBasePacked

, -// mut yield_constr: StridedConstraintConsumer

, -// ) { -// yield_constr.many((0..self.num_consts).map(|i| { -// vars.get_constant(self.const_input(i)) - vars.local_wires[self.wire_output(i)] -// })); -// } -// } +impl, const D: usize> PackedEvaluableBase for ConstantGate { + fn eval_unfiltered_base_packed>( + &self, + vars: EvaluationVarsBasePacked

, + mut yield_constr: StridedConstraintConsumer

, + ) { + yield_constr.many((0..self.num_consts).map(|i| { + vars.local_constants[self.const_input(i)] - vars.local_wires[self.wire_output(i)] + })); + } +} #[derive(Debug)] struct ConstantGenerator { diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index ccc65512..bc56b2e2 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -7,7 +7,6 @@ use plonky2_field::batch_util::batch_multiply_inplace; use plonky2_field::extension_field::{Extendable, FieldExtension}; use plonky2_field::field_types::Field; -use crate::gates::gate_tree::Tree; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; @@ -93,13 +92,6 @@ pub trait Gate, const D: usize>: 'static + Send + S combination_range, vars.local_constants[selector_index], ); - // println!( - // "{} {:?} {} {}", - // self.id(), - // combination_range, - // gate_index, - // self.degree() - // ); vars.remove_prefix(num_selectors); self.eval_unfiltered(vars) .into_iter() @@ -237,18 +229,9 @@ pub struct PrefixedGate, const D: usize> { pub prefix: Vec, } -impl, const D: usize> PrefixedGate { - pub fn from_tree(tree: Tree>) -> Vec { - tree.traversal() - .into_iter() - .map(|(gate, prefix)| PrefixedGate { gate, prefix }) - .collect() - } -} - /// A gate's filter is computed as `prod b_i*c_i + (1-b_i)*(1-c_i)`, with `(b_i)` the prefix and /// `(c_i)` the local constants, which is one if the prefix of `constants` matches `prefix`. -fn compute_filter<'a, K: Field>( +fn compute_filter( gate_index: usize, combination_range: (usize, usize), constant: K, diff --git a/plonky2/src/gates/gate_tree.rs b/plonky2/src/gates/gate_tree.rs deleted file mode 100644 index 2f670337..00000000 --- a/plonky2/src/gates/gate_tree.rs +++ /dev/null @@ -1,294 +0,0 @@ -use log::debug; -use plonky2_field::extension_field::Extendable; - -use crate::gates::gate::GateRef; -use crate::hash::hash_types::RichField; - -/// A binary tree where leaves hold some type `T` and other nodes are empty. -#[derive(Debug, Clone)] -pub enum Tree { - Leaf(T), - Bifurcation(Option>>, Option>>), -} - -impl Default for Tree { - fn default() -> Self { - Self::Bifurcation(None, None) - } -} - -impl Tree { - /// Traverse a tree using a depth-first traversal and collect data and position for each leaf. - /// A leaf's position is represented by its left/right path, where `false` means left and `true` means right. - pub fn traversal(&self) -> Vec<(T, Vec)> { - let mut res = Vec::new(); - let prefix = []; - self.traverse(&prefix, &mut res); - res - } - - /// Utility function to traverse the tree. - fn traverse(&self, prefix: &[bool], current: &mut Vec<(T, Vec)>) { - match &self { - // If node is a leaf, collect the data and position. - Tree::Leaf(t) => { - current.push((t.clone(), prefix.to_vec())); - } - // Otherwise, traverse the left subtree and then the right subtree. - Tree::Bifurcation(left, right) => { - if let Some(l) = left { - let mut left_prefix = prefix.to_vec(); - left_prefix.push(false); - l.traverse(&left_prefix, current); - } - if let Some(r) = right { - let mut right_prefix = prefix.to_vec(); - right_prefix.push(true); - r.traverse(&right_prefix, current); - } - } - } - } -} - -impl, const D: usize> Tree> { - /// The binary gate tree influences the degree `D` of the constraint polynomial and the number `C` - /// of constant wires in the circuit. We want to construct a tree minimizing both values. To do so - /// we iterate over possible values of `(D, C)` and try to construct a tree with these values. - /// For this construction, we use the greedy algorithm in `Self::find_tree`. - /// This latter function greedily adds gates at the depth where - /// `filtered_deg(gate)=D, constant_wires(gate)=C` to ensure no space is wasted. - /// We return the first tree found in this manner, along with it's maximum filtered degree - /// and the number of constant wires needed when using this tree. - pub fn from_gates(mut gates: Vec>) -> (Self, usize, usize) { - let timer = std::time::Instant::now(); - gates.sort_unstable_by_key(|g| (-(g.0.degree() as isize), -(g.0.num_constants() as isize))); - - for max_degree_bits in 1..10 { - // The quotient polynomials are padded to the next power of 2 in `compute_quotient_polys`. - // So we can restrict our search space by setting `max_degree` to 1 + a power of 2. - let max_degree = (1 << max_degree_bits) + 1; - for max_constants in 1..100 { - if let Some(mut best_tree) = Self::find_tree(&gates, max_degree, max_constants) { - let mut best_num_constants = best_tree.num_constants(); - let mut best_degree = max_degree; - // Iterate backwards from `max_degree` to try to find a tree with a lower degree - // but the same number of constants. - 'optdegree: for degree in (0..max_degree).rev() { - if let Some(tree) = Self::find_tree(&gates, degree, max_constants) { - let num_constants = tree.num_constants(); - if num_constants > best_num_constants { - break 'optdegree; - } else { - best_degree = degree; - best_num_constants = num_constants; - best_tree = tree; - } - } - } - debug!( - "Found tree with max degree {} and {} constants wires in {:.4}s.", - best_degree, - best_num_constants, - timer.elapsed().as_secs_f32() - ); - return (best_tree, best_degree, best_num_constants); - } - } - } - - panic!("Can't find a tree.") - } - - /// Greedily add gates wherever possible. Returns `None` if this fails. - fn find_tree(gates: &[GateRef], max_degree: usize, max_constants: usize) -> Option { - let mut tree = Tree::default(); - - for g in gates { - tree.try_add_gate(g, max_degree, max_constants)?; - } - tree.shorten(); - Some(tree) - } - - /// Try to add a gate in the tree. Returns `None` if this fails. - fn try_add_gate( - &mut self, - g: &GateRef, - max_degree: usize, - max_constants: usize, - ) -> Option<()> { - // We want `gate.degree + depth <= max_degree` and `gate.num_constants + depth <= max_wires`. - let depth = max_degree - .checked_sub(g.0.degree())? - .min(max_constants.checked_sub(g.0.num_constants())?); - self.try_add_gate_at_depth(g, depth) - } - - /// Try to add a gate in the tree at a specified depth. Returns `None` if this fails. - fn try_add_gate_at_depth(&mut self, g: &GateRef, depth: usize) -> Option<()> { - // If depth is 0, we have to insert the gate here. - if depth == 0 { - return if let Tree::Bifurcation(None, None) = self { - // Insert the gate as a new leaf. - *self = Tree::Leaf(g.clone()); - Some(()) - } else { - // A leaf is already here. - None - }; - } - - // A leaf is already here so we cannot go deeper. - if let Tree::Leaf(_) = self { - return None; - } - - if let Tree::Bifurcation(left, right) = self { - if let Some(left) = left { - // Try to add the gate to the left if there's already a left subtree. - if left.try_add_gate_at_depth(g, depth - 1).is_some() { - return Some(()); - } - } else { - // Add a new left subtree and try to add the gate to it. - let mut new_left = Tree::default(); - if new_left.try_add_gate_at_depth(g, depth - 1).is_some() { - *left = Some(Box::new(new_left)); - return Some(()); - } - } - if let Some(right) = right { - // Try to add the gate to the right if there's already a right subtree. - if right.try_add_gate_at_depth(g, depth - 1).is_some() { - return Some(()); - } - } else { - // Add a new right subtree and try to add the gate to it. - let mut new_right = Tree::default(); - if new_right.try_add_gate_at_depth(g, depth - 1).is_some() { - *right = Some(Box::new(new_right)); - return Some(()); - } - } - } - - None - } - - /// `Self::find_tree` returns a tree where each gate has `F(gate)=M` (see `Self::from_gates` comment). - /// This can produce subtrees with more nodes than necessary. This function removes useless nodes, - /// i.e., nodes that have a left but no right subtree. - fn shorten(&mut self) { - if let Tree::Bifurcation(left, right) = self { - if let (Some(left), None) = (left, right) { - // If the node has a left but no right subtree, set the node to its (shortened) left subtree. - let mut new = *left.clone(); - new.shorten(); - *self = new; - } - } - if let Tree::Bifurcation(left, right) = self { - if let Some(left) = left { - // Shorten the left subtree if there is one. - left.shorten(); - } - if let Some(right) = right { - // Shorten the right subtree if there is one. - right.shorten(); - } - } - } - - /// Returns the tree's maximum filtered constraint degree. - pub fn max_filtered_degree(&self) -> usize { - self.traversal() - .into_iter() - .map(|(g, p)| g.0.degree() + p.len()) - .max() - .expect("Empty tree.") - } - - /// Returns the number of constant wires needed to fit all prefixes and gate constants. - fn num_constants(&self) -> usize { - self.traversal() - .into_iter() - .map(|(g, p)| g.0.num_constants() + p.len()) - .max() - .expect("Empty tree.") - } -} - -#[cfg(test)] -mod tests { - use log::info; - - use super::*; - use crate::gadgets::interpolation::InterpolationGate; - use crate::gates::arithmetic_extension::ArithmeticExtensionGate; - use crate::gates::base_sum::BaseSumGate; - use crate::gates::constant::ConstantGate; - use crate::gates::interpolation::HighDegreeInterpolationGate; - use crate::gates::noop::NoopGate; - use crate::gates::poseidon::PoseidonGate; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - #[test] - fn test_prefix_generation() { - env_logger::init(); - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - - let gates = vec![ - GateRef::new(NoopGate), - GateRef::new(ConstantGate { num_consts: 4 }), - GateRef::new(ArithmeticExtensionGate { num_ops: 4 }), - GateRef::new(BaseSumGate::<4>::new(4)), - GateRef::new(PoseidonGate::::new()), - GateRef::new(HighDegreeInterpolationGate::new(2)), - ]; - - let (tree, _, _) = Tree::from_gates(gates.clone()); - let mut gates_with_prefix = tree.traversal(); - for (g, p) in &gates_with_prefix { - info!( - "\nGate: {}, prefix: {:?}.\n\ - Filtered constraint degree: {}, Num constant wires: {}", - &g.0.id()[..20.min(g.0.id().len())], - p, - g.0.degree() + p.len(), - g.0.num_constants() + p.len() - ); - } - - assert_eq!( - gates_with_prefix.len(), - gates.len(), - "The tree has too much or too little gates." - ); - assert!( - gates - .iter() - .all(|g| gates_with_prefix.iter().map(|(gg, _)| gg).any(|gg| gg == g)), - "Some gates are not in the tree." - ); - assert!( - gates_with_prefix - .iter() - .all(|(g, p)| g.0.degree() + g.0.num_constants() + p.len() <= 9), - "Total degree is larger than 8." - ); - - gates_with_prefix.sort_unstable_by_key(|(_g, p)| p.len()); - for i in 0..gates_with_prefix.len() { - for j in i + 1..gates_with_prefix.len() { - assert_ne!( - &gates_with_prefix[i].1, - &gates_with_prefix[j].1[0..gates_with_prefix[i].1.len()], - "Some gates share an overlapping prefix" - ); - } - } - } -} diff --git a/plonky2/src/gates/mod.rs b/plonky2/src/gates/mod.rs index 2450492f..7a08e709 100644 --- a/plonky2/src/gates/mod.rs +++ b/plonky2/src/gates/mod.rs @@ -11,7 +11,6 @@ pub mod comparison; pub mod constant; pub mod exponentiation; pub mod gate; -pub mod gate_tree; pub mod interpolation; pub mod low_degree_interpolation; pub mod multiplication_extension; diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index 52d32ab0..09701260 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -67,22 +67,22 @@ impl, const D: usize> Gate for MulExtensionGa constraints } - // fn eval_unfiltered_base_one( - // &self, - // vars: EvaluationVarsBase, - // mut yield_constr: StridedConstraintConsumer, - // ) { - // let const_0 = vars.get_constant(0); - // - // for i in 0..self.num_ops { - // let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i)); - // let multiplicand_1 = vars.get_local_ext(Self::wires_ith_multiplicand_1(i)); - // let output = vars.get_local_ext(Self::wires_ith_output(i)); - // let computed_output = (multiplicand_0 * multiplicand_1).scalar_mul(const_0); - // - // yield_constr.many((output - computed_output).to_basefield_array()); - // } - // } + fn eval_unfiltered_base_one( + &self, + vars: EvaluationVarsBase, + mut yield_constr: StridedConstraintConsumer, + ) { + let const_0 = vars.local_constants[0]; + + for i in 0..self.num_ops { + let multiplicand_0 = vars.get_local_ext(Self::wires_ith_multiplicand_0(i)); + let multiplicand_1 = vars.get_local_ext(Self::wires_ith_multiplicand_1(i)); + let output = vars.get_local_ext(Self::wires_ith_output(i)); + let computed_output = (multiplicand_0 * multiplicand_1).scalar_mul(const_0); + + yield_constr.many((output - computed_output).to_basefield_array()); + } + } fn eval_unfiltered_recursively( &self, diff --git a/plonky2/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs index e827cc9b..20fc59c8 100644 --- a/plonky2/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -36,17 +36,17 @@ impl, const D: usize> Gate for PublicInputGat .collect() } - // fn eval_unfiltered_base_one( - // &self, - // _vars: EvaluationVarsBase, - // _yield_constr: StridedConstraintConsumer, - // ) { - // panic!("use eval_unfiltered_base_packed instead"); - // } - // - // fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { - // self.eval_unfiltered_base_batch_packed(vars_base) - // } + fn eval_unfiltered_base_one( + &self, + _vars: EvaluationVarsBase, + _yield_constr: StridedConstraintConsumer, + ) { + panic!("use eval_unfiltered_base_packed instead"); + } + + fn eval_unfiltered_base_batch(&self, vars_base: EvaluationVarsBaseBatch) -> Vec { + self.eval_unfiltered_base_batch_packed(vars_base) + } fn eval_unfiltered_recursively( &self, diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 9d0145af..a014c2d4 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -5,7 +5,7 @@ use crate::gates::gate::{GateInstance, GateRef}; use crate::hash::hash_types::RichField; pub(crate) fn compute_selectors, const D: usize>( - mut gates: Vec>, + gates: Vec>, instances: &[GateInstance], max_degree: usize, ) -> ( @@ -21,13 +21,12 @@ pub(crate) fn compute_selectors, const D: usize>( while pos < gates.len() { let mut i = 0; - while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() + 1 <= max_degree) { + while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() < max_degree) { i += 1; } combinations.push((pos, pos + i)); pos += i; } - dbg!(&combinations); let bad = F::from_canonical_usize(u32::MAX as usize); let num_constants_polynomials = gates.iter().map(|g| g.0.num_constants()).max().unwrap(); diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index fd28f2ea..cd039da6 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -19,8 +19,7 @@ use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; use crate::gates::constant::ConstantGate; -use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef, PrefixedGate}; -use crate::gates::gate_tree::Tree; +use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef}; use crate::gates::noop::NoopGate; use crate::gates::public_input::PublicInputGate; use crate::gates::selectors::compute_selectors; @@ -45,22 +44,22 @@ use crate::util::context_tree::ContextTree; use crate::util::marking::{Markable, MarkedTargets}; use crate::util::partial_products::num_partial_products; use crate::util::timing::TimingTree; -use crate::util::{transpose, transpose_poly_values}; +use crate::util::transpose_poly_values; pub struct CircuitBuilder, const D: usize> { pub config: CircuitConfig, /// The types of gates used in this circuit. - pub(crate) gates: HashSet>, + gates: HashSet>, /// The concrete placement of each gate. pub(crate) gate_instances: Vec>, /// Targets to be made public. - pub(crate) public_inputs: Vec, + public_inputs: Vec, /// The next available index for a `VirtualTarget`. - pub(crate) virtual_target_index: usize, + virtual_target_index: usize, copy_constraints: Vec, @@ -68,10 +67,10 @@ pub struct CircuitBuilder, const D: usize> { context_log: ContextTree, /// A vector of marked targets. The values assigned to these targets will be displayed by the prover. - pub(crate) marked_targets: Vec>, + marked_targets: Vec>, /// Generators used to generate the witness. - pub(crate) generators: Vec>>, + generators: Vec>>, constants_to_targets: HashMap, targets_to_constants: HashMap, @@ -83,7 +82,7 @@ pub struct CircuitBuilder, const D: usize> { pub(crate) arithmetic_results: HashMap, ExtensionTarget>, /// Map between gate type and the current gate of this type with available slots. - pub(crate) current_slots: HashMap, CurrentSlot>, + current_slots: HashMap, CurrentSlot>, } impl, const D: usize> CircuitBuilder { @@ -424,7 +423,7 @@ impl, const D: usize> CircuitBuilder { (gate_idx, slot_idx) } - pub(crate) fn fri_params(&self, degree_bits: usize) -> FriParams { + fn fri_params(&self, degree_bits: usize) -> FriParams { self.config .fri_config .fri_params(degree_bits, self.config.zero_knowledge) @@ -493,7 +492,7 @@ impl, const D: usize> CircuitBuilder { } } - pub(crate) fn blind_and_pad(&mut self) { + fn blind_and_pad(&mut self) { if self.config.zero_knowledge { self.blind(); } @@ -552,39 +551,7 @@ impl, const D: usize> CircuitBuilder { } } - fn constant_polys( - &self, - gates: &[PrefixedGate], - num_constants: usize, - ) -> Vec> { - let constants_per_gate = self - .gate_instances - .iter() - .map(|gate| { - let prefix = &gates - .iter() - .find(|g| g.gate.0.id() == gate.gate_ref.0.id()) - .unwrap() - .prefix; - let mut prefixed_constants = Vec::with_capacity(num_constants); - prefixed_constants.extend(prefix.iter().map(|&b| if b { F::ONE } else { F::ZERO })); - prefixed_constants.extend_from_slice(&gate.constants); - prefixed_constants.resize(num_constants, F::ZERO); - prefixed_constants - }) - .collect::>(); - - transpose(&constants_per_gate) - .into_iter() - .map(PolynomialValues::new) - .collect() - } - - pub(crate) fn sigma_vecs( - &self, - k_is: &[F], - subgroup: &[F], - ) -> (Vec>, Forest) { + fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> (Vec>, Forest) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); let config = &self.config; @@ -682,29 +649,12 @@ impl, const D: usize> CircuitBuilder { &self.gate_instances, self.config.max_quotient_degree_factor + 1, ); - // dbg!(&constant_vecs, &selector_indices, &combination_ranges); let num_constants = constant_vecs.len(); - // let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates); - // let prefixed_gates = PrefixedGate::from_tree(gate_tree); - // - // // `quotient_degree_factor` has to be between `max_filtered_constraint_degree-1` and `1<(&config, 16_000)?; assert_eq!(cd.degree_bits, 14); - test_serialization(&proof, &cd)?; // Shrink it to 2^13. let (proof, vd, cd) = recursive_proof::(proof, vd, cd, &config, Some(13), false, false)?; assert_eq!(cd.degree_bits, 13); - test_serialization(&proof, &cd)?; // Shrink it to 2^12. let (proof, _vd, cd) = diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index ff578759..44e48843 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -3,7 +3,6 @@ use plonky2_field::extension_field::{Extendable, FieldExtension}; use plonky2_field::field_types::Field; use plonky2_field::zero_poly_coset::ZeroPolyOnCoset; -use crate::gates::gate::{Gate, GateRef, PrefixedGate}; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; @@ -127,7 +126,7 @@ pub(crate) fn eval_vanishing_poly_base_batch< let num_gate_constraints = common_data.num_gate_constraints; - let constraint_terms_batch = evaluate_gate_constraints_base_batch(&common_data, vars_batch); + let constraint_terms_batch = evaluate_gate_constraints_base_batch(common_data, vars_batch); debug_assert!(constraint_terms_batch.len() == n * num_gate_constraints); let num_challenges = common_data.config.num_challenges; @@ -250,7 +249,7 @@ pub fn evaluate_gate_constraints_base_batch< let mut constraints_batch = vec![F::ZERO; common_data.num_gate_constraints * vars_batch.len()]; for (i, gate) in common_data.gates.iter().enumerate() { let gate_constraints_batch = gate.0.eval_filtered_base_batch( - vars_batch.clone(), + vars_batch, i, common_data.selector_indices[i], common_data.combination_ranges[i], diff --git a/plonky2/src/plonk/vars.rs b/plonky2/src/plonk/vars.rs index 91529b15..8c7b71e3 100644 --- a/plonky2/src/plonk/vars.rs +++ b/plonky2/src/plonk/vars.rs @@ -21,7 +21,7 @@ pub struct EvaluationVars<'a, F: RichField + Extendable, const D: usize> { /// evaluation points, then wire 1 for all points, and so on). #[derive(Debug, Copy, Clone)] pub struct EvaluationVarsBaseBatch<'a, F: Field> { - pub(crate) batch_size: usize, + batch_size: usize, pub local_constants: &'a [F], pub local_wires: &'a [F], pub public_inputs_hash: &'a HashOut, From 847565a8c38e1d575cb34b941ad4293ab6825297 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 25 Mar 2022 07:52:39 +0100 Subject: [PATCH 12/16] Comments --- plonky2/src/gates/gate.rs | 49 ++++++++-------- plonky2/src/gates/selectors.rs | 83 ++++++++++++++-------------- plonky2/src/plonk/circuit_builder.rs | 50 ++++++++++++----- plonky2/src/plonk/circuit_data.rs | 6 +- plonky2/src/plonk/vanishing_poly.rs | 21 ++++--- 5 files changed, 114 insertions(+), 95 deletions(-) diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index bc56b2e2..f5de3472 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -7,6 +7,7 @@ use plonky2_field::batch_util::batch_multiply_inplace; use plonky2_field::extension_field::{Extendable, FieldExtension}; use plonky2_field::field_types::Field; +use crate::gates::selectors::UNUSED_SELECTOR; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; @@ -84,12 +85,12 @@ pub trait Gate, const D: usize>: 'static + Send + S mut vars: EvaluationVars, gate_index: usize, selector_index: usize, - combination_range: (usize, usize), + group_range: (usize, usize), num_selectors: usize, ) -> Vec { let filter = compute_filter( gate_index, - combination_range, + group_range, vars.local_constants[selector_index], ); vars.remove_prefix(num_selectors); @@ -106,7 +107,7 @@ pub trait Gate, const D: usize>: 'static + Send + S mut vars_batch: EvaluationVarsBaseBatch, gate_index: usize, selector_index: usize, - combination_range: (usize, usize), + group_range: (usize, usize), num_selectors: usize, ) -> Vec { let filters: Vec<_> = vars_batch @@ -114,7 +115,7 @@ pub trait Gate, const D: usize>: 'static + Send + S .map(|vars| { compute_filter( gate_index, - combination_range, + group_range, vars.local_constants[selector_index], ) }) @@ -134,14 +135,14 @@ pub trait Gate, const D: usize>: 'static + Send + S mut vars: EvaluationTargets, gate_index: usize, selector_index: usize, - combination_range: (usize, usize), - combined_gate_constraints: &mut [ExtensionTarget], + group_range: (usize, usize), num_selectors: usize, + combined_gate_constraints: &mut [ExtensionTarget], ) { let filter = compute_filter_recursively( builder, gate_index, - combination_range, + group_range, vars.local_constants[selector_index], ); vars.remove_prefix(num_selectors); @@ -229,34 +230,30 @@ pub struct PrefixedGate, const D: usize> { pub prefix: Vec, } -/// A gate's filter is computed as `prod b_i*c_i + (1-b_i)*(1-c_i)`, with `(b_i)` the prefix and -/// `(c_i)` the local constants, which is one if the prefix of `constants` matches `prefix`. -fn compute_filter( - gate_index: usize, - combination_range: (usize, usize), - constant: K, -) -> K { - (combination_range.0..combination_range.1) +/// A gate's filter designed so that it is non-zero if `s = gate_index`. +fn compute_filter(gate_index: usize, group_range: (usize, usize), s: K) -> K { + debug_assert!((group_range.0 <= gate_index) && (gate_index < group_range.1)); + (group_range.0..group_range.1) .filter(|&i| i != gate_index) - .chain(Some(u32::MAX as usize)) - .map(|i| K::from_canonical_usize(i) - constant) + .chain(Some(UNUSED_SELECTOR)) + .map(|i| K::from_canonical_usize(i) - s) .product() } fn compute_filter_recursively, const D: usize>( builder: &mut CircuitBuilder, gate_index: usize, - combination_range: (usize, usize), - constant: ExtensionTarget, + group_range: (usize, usize), + s: ExtensionTarget, ) -> ExtensionTarget { - let v = (combination_range.0..combination_range.1) + debug_assert!((group_range.0 <= gate_index) && (gate_index < group_range.1)); + let v = (group_range.0..group_range.1) .filter(|&i| i != gate_index) - .chain(Some(u32::MAX as usize)) - .map(|i| builder.constant_extension(F::Extension::from_canonical_usize(i))) - .collect::>(); - let v = v - .into_iter() - .map(|x| builder.sub_extension(x, constant)) + .chain(Some(UNUSED_SELECTOR)) + .map(|i| { + let c = builder.constant_extension(F::Extension::from_canonical_usize(i)); + builder.sub_extension(c, s) + }) .collect::>(); builder.mul_many_extension(&v) } diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index a014c2d4..ed251237 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -4,74 +4,73 @@ use plonky2_field::polynomial::PolynomialValues; use crate::gates::gate::{GateInstance, GateRef}; use crate::hash::hash_types::RichField; -pub(crate) fn compute_selectors, const D: usize>( +/// Placeholder value to indicate that a gate doesn't use a selector polynomial. +pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize; + +#[derive(Debug, Clone)] +pub(crate) struct SelectorsInfo { + pub(crate) selector_indices: Vec, + pub(crate) groups: Vec<(usize, usize)>, + pub(crate) num_selectors: usize, +} + +/// Returns the selector polynomials and related information. +/// +/// Selector polynomials are computed as follows: +/// Partition the gates into (the smallest amount of) groups `{ G_i }`, such that for each group `G` +/// `|G| + max_{g in G} g.degree() <= max_degree`. These groups are constructed greedily from +/// the list of gates sorted by degree. +pub(crate) fn selector_polynomials, const D: usize>( gates: Vec>, instances: &[GateInstance], max_degree: usize, -) -> ( - Vec>, - Vec, - Vec<(usize, usize)>, - usize, -) { +) -> (Vec>, SelectorsInfo) { let n = instances.len(); - let mut combinations = Vec::new(); + // Greedily construct the groups. + let mut groups = Vec::new(); let mut pos = 0; - while pos < gates.len() { let mut i = 0; while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() < max_degree) { i += 1; } - combinations.push((pos, pos + i)); + groups.push((pos, pos + i)); pos += i; } - let bad = F::from_canonical_usize(u32::MAX as usize); - - let num_constants_polynomials = gates.iter().map(|g| g.0.num_constants()).max().unwrap(); - let mut polynomials = - vec![PolynomialValues::zero(n); combinations.len() + num_constants_polynomials]; let index = |id| gates.iter().position(|g| g.0.id() == id).unwrap(); - let combination = |i| { - combinations - .iter() - .position(|&(a, b)| a <= i && i < b) - .unwrap() - }; + let group = |i| groups.iter().position(|&(a, b)| a <= i && i < b).unwrap(); + // `selector_indices[i] = j` iff the `i`-th gate uses the `j`-th selector polynomial. let selector_indices = gates .iter() - .map(|g| combination(index(g.0.id()))) + .map(|g| group(index(g.0.id()))) .collect::>(); - let combination_ranges = selector_indices - .iter() - .map(|&i| (combinations[i].0, combinations[i].1)) - .collect(); + // Placeholder value to indicate that a gate doesn't use a selector polynomial. + let unused = F::from_canonical_usize(UNUSED_SELECTOR); + + let mut polynomials = vec![PolynomialValues::zero(n); groups.len()]; for (j, g) in instances.iter().enumerate() { - let GateInstance { - gate_ref, - constants, - } = g; + let GateInstance { gate_ref, .. } = g; let i = index(gate_ref.0.id()); - let comb = combination(i); - polynomials[comb].values[j] = F::from_canonical_usize(i); - - for combis in (0..combinations.len()).filter(|&combis| combis != comb) { - polynomials[combis].values[j] = bad; - } - - for k in 0..constants.len() { - polynomials[combinations.len() + k].values[j] = constants[k]; + let gr = group(i); + for g in 0..groups.len() { + polynomials[g].values[j] = if g == gr { + F::from_canonical_usize(i) + } else { + unused + }; } } ( polynomials, - selector_indices, - combination_ranges, - combinations.len(), + SelectorsInfo { + selector_indices, + num_selectors: groups.len(), + groups, + }, ) } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index cd039da6..7fbc67f4 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -22,7 +22,7 @@ use crate::gates::constant::ConstantGate; use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef}; use crate::gates::noop::NoopGate; use crate::gates::public_input::PublicInputGate; -use crate::gates::selectors::compute_selectors; +use crate::gates::selectors::selector_polynomials; use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; use crate::hash::merkle_proofs::MerkleProofTarget; use crate::iop::ext_target::ExtensionTarget; @@ -44,7 +44,7 @@ use crate::util::context_tree::ContextTree; use crate::util::marking::{Markable, MarkedTargets}; use crate::util::partial_products::num_partial_products; use crate::util::timing::TimingTree; -use crate::util::transpose_poly_values; +use crate::util::{transpose, transpose_poly_values}; pub struct CircuitBuilder, const D: usize> { pub config: CircuitConfig, @@ -551,6 +551,29 @@ impl, const D: usize> CircuitBuilder { } } + fn constant_polys(&self) -> Vec> { + let max_constants = self + .gates + .iter() + .map(|g| g.0.num_constants()) + .max() + .unwrap(); + transpose( + &self + .gate_instances + .iter() + .map(|g| { + let mut consts = g.constants.clone(); + consts.resize(max_constants, F::ZERO); + consts + }) + .collect::>(), + ) + .into_iter() + .map(PolynomialValues::new) + .collect() + } + fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> (Vec>, Forest) { let degree = self.gate_instances.len(); let degree_log = log2_strict(degree); @@ -641,17 +664,16 @@ impl, const D: usize> CircuitBuilder { "FRI total reduction arity is too large.", ); - let mut gates = self.gates.iter().cloned().collect::>(); - gates.sort_unstable_by_key(|g| g.0.degree()); - let (constant_vecs, selector_indices, combination_ranges, num_selectors) = - compute_selectors( - gates.clone(), - &self.gate_instances, - self.config.max_quotient_degree_factor + 1, - ); - let num_constants = constant_vecs.len(); let quotient_degree_factor = self.config.max_quotient_degree_factor; - debug!("Quotient degree factor set to: {}.", quotient_degree_factor); + let mut gates = self.gates.iter().cloned().collect::>(); + gates.sort_unstable_by_key(|g| (g.0.degree(), g.0.id())); + let (mut constant_vecs, selectors_info) = selector_polynomials( + gates.clone(), + &self.gate_instances, + quotient_degree_factor + 1, + ); + constant_vecs.extend(self.constant_polys()); + let num_constants = constant_vecs.len(); let subgroup = F::two_adic_subgroup(degree_bits); @@ -754,9 +776,7 @@ impl, const D: usize> CircuitBuilder { fri_params, degree_bits, gates, - selector_indices, - combination_ranges, - num_selectors, + selectors_info, quotient_degree_factor, num_gate_constraints, num_constants, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index f67024e3..8c33ae98 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -13,6 +13,7 @@ use crate::fri::structure::{ }; use crate::fri::{FriConfig, FriParams}; use crate::gates::gate::GateRef; +use crate::gates::selectors::SelectorsInfo; use crate::hash::hash_types::{MerkleCapTarget, RichField}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::ext_target::ExtensionTarget; @@ -248,9 +249,8 @@ pub struct CommonCircuitData< /// The types of gates used in this circuit, along with their prefixes. pub(crate) gates: Vec>, - pub(crate) selector_indices: Vec, - pub(crate) combination_ranges: Vec<(usize, usize)>, - pub(crate) num_selectors: usize, + /// Information on the circuit's selector polynomials. + pub(crate) selectors_info: SelectorsInfo, /// The degree of the PLONK quotient polynomial. pub(crate) quotient_degree_factor: usize, diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 44e48843..4ee797a5 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -215,12 +215,13 @@ pub fn evaluate_gate_constraints< ) -> Vec { let mut constraints = vec![F::Extension::ZERO; common_data.num_gate_constraints]; for (i, gate) in common_data.gates.iter().enumerate() { + let selector_index = common_data.selectors_info.selector_indices[i]; let gate_constraints = gate.0.eval_filtered( vars, i, - common_data.selector_indices[i], - common_data.combination_ranges[i], - common_data.num_selectors, + selector_index, + common_data.selectors_info.groups[selector_index], + common_data.selectors_info.num_selectors, ); for (i, c) in gate_constraints.into_iter().enumerate() { debug_assert!( @@ -248,12 +249,13 @@ pub fn evaluate_gate_constraints_base_batch< ) -> Vec { let mut constraints_batch = vec![F::ZERO; common_data.num_gate_constraints * vars_batch.len()]; for (i, gate) in common_data.gates.iter().enumerate() { + let selector_index = common_data.selectors_info.selector_indices[i]; let gate_constraints_batch = gate.0.eval_filtered_base_batch( vars_batch, i, - common_data.selector_indices[i], - common_data.combination_ranges[i], - common_data.num_selectors, + selector_index, + common_data.selectors_info.groups[selector_index], + common_data.selectors_info.num_selectors, ); debug_assert!( gate_constraints_batch.len() <= constraints_batch.len(), @@ -279,6 +281,7 @@ pub fn evaluate_gate_constraints_recursively< ) -> Vec> { let mut all_gate_constraints = vec![builder.zero_extension(); common_data.num_gate_constraints]; for (i, gate) in common_data.gates.iter().enumerate() { + let selector_index = common_data.selectors_info.selector_indices[i]; with_context!( builder, &format!("evaluate {} constraints", gate.0.id()), @@ -286,10 +289,10 @@ pub fn evaluate_gate_constraints_recursively< builder, vars, i, - common_data.selector_indices[i], - common_data.combination_ranges[i], + selector_index, + common_data.selectors_info.groups[selector_index], + common_data.selectors_info.num_selectors, &mut all_gate_constraints, - common_data.num_selectors ) ); } From 19cbbd4d12667da75047913dda43416bd2a8e20c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 25 Mar 2022 08:01:22 +0100 Subject: [PATCH 13/16] Minor --- plonky2/src/gates/selectors.rs | 10 +++++++++- plonky2/src/plonk/circuit_builder.rs | 7 ++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index ed251237..a5d15f87 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -20,8 +20,16 @@ pub(crate) struct SelectorsInfo { /// Partition the gates into (the smallest amount of) groups `{ G_i }`, such that for each group `G` /// `|G| + max_{g in G} g.degree() <= max_degree`. These groups are constructed greedily from /// the list of gates sorted by degree. +/// We build a selector polynomial `S_i` for each group `G_i`, with +/// ``` +/// S_i[j] = +/// if j-th row gate=g_k in G_i +/// k +/// else +/// UNUSED_SELECTOR +/// ``` pub(crate) fn selector_polynomials, const D: usize>( - gates: Vec>, + gates: &[GateRef], instances: &[GateInstance], max_degree: usize, ) -> (Vec>, SelectorsInfo) { diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 7fbc67f4..12180600 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -667,11 +667,8 @@ impl, const D: usize> CircuitBuilder { let quotient_degree_factor = self.config.max_quotient_degree_factor; let mut gates = self.gates.iter().cloned().collect::>(); gates.sort_unstable_by_key(|g| (g.0.degree(), g.0.id())); - let (mut constant_vecs, selectors_info) = selector_polynomials( - gates.clone(), - &self.gate_instances, - quotient_degree_factor + 1, - ); + let (mut constant_vecs, selectors_info) = + selector_polynomials(&gates, &self.gate_instances, quotient_degree_factor + 1); constant_vecs.extend(self.constant_polys()); let num_constants = constant_vecs.len(); From 283c9350a74e45496927905034be01e9fe880f9e Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 25 Mar 2022 08:24:32 +0100 Subject: [PATCH 14/16] No doc-test --- plonky2/src/gates/selectors.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index a5d15f87..f51bc8cb 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -21,13 +21,11 @@ pub(crate) struct SelectorsInfo { /// `|G| + max_{g in G} g.degree() <= max_degree`. These groups are constructed greedily from /// the list of gates sorted by degree. /// We build a selector polynomial `S_i` for each group `G_i`, with -/// ``` /// S_i[j] = /// if j-th row gate=g_k in G_i /// k /// else /// UNUSED_SELECTOR -/// ``` pub(crate) fn selector_polynomials, const D: usize>( gates: &[GateRef], instances: &[GateInstance], From e50e668f7eec399078a3f423f7dfc7b36f00a3fd Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 28 Mar 2022 10:15:06 +0200 Subject: [PATCH 15/16] PR feedback + use only one selector when possible --- plonky2/src/gates/gate.rs | 34 +++++++++++------- plonky2/src/gates/selectors.rs | 54 ++++++++++++++++++++-------- plonky2/src/plonk/circuit_builder.rs | 1 + plonky2/src/plonk/vanishing_poly.rs | 6 ++-- 4 files changed, 66 insertions(+), 29 deletions(-) diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index f5de3472..e95ec0f8 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::fmt::{Debug, Error, Formatter}; use std::hash::{Hash, Hasher}; +use std::ops::Range; use std::sync::Arc; use plonky2_field::batch_util::batch_multiply_inplace; @@ -85,13 +86,14 @@ pub trait Gate, const D: usize>: 'static + Send + S mut vars: EvaluationVars, gate_index: usize, selector_index: usize, - group_range: (usize, usize), + group_range: Range, num_selectors: usize, ) -> Vec { let filter = compute_filter( gate_index, group_range, vars.local_constants[selector_index], + num_selectors > 1, ); vars.remove_prefix(num_selectors); self.eval_unfiltered(vars) @@ -107,7 +109,7 @@ pub trait Gate, const D: usize>: 'static + Send + S mut vars_batch: EvaluationVarsBaseBatch, gate_index: usize, selector_index: usize, - group_range: (usize, usize), + group_range: Range, num_selectors: usize, ) -> Vec { let filters: Vec<_> = vars_batch @@ -115,8 +117,9 @@ pub trait Gate, const D: usize>: 'static + Send + S .map(|vars| { compute_filter( gate_index, - group_range, + group_range.clone(), vars.local_constants[selector_index], + num_selectors > 1, ) }) .collect(); @@ -135,7 +138,7 @@ pub trait Gate, const D: usize>: 'static + Send + S mut vars: EvaluationTargets, gate_index: usize, selector_index: usize, - group_range: (usize, usize), + group_range: Range, num_selectors: usize, combined_gate_constraints: &mut [ExtensionTarget], ) { @@ -144,6 +147,7 @@ pub trait Gate, const D: usize>: 'static + Send + S gate_index, group_range, vars.local_constants[selector_index], + num_selectors > 1, ); vars.remove_prefix(num_selectors); let my_constraints = self.eval_unfiltered_recursively(builder, vars); @@ -231,11 +235,16 @@ pub struct PrefixedGate, const D: usize> { } /// A gate's filter designed so that it is non-zero if `s = gate_index`. -fn compute_filter(gate_index: usize, group_range: (usize, usize), s: K) -> K { - debug_assert!((group_range.0 <= gate_index) && (gate_index < group_range.1)); - (group_range.0..group_range.1) +fn compute_filter( + gate_index: usize, + group_range: Range, + s: K, + many_selector: bool, +) -> K { + debug_assert!(group_range.contains(&gate_index)); + group_range .filter(|&i| i != gate_index) - .chain(Some(UNUSED_SELECTOR)) + .chain(many_selector.then(|| UNUSED_SELECTOR)) .map(|i| K::from_canonical_usize(i) - s) .product() } @@ -243,13 +252,14 @@ fn compute_filter(gate_index: usize, group_range: (usize, usize), s: K fn compute_filter_recursively, const D: usize>( builder: &mut CircuitBuilder, gate_index: usize, - group_range: (usize, usize), + group_range: Range, s: ExtensionTarget, + many_selectors: bool, ) -> ExtensionTarget { - debug_assert!((group_range.0 <= gate_index) && (gate_index < group_range.1)); - let v = (group_range.0..group_range.1) + debug_assert!(group_range.contains(&gate_index)); + let v = group_range .filter(|&i| i != gate_index) - .chain(Some(UNUSED_SELECTOR)) + .chain(many_selectors.then(|| UNUSED_SELECTOR)) .map(|i| { let c = builder.constant_extension(F::Extension::from_canonical_usize(i)); builder.sub_extension(c, s) diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index f51bc8cb..559dcf48 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -1,3 +1,5 @@ +use std::ops::Range; + use plonky2_field::extension_field::Extendable; use plonky2_field::polynomial::PolynomialValues; @@ -10,7 +12,7 @@ pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize; #[derive(Debug, Clone)] pub(crate) struct SelectorsInfo { pub(crate) selector_indices: Vec, - pub(crate) groups: Vec<(usize, usize)>, + pub(crate) groups: Vec>, pub(crate) num_selectors: usize, } @@ -32,27 +34,51 @@ pub(crate) fn selector_polynomials, const D: usize> max_degree: usize, ) -> (Vec>, SelectorsInfo) { let n = instances.len(); + let num_gates = gates.len(); + let max_gate_degree = gates.last().expect("No gates?").0.degree(); + + let index = |id| gates.iter().position(|g| g.0.id() == id).unwrap(); + + // Special case if we can use only one selector polynomial. + if max_gate_degree + num_gates - 1 <= max_degree { + return ( + vec![PolynomialValues::new( + instances + .iter() + .map(|g| F::from_canonical_usize(index(g.gate_ref.0.id()))) + .collect(), + )], + SelectorsInfo { + selector_indices: vec![0; num_gates], + groups: vec![0..num_gates], + num_selectors: 1, + }, + ); + } + + if max_gate_degree >= max_degree { + panic!( + "{} has too high degree. Consider increasing `quotient_degree_factor`.", + gates.last().unwrap().0.id() + ); + } // Greedily construct the groups. let mut groups = Vec::new(); - let mut pos = 0; - while pos < gates.len() { - let mut i = 0; - while (pos + i < gates.len()) && (i + gates[pos + i].0.degree() < max_degree) { - i += 1; + let mut start = 0; + while start < num_gates { + let mut size = 0; + while (start + size < gates.len()) && (size + gates[start + size].0.degree() < max_degree) { + size += 1; } - groups.push((pos, pos + i)); - pos += i; + groups.push(start..start + size); + start += size; } - let index = |id| gates.iter().position(|g| g.0.id() == id).unwrap(); - let group = |i| groups.iter().position(|&(a, b)| a <= i && i < b).unwrap(); + let group = |i| groups.iter().position(|range| range.contains(&i)).unwrap(); // `selector_indices[i] = j` iff the `i`-th gate uses the `j`-th selector polynomial. - let selector_indices = gates - .iter() - .map(|g| group(index(g.0.id()))) - .collect::>(); + let selector_indices = (0..num_gates).map(group).collect(); // Placeholder value to indicate that a gate doesn't use a selector polynomial. let unused = F::from_canonical_usize(UNUSED_SELECTOR); diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 12180600..022e2b12 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -666,6 +666,7 @@ impl, const D: usize> CircuitBuilder { let quotient_degree_factor = self.config.max_quotient_degree_factor; let mut gates = self.gates.iter().cloned().collect::>(); + // Gates need to be sorted by their degrees to compute the selector polynomials. gates.sort_unstable_by_key(|g| (g.0.degree(), g.0.id())); let (mut constant_vecs, selectors_info) = selector_polynomials(&gates, &self.gate_instances, quotient_degree_factor + 1); diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 4ee797a5..54a5fe98 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -220,7 +220,7 @@ pub fn evaluate_gate_constraints< vars, i, selector_index, - common_data.selectors_info.groups[selector_index], + common_data.selectors_info.groups[selector_index].clone(), common_data.selectors_info.num_selectors, ); for (i, c) in gate_constraints.into_iter().enumerate() { @@ -254,7 +254,7 @@ pub fn evaluate_gate_constraints_base_batch< vars_batch, i, selector_index, - common_data.selectors_info.groups[selector_index], + common_data.selectors_info.groups[selector_index].clone(), common_data.selectors_info.num_selectors, ); debug_assert!( @@ -290,7 +290,7 @@ pub fn evaluate_gate_constraints_recursively< vars, i, selector_index, - common_data.selectors_info.groups[selector_index], + common_data.selectors_info.groups[selector_index].clone(), common_data.selectors_info.num_selectors, &mut all_gate_constraints, ) From 604715240f9cc8cde31af4d14173c63ee8aedb19 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 31 Mar 2022 08:51:28 +0200 Subject: [PATCH 16/16] PR feedback: num_selectors as fn and sorting comment --- plonky2/src/gates/selectors.rs | 9 ++++++--- plonky2/src/plonk/circuit_builder.rs | 2 +- plonky2/src/plonk/vanishing_poly.rs | 6 +++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 559dcf48..dffeb987 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -13,7 +13,12 @@ pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize; pub(crate) struct SelectorsInfo { pub(crate) selector_indices: Vec, pub(crate) groups: Vec>, - pub(crate) num_selectors: usize, +} + +impl SelectorsInfo { + pub fn num_selectors(&self) -> usize { + self.groups.len() + } } /// Returns the selector polynomials and related information. @@ -51,7 +56,6 @@ pub(crate) fn selector_polynomials, const D: usize> SelectorsInfo { selector_indices: vec![0; num_gates], groups: vec![0..num_gates], - num_selectors: 1, }, ); } @@ -101,7 +105,6 @@ pub(crate) fn selector_polynomials, const D: usize> polynomials, SelectorsInfo { selector_indices, - num_selectors: groups.len(), groups, }, ) diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 022e2b12..924ca553 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -666,7 +666,7 @@ impl, const D: usize> CircuitBuilder { let quotient_degree_factor = self.config.max_quotient_degree_factor; let mut gates = self.gates.iter().cloned().collect::>(); - // Gates need to be sorted by their degrees to compute the selector polynomials. + // Gates need to be sorted by their degrees (and ID to make the ordering deterministic) to compute the selector polynomials. gates.sort_unstable_by_key(|g| (g.0.degree(), g.0.id())); let (mut constant_vecs, selectors_info) = selector_polynomials(&gates, &self.gate_instances, quotient_degree_factor + 1); diff --git a/plonky2/src/plonk/vanishing_poly.rs b/plonky2/src/plonk/vanishing_poly.rs index 54a5fe98..ab23aa45 100644 --- a/plonky2/src/plonk/vanishing_poly.rs +++ b/plonky2/src/plonk/vanishing_poly.rs @@ -221,7 +221,7 @@ pub fn evaluate_gate_constraints< i, selector_index, common_data.selectors_info.groups[selector_index].clone(), - common_data.selectors_info.num_selectors, + common_data.selectors_info.num_selectors(), ); for (i, c) in gate_constraints.into_iter().enumerate() { debug_assert!( @@ -255,7 +255,7 @@ pub fn evaluate_gate_constraints_base_batch< i, selector_index, common_data.selectors_info.groups[selector_index].clone(), - common_data.selectors_info.num_selectors, + common_data.selectors_info.num_selectors(), ); debug_assert!( gate_constraints_batch.len() <= constraints_batch.len(), @@ -291,7 +291,7 @@ pub fn evaluate_gate_constraints_recursively< i, selector_index, common_data.selectors_info.groups[selector_index].clone(), - common_data.selectors_info.num_selectors, + common_data.selectors_info.num_selectors(), &mut all_gate_constraints, ) );