From 21669be2463a77bcaf5e23bd40cafa1cca5250fc Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 10:40:31 +0200 Subject: [PATCH 01/17] Some arithm optims --- src/fri/recursive_verifier.rs | 49 +++++++++++++++++++++++---------- src/gadgets/interpolation.rs | 5 ++-- src/gates/arithmetic.rs | 8 +++--- src/plonk/copy_constraint.rs | 1 + src/plonk/prover.rs | 20 ++++++++++++++ src/plonk/recursive_verifier.rs | 8 +++--- src/util/reducing.rs | 18 ++++++++++-- 7 files changed, 83 insertions(+), 26 deletions(-) diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index 1e028255..cf07dfad 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -139,7 +139,13 @@ impl, const D: usize> CircuitBuilder { let precomputed_reduced_evals = with_context!( self, "precompute reduced evaluations", - PrecomputedReducedEvalsTarget::from_os_and_alpha(os, alpha, self) + PrecomputedReducedEvalsTarget::from_os_and_alpha( + os, + alpha, + common_data.degree_bits, + zeta, + self + ) ); for (i, round_proof) in proof.query_round_proofs.iter().enumerate() { @@ -209,6 +215,7 @@ impl, const D: usize> CircuitBuilder { precomputed_reduced_evals: PrecomputedReducedEvalsTarget, common_data: &CommonCircuitData, ) -> ExtensionTarget { + println!("combine initial: {}", self.num_gates()); assert!(D > 1, "Not implemented for D=1."); let config = self.config.clone(); let degree_log = common_data.degree_bits; @@ -246,6 +253,7 @@ impl, const D: usize> CircuitBuilder { sum = self.div_add_extension(single_numerator, vanish_zeta, sum); alpha.reset(); + println!("done single: {}", self.num_gates()); // Polynomials opened at `x` and `g x`, i.e., the Zs polynomials. let zs_evals = proof .unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge) @@ -255,20 +263,21 @@ impl, const D: usize> CircuitBuilder { .collect::>(); let zs_composition_eval = alpha.reduce_base(&zs_evals, self); - let g = self.constant_extension(F::Extension::primitive_root_of_unity(degree_log)); - let zeta_right = self.mul_extension(g, zeta); - let interpol_val = self.interpolate2( - [ - (zeta, precomputed_reduced_evals.zs), - (zeta_right, precomputed_reduced_evals.zs_right), - ], - subgroup_x, + let interpol_val = self.mul_add_extension( + vanish_zeta, + precomputed_reduced_evals.slope, + precomputed_reduced_evals.zs, ); - let (zs_numerator, vanish_zeta_right) = - self.sub_two_extension(zs_composition_eval, interpol_val, subgroup_x, zeta_right); - let zs_denominator = self.mul_extension(vanish_zeta, vanish_zeta_right); - sum = alpha.shift(sum, self); + let (zs_numerator, vanish_zeta_right) = self.sub_two_extension( + zs_composition_eval, + interpol_val, + subgroup_x, + precomputed_reduced_evals.zeta_right, + ); + let (mut sum, zs_denominator) = + alpha.shift_and_mul(sum, vanish_zeta, vanish_zeta_right, self); sum = self.div_add_extension(zs_numerator, zs_denominator, sum); + println!("done doubles: {}", self.num_gates()); sum } @@ -286,6 +295,7 @@ impl, const D: usize> CircuitBuilder { round_proof: &FriQueryRoundTarget, common_data: &CommonCircuitData, ) { + println!("query round: {}", self.num_gates()); let config = &common_data.config.fri_config; let n_log = log2_strict(n); // TODO: Do we need to range check `x_index` to a target smaller than `p`? @@ -308,7 +318,7 @@ impl, const D: usize> CircuitBuilder { // `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain. let mut subgroup_x = with_context!(self, "compute x from its index", { - let g = self.constant(F::MULTIPLICATIVE_GROUP_GENERATOR); + let g = self.constant(F::coset_shift()); let phi = self.constant(F::primitive_root_of_unity(n_log)); let phi = self.exp_from_bits(phi, x_index_bits.iter().rev()); @@ -331,6 +341,7 @@ impl, const D: usize> CircuitBuilder { ); for (i, &arity_bits) in config.reduction_arity_bits.iter().enumerate() { + println!("query round, {}-th arity: {}", i, self.num_gates()); let evals = &round_proof.steps[i].evals; // Split x_index into the index of the coset x is in, and the index of x within that coset. @@ -393,12 +404,16 @@ struct PrecomputedReducedEvalsTarget { pub single: ExtensionTarget, pub zs: ExtensionTarget, pub zs_right: ExtensionTarget, + pub slope: ExtensionTarget, + pub zeta_right: ExtensionTarget, } impl PrecomputedReducedEvalsTarget { fn from_os_and_alpha>( os: &OpeningSetTarget, alpha: ExtensionTarget, + degree_log: usize, + zeta: ExtensionTarget, builder: &mut CircuitBuilder, ) -> Self { let mut alpha = ReducingFactorTarget::new(alpha); @@ -416,10 +431,16 @@ impl PrecomputedReducedEvalsTarget { let zs = alpha.reduce(&os.plonk_zs, builder); let zs_right = alpha.reduce(&os.plonk_zs_right, builder); + let g = builder.constant_extension(F::Extension::primitive_root_of_unity(degree_log)); + let zeta_right = builder.mul_extension(g, zeta); + let (numerator, denominator) = builder.sub_two_extension(zs_right, zs, zeta_right, zeta); + Self { single, zs, zs_right, + slope: builder.div_extension(numerator, denominator), + zeta_right, } } } diff --git a/src/gadgets/interpolation.rs b/src/gadgets/interpolation.rs index 92090d90..dd8a1334 100644 --- a/src/gadgets/interpolation.rs +++ b/src/gadgets/interpolation.rs @@ -12,9 +12,10 @@ impl, const D: usize> CircuitBuilder { interpolation_points: [(ExtensionTarget, ExtensionTarget); 2], evaluation_point: ExtensionTarget, ) -> ExtensionTarget { - // a0 -> a1 - // b0 -> b1 + // a0 -> a1 : zeta -> precomp0 + // b0 -> b1 : g*zeta -> precomp1 // x -> a1 + (x-a0)*(b1-a1)/(b0-a0) + // x -> precomp0 + (x-zeta)*(precomp1-precomp0)/(g*zeta - zeta) let (x_m_a0, b1_m_a1) = self.sub_two_extension( evaluation_point, diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 499bd4a7..81c9bc9a 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -24,16 +24,16 @@ impl ArithmeticExtensionGate { pub fn wires_first_addend() -> Range { 2 * D..3 * D } - pub fn wires_second_multiplicand_0() -> Range { + pub fn wires_first_output() -> Range { 3 * D..4 * D } - pub fn wires_second_multiplicand_1() -> Range { + pub fn wires_second_multiplicand_0() -> Range { 4 * D..5 * D } - pub fn wires_second_addend() -> Range { + pub fn wires_second_multiplicand_1() -> Range { 5 * D..6 * D } - pub fn wires_first_output() -> Range { + pub fn wires_second_addend() -> Range { 6 * D..7 * D } pub fn wires_second_output() -> Range { diff --git a/src/plonk/copy_constraint.rs b/src/plonk/copy_constraint.rs index a838ed37..a04fc75b 100644 --- a/src/plonk/copy_constraint.rs +++ b/src/plonk/copy_constraint.rs @@ -1,6 +1,7 @@ use crate::iop::target::Target; /// A named copy constraint. +#[derive(Debug)] pub struct CopyConstraint { pub pair: (Target, Target), pub name: String, diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 0d66daa8..026fc4b7 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -68,6 +68,26 @@ pub(crate) fn prove, const D: usize>( partial_witness.full_witness(degree, num_wires) ); + { + let mut count = 0; + let mut count_bad = 0; + for i in 0..degree { + if prover_data.gate_instances[i].gate_ref.0.id() + != "ArithmeticExtensionGate".to_string() + { + continue; + } + count += 1; + let row = witness.wire_values.iter().map(|c| c[i]).collect::>(); + // println!("{} {:?}", i, &row); + if row[16..].iter().all(|x| x.is_zero()) { + println!("{} {:?}", i, row); + count_bad += 1; + } + } + println!("{} {}", count, count_bad); + } + let wires_values: Vec> = timed!( timing, "compute wire polynomials", diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 3ab1cdec..369fbcb1 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -426,7 +426,7 @@ mod tests { const D: usize = 4; let config = CircuitConfig { num_wires: 126, - num_routed_wires: 37, + num_routed_wires: 64, security_bits: 128, rate_bits: 3, num_challenges: 3, @@ -434,7 +434,7 @@ mod tests { cap_height: 3, fri_config: FriConfig { proof_of_work_bits: 1, - reduction_arity_bits: vec![2, 2, 2, 2, 2, 2], + reduction_arity_bits: vec![3, 3, 3], num_query_rounds: 40, cap_height: 3, }, @@ -443,9 +443,9 @@ mod tests { let (proof_with_pis, vd, cd) = { let mut builder = CircuitBuilder::::new(config.clone()); let _two = builder.two(); - let _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; + let mut _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; for _ in 0..10000 { - let _two = builder.mul(_two, _two); + _two = builder.mul(_two, _two); } let data = builder.build(); ( diff --git a/src/util/reducing.rs b/src/util/reducing.rs index ce6827ba..8e8fa661 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -211,9 +211,23 @@ impl ReducingFactorTarget { F: Extendable, { let exp = builder.exp_u64_extension(self.base, self.count); - let tmp = builder.mul_extension(exp, x); self.count = 0; - tmp + builder.mul_extension(exp, x) + } + + pub fn shift_and_mul( + &mut self, + x: ExtensionTarget, + a: ExtensionTarget, + b: ExtensionTarget, + builder: &mut CircuitBuilder, + ) -> (ExtensionTarget, ExtensionTarget) + where + F: Extendable, + { + let exp = builder.exp_u64_extension(self.base, self.count); + self.count = 0; + builder.mul_two_extension(exp, x, a, b) } pub fn reset(&mut self) { From 71c392e935b065b5309f5f1c02e2dcde852cbf5f Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 10:46:51 +0200 Subject: [PATCH 02/17] More optim --- src/fri/recursive_verifier.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index cf07dfad..d8f6b0ef 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -210,8 +210,8 @@ impl, const D: usize> CircuitBuilder { &mut self, proof: &FriInitialTreeProofTarget, alpha: ExtensionTarget, - zeta: ExtensionTarget, subgroup_x: Target, + vanish_zeta: ExtensionTarget, precomputed_reduced_evals: PrecomputedReducedEvalsTarget, common_data: &CommonCircuitData, ) -> ExtensionTarget { @@ -225,7 +225,6 @@ impl, const D: usize> CircuitBuilder { - config.rate_bits ); let subgroup_x = self.convert_to_ext(subgroup_x); - let vanish_zeta = self.sub_extension(subgroup_x, zeta); let mut alpha = ReducingFactorTarget::new(alpha); let mut sum = self.zero_extension(); @@ -317,12 +316,25 @@ impl, const D: usize> CircuitBuilder { ); // `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain. - let mut subgroup_x = with_context!(self, "compute x from its index", { + let (mut subgroup_x, vanish_zeta) = with_context!(self, "compute x from its index", { let g = self.constant(F::coset_shift()); let phi = self.constant(F::primitive_root_of_unity(n_log)); let phi = self.exp_from_bits(phi, x_index_bits.iter().rev()); - self.mul(g, phi) + let g_ext = self.convert_to_ext(g); + let phi_ext = self.convert_to_ext(phi); + let zero = self.zero_extension(); + let tmp = self.double_arithmetic_extension( + F::ONE, + F::NEG_ONE, + g_ext, + phi_ext, + zero, + g_ext, + phi_ext, + zeta, + ); + (tmp.0 .0[0], tmp.1) }); // old_eval is the last derived evaluation; it will be checked for consistency with its @@ -333,8 +345,8 @@ impl, const D: usize> CircuitBuilder { self.fri_combine_initial( &round_proof.initial_trees_proof, alpha, - zeta, subgroup_x, + vanish_zeta, precomputed_reduced_evals, common_data, ) From 75ad055f40cc953da66e942752ab4127e4c4cb18 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 14:28:05 +0200 Subject: [PATCH 03/17] First try --- src/gadgets/arithmetic_extension.rs | 135 ++++++++++++++++++++- src/gates/arithmetic.rs | 175 +++++++++++++++++----------- src/iop/generator.rs | 8 +- src/plonk/circuit_builder.rs | 3 + src/plonk/circuit_data.rs | 4 +- src/plonk/recursive_verifier.rs | 7 +- src/plonk/vanishing_poly.rs | 3 + src/util/reducing.rs | 27 ++++- 8 files changed, 278 insertions(+), 84 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 8b7c11e3..b76a2482 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -9,11 +9,75 @@ use crate::field::field_types::Field; use crate::gates::arithmetic::ArithmeticExtensionGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; +use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; impl, const D: usize> CircuitBuilder { + pub fn yo( + &mut self, + gate: usize, + first_multiplicand_0: ExtensionTarget, + first_multiplicand_1: ExtensionTarget, + first_addend: ExtensionTarget, + second_multiplicand_0: ExtensionTarget, + second_multiplicand_1: ExtensionTarget, + second_addend: ExtensionTarget, + ) -> (ExtensionTarget, ExtensionTarget) { + // for et in &mut [ + // first_multiplicand_0, + // first_multiplicand_1, + // first_addend, + // second_multiplicand_0, + // second_multiplicand_1, + // second_addend, + // ] { + // for t in &mut et.0 { + // if let Target::Wire(Wire { gate: g, input }) = t { + // if *g > gate { + // *g = gate; + // *input += 8 * D; + // dbg!(*g, *t); + // } + // } + // } + // } + let wire_third_multiplicand_0 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_third_multiplicand_0(), + ); + let wire_third_multiplicand_1 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_third_multiplicand_1(), + ); + let wire_third_addend = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_addend()); + let wire_fourth_multiplicand_0 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_fourth_multiplicand_0(), + ); + let wire_fourth_multiplicand_1 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_fourth_multiplicand_1(), + ); + let wire_fourth_addend = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_addend()); + let wire_third_output = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_output()); + let wire_fourth_output = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_output()); + + self.route_extension(first_multiplicand_0, wire_third_multiplicand_0); + self.route_extension(first_multiplicand_1, wire_third_multiplicand_1); + self.route_extension(first_addend, wire_third_addend); + self.route_extension(second_multiplicand_0, wire_fourth_multiplicand_0); + self.route_extension(second_multiplicand_1, wire_fourth_multiplicand_1); + self.route_extension(second_addend, wire_fourth_addend); + self.free_arithmetic = None; + + (wire_third_output, wire_fourth_output) + } pub fn double_arithmetic_extension( &mut self, const_0: F, @@ -25,8 +89,22 @@ impl, const D: usize> CircuitBuilder { second_multiplicand_1: ExtensionTarget, second_addend: ExtensionTarget, ) -> (ExtensionTarget, ExtensionTarget) { - let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]); + if let Some((g, c_0, c_1)) = self.free_arithmetic { + if g == self.num_gates() - 1 && c_0 == const_0 && c_1 == const_1 { + return self.yo( + g, + first_multiplicand_0, + first_multiplicand_1, + first_addend, + second_multiplicand_0, + second_multiplicand_1, + second_addend, + ); + } + } + let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]); + self.free_arithmetic = Some((gate, const_0, const_1)); let wire_first_multiplicand_0 = ExtensionTarget::from_range( gate, ArithmeticExtensionGate::::wires_first_multiplicand_0(), @@ -175,11 +253,27 @@ impl, const D: usize> CircuitBuilder { for chunk in pairs.chunks_exact(2) { let (a0, b0) = chunk[0]; let (a1, b1) = chunk[1]; - let gate = self.num_gates(); - let first_out = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_first_output(), - ); + let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { + if g == self.num_gates() - 1 && c_0 == constant && c_1 == F::ONE { + (g, ArithmeticExtensionGate::::wires_third_output()) + } else { + ( + self.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + } + } else { + ( + self.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + }; + let first_out = ExtensionTarget::from_range(gate, range); + // let gate = self.num_gates(); + // let first_out = ExtensionTarget::from_range( + // gate, + // ArithmeticExtensionGate::::wires_first_output(), + // ); acc = self .double_arithmetic_extension(constant, F::ONE, a0, b0, acc, a1, b1, first_out) .1; @@ -706,6 +800,35 @@ mod tests { verify(proof, &data.verifier_only, &data.common) } + #[test] + fn test_mul() -> Result<()> { + type F = CrandallField; + type FF = QuarticCrandallField; + const D: usize = 4; + + let config = CircuitConfig::large_config(); + + let pw = PartialWitness::new(config.num_wires); + let mut builder = CircuitBuilder::::new(config); + + let x = FF::ONE; + let y = FF::TWO; + let z = x * y; + let xt = builder.constant_extension(x); + let yt = builder.constant_extension(y); + let zt = builder.constant_extension(z); + let comp_zt = builder.mul_extension(xt, yt); + dbg!(comp_zt); + builder.add_marked(zt.into(), "yo"); + builder.add_marked(comp_zt.into(), "ya"); + builder.assert_equal_extension(zt, comp_zt); + + let data = builder.build(); + let proof = data.prove(pw)?; + + verify(proof, &data.verifier_only, &data.common) + } + #[test] fn test_div_extension() -> Result<()> { type F = CrandallField; diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 81c9bc9a..7c780671 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -27,6 +27,7 @@ impl ArithmeticExtensionGate { pub fn wires_first_output() -> Range { 3 * D..4 * D } + pub fn wires_second_multiplicand_0() -> Range { 4 * D..5 * D } @@ -39,6 +40,32 @@ impl ArithmeticExtensionGate { pub fn wires_second_output() -> Range { 7 * D..8 * D } + + pub fn wires_third_multiplicand_0() -> Range { + 8 * D..9 * D + } + pub fn wires_third_multiplicand_1() -> Range { + 9 * D..10 * D + } + pub fn wires_third_addend() -> Range { + 10 * D..11 * D + } + pub fn wires_third_output() -> Range { + 11 * D..12 * D + } + + pub fn wires_fourth_multiplicand_0() -> Range { + 12 * D..13 * D + } + pub fn wires_fourth_multiplicand_1() -> Range { + 13 * D..14 * D + } + pub fn wires_fourth_addend() -> Range { + 14 * D..15 * D + } + pub fn wires_fourth_output() -> Range { + 15 * D..16 * D + } } impl, const D: usize> Gate for ArithmeticExtensionGate { @@ -56,18 +83,32 @@ impl, const D: usize> Gate for ArithmeticExtensionGate let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0()); let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1()); let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend()); + let third_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_0()); + let third_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_1()); + let third_addend = vars.get_local_ext_algebra(Self::wires_third_addend()); + let fourth_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_0()); + let fourth_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_1()); + let fourth_addend = vars.get_local_ext_algebra(Self::wires_fourth_addend()); let first_output = vars.get_local_ext_algebra(Self::wires_first_output()); let second_output = vars.get_local_ext_algebra(Self::wires_second_output()); + let third_output = vars.get_local_ext_algebra(Self::wires_third_output()); + let fourth_output = vars.get_local_ext_algebra(Self::wires_fourth_output()); let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into() + first_addend * const_1.into(); let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into() + second_addend * const_1.into(); + let third_computed_output = third_multiplicand_0 * third_multiplicand_1 * const_0.into() + + third_addend * const_1.into(); + let fourth_computed_output = fourth_multiplicand_0 * fourth_multiplicand_1 * const_0.into() + + fourth_addend * const_1.into(); let mut constraints = (first_output - first_computed_output) .to_basefield_array() .to_vec(); constraints.extend((second_output - second_computed_output).to_basefield_array()); + constraints.extend((third_output - third_computed_output).to_basefield_array()); + constraints.extend((fourth_output - fourth_computed_output).to_basefield_array()); constraints } @@ -81,18 +122,32 @@ impl, const D: usize> Gate for ArithmeticExtensionGate let second_multiplicand_0 = vars.get_local_ext(Self::wires_second_multiplicand_0()); let second_multiplicand_1 = vars.get_local_ext(Self::wires_second_multiplicand_1()); let second_addend = vars.get_local_ext(Self::wires_second_addend()); + let third_multiplicand_0 = vars.get_local_ext(Self::wires_third_multiplicand_0()); + let third_multiplicand_1 = vars.get_local_ext(Self::wires_third_multiplicand_1()); + let third_addend = vars.get_local_ext(Self::wires_third_addend()); + let fourth_multiplicand_0 = vars.get_local_ext(Self::wires_fourth_multiplicand_0()); + let fourth_multiplicand_1 = vars.get_local_ext(Self::wires_fourth_multiplicand_1()); + let fourth_addend = vars.get_local_ext(Self::wires_fourth_addend()); let first_output = vars.get_local_ext(Self::wires_first_output()); let second_output = vars.get_local_ext(Self::wires_second_output()); + let third_output = vars.get_local_ext(Self::wires_third_output()); + let fourth_output = vars.get_local_ext(Self::wires_fourth_output()); let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into() + first_addend * const_1.into(); let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into() + second_addend * const_1.into(); + let third_computed_output = third_multiplicand_0 * third_multiplicand_1 * const_0.into() + + third_addend * const_1.into(); + let fourth_computed_output = fourth_multiplicand_0 * fourth_multiplicand_1 * const_0.into() + + fourth_addend * const_1.into(); let mut constraints = (first_output - first_computed_output) .to_basefield_array() .to_vec(); constraints.extend((second_output - second_computed_output).to_basefield_array()); + constraints.extend((third_output - third_computed_output).to_basefield_array()); + constraints.extend((fourth_output - fourth_computed_output).to_basefield_array()); constraints } @@ -110,8 +165,16 @@ impl, const D: usize> Gate for ArithmeticExtensionGate let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0()); let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1()); let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend()); + let third_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_0()); + let third_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_1()); + let third_addend = vars.get_local_ext_algebra(Self::wires_third_addend()); + let fourth_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_0()); + let fourth_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_1()); + let fourth_addend = vars.get_local_ext_algebra(Self::wires_fourth_addend()); let first_output = vars.get_local_ext_algebra(Self::wires_first_output()); let second_output = vars.get_local_ext_algebra(Self::wires_second_output()); + let third_output = vars.get_local_ext_algebra(Self::wires_third_output()); + let fourth_output = vars.get_local_ext_algebra(Self::wires_fourth_output()); let first_computed_output = builder.mul_ext_algebra(first_multiplicand_0, first_multiplicand_1); @@ -128,10 +191,29 @@ impl, const D: usize> Gate for ArithmeticExtensionGate let second_computed_output = builder.add_ext_algebra(second_computed_output, second_scaled_addend); + let third_computed_output = + builder.mul_ext_algebra(third_multiplicand_0, third_multiplicand_1); + let third_computed_output = builder.scalar_mul_ext_algebra(const_0, third_computed_output); + let third_scaled_addend = builder.scalar_mul_ext_algebra(const_1, third_addend); + let third_computed_output = + builder.add_ext_algebra(third_computed_output, third_scaled_addend); + + let fourth_computed_output = + builder.mul_ext_algebra(fourth_multiplicand_0, fourth_multiplicand_1); + let fourth_computed_output = + builder.scalar_mul_ext_algebra(const_0, fourth_computed_output); + let fourth_scaled_addend = builder.scalar_mul_ext_algebra(const_1, fourth_addend); + let fourth_computed_output = + builder.add_ext_algebra(fourth_computed_output, fourth_scaled_addend); + let diff_0 = builder.sub_ext_algebra(first_output, first_computed_output); let diff_1 = builder.sub_ext_algebra(second_output, second_computed_output); + let diff_2 = builder.sub_ext_algebra(third_output, third_computed_output); + let diff_3 = builder.sub_ext_algebra(fourth_output, fourth_computed_output); let mut constraints = diff_0.to_ext_target_array().to_vec(); constraints.extend(diff_1.to_ext_target_array()); + constraints.extend(diff_2.to_ext_target_array()); + constraints.extend(diff_3.to_ext_target_array()); constraints } @@ -140,21 +222,24 @@ impl, const D: usize> Gate for ArithmeticExtensionGate gate_index: usize, local_constants: &[F], ) -> Vec>> { - let gen0 = ArithmeticExtensionGenerator0 { - gate_index, - const_0: local_constants[0], - const_1: local_constants[1], - }; - let gen1 = ArithmeticExtensionGenerator1 { - gate_index, - const_0: local_constants[0], - const_1: local_constants[1], - }; - vec![Box::new(gen0), Box::new(gen1)] + let gens = (0..4) + .map(|i| ArithmeticExtensionGenerator { + gate_index, + const_0: local_constants[0], + const_1: local_constants[1], + i, + }) + .collect::>(); + vec![ + Box::new(gens[0].clone()), + Box::new(gens[1].clone()), + Box::new(gens[2].clone()), + Box::new(gens[3].clone()), + ] } fn num_wires(&self) -> usize { - 8 * D + 16 * D } fn num_constants(&self) -> usize { @@ -166,27 +251,21 @@ impl, const D: usize> Gate for ArithmeticExtensionGate } fn num_constraints(&self) -> usize { - 2 * D + 4 * D } } -struct ArithmeticExtensionGenerator0, const D: usize> { +#[derive(Clone)] +struct ArithmeticExtensionGenerator, const D: usize> { gate_index: usize, const_0: F, const_1: F, + i: usize, } -struct ArithmeticExtensionGenerator1, const D: usize> { - gate_index: usize, - const_0: F, - const_1: F, -} - -impl, const D: usize> SimpleGenerator for ArithmeticExtensionGenerator0 { +impl, const D: usize> SimpleGenerator for ArithmeticExtensionGenerator { fn dependencies(&self) -> Vec { - ArithmeticExtensionGate::::wires_first_multiplicand_0() - .chain(ArithmeticExtensionGate::::wires_first_multiplicand_1()) - .chain(ArithmeticExtensionGate::::wires_first_addend()) + (4 * self.i * D..(4 * self.i + 3) * D) .map(|i| Target::wire(self.gate_index, i)) .collect() } @@ -197,49 +276,13 @@ impl, const D: usize> SimpleGenerator for ArithmeticExtensio witness.get_extension_target(t) }; - let multiplicand_0 = - extract_extension(ArithmeticExtensionGate::::wires_first_multiplicand_0()); - let multiplicand_1 = - extract_extension(ArithmeticExtensionGate::::wires_first_multiplicand_1()); - let addend = extract_extension(ArithmeticExtensionGate::::wires_first_addend()); + let start = 4 * self.i * D; + let multiplicand_0 = extract_extension(start..start + D); + let multiplicand_1 = extract_extension(start + D..start + 2 * D); + let addend = extract_extension(start + 2 * D..start + 3 * D); - let output_target = ExtensionTarget::from_range( - self.gate_index, - ArithmeticExtensionGate::::wires_first_output(), - ); - - let computed_output = - multiplicand_0 * multiplicand_1 * self.const_0.into() + addend * self.const_1.into(); - - out_buffer.set_extension_target(output_target, computed_output) - } -} - -impl, const D: usize> SimpleGenerator for ArithmeticExtensionGenerator1 { - fn dependencies(&self) -> Vec { - ArithmeticExtensionGate::::wires_second_multiplicand_0() - .chain(ArithmeticExtensionGate::::wires_second_multiplicand_1()) - .chain(ArithmeticExtensionGate::::wires_second_addend()) - .map(|i| Target::wire(self.gate_index, i)) - .collect() - } - - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { - let extract_extension = |range: Range| -> F::Extension { - let t = ExtensionTarget::from_range(self.gate_index, range); - witness.get_extension_target(t) - }; - - let multiplicand_0 = - extract_extension(ArithmeticExtensionGate::::wires_second_multiplicand_0()); - let multiplicand_1 = - extract_extension(ArithmeticExtensionGate::::wires_second_multiplicand_1()); - let addend = extract_extension(ArithmeticExtensionGate::::wires_second_addend()); - - let output_target = ExtensionTarget::from_range( - self.gate_index, - ArithmeticExtensionGate::::wires_second_output(), - ); + let output_target = + ExtensionTarget::from_range(self.gate_index, start + 3 * D..start + 4 * D); let computed_output = multiplicand_0 * multiplicand_1 * self.const_0.into() + addend * self.const_1.into(); diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 6ab1b412..189648c5 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -76,10 +76,10 @@ pub(crate) fn generate_partial_witness( pending_generator_indices = next_pending_generator_indices; } - assert!( - generator_is_expired.into_iter().all(identity), - "Some generators weren't run." - ); + // assert!( + // generator_is_expired.into_iter().all(identity), + // "Some generators weren't run." + // ); } /// A generator participates in the generation of the witness. diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index d783d890..bae4b5d6 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -60,6 +60,8 @@ pub struct CircuitBuilder, const D: usize> { constants_to_targets: HashMap, targets_to_constants: HashMap, + + pub(crate) free_arithmetic: Option<(usize, F, F)>, } impl, const D: usize> CircuitBuilder { @@ -76,6 +78,7 @@ impl, const D: usize> CircuitBuilder { generators: Vec::new(), constants_to_targets: HashMap::new(), targets_to_constants: HashMap::new(), + free_arithmetic: None, } } diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 2441d810..59aaa485 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -66,11 +66,11 @@ impl CircuitConfig { security_bits: 128, rate_bits: 3, num_challenges: 3, - zero_knowledge: true, + zero_knowledge: false, cap_height: 1, fri_config: FriConfig { proof_of_work_bits: 1, - reduction_arity_bits: vec![1, 1, 1, 1], + reduction_arity_bits: vec![1], num_query_rounds: 1, cap_height: 1, }, diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 369fbcb1..792c8270 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -97,8 +97,13 @@ impl, const D: usize> CircuitBuilder { .chunks(inner_common_data.quotient_degree_factor) .enumerate() { + dbg!(chunk.len()); let recombined_quotient = scale.reduce(chunk, self); + self.add_marked(z_h_zeta.into(), &format!("zhz {}", i)); + self.add_marked(recombined_quotient.into(), &format!("recomb {}", i)); let computed_vanishing_poly = self.mul_extension(z_h_zeta, recombined_quotient); + self.add_marked(vanishing_polys_zeta[i].into(), &format!("yo {}", i)); + self.add_marked(computed_vanishing_poly.into(), &format!("ya {}", i)); self.named_assert_equal_extension( vanishing_polys_zeta[i], computed_vanishing_poly, @@ -444,7 +449,7 @@ mod tests { let mut builder = CircuitBuilder::::new(config.clone()); let _two = builder.two(); let mut _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; - for _ in 0..10000 { + for _ in 0..20000 { _two = builder.mul(_two, _two); } let data = builder.build(); diff --git a/src/plonk/vanishing_poly.rs b/src/plonk/vanishing_poly.rs index e2180552..1f7526e2 100644 --- a/src/plonk/vanishing_poly.rs +++ b/src/plonk/vanishing_poly.rs @@ -382,6 +382,9 @@ pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( ] .concat(); + for (i, &v) in vanishing_terms.iter().enumerate() { + builder.add_marked(v.into(), &format!("v {}", i)); + } alphas .iter() .map(|&alpha| { diff --git a/src/util/reducing.rs b/src/util/reducing.rs index 8e8fa661..479e7e39 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -176,16 +176,30 @@ impl ReducingFactorTarget { terms_vec.reverse(); let mut acc = zero; + let mut countt = 0; + dbg!(terms_vec.len()); for pair in terms_vec.chunks(2) { // We will route the output of the first arithmetic operation to the multiplicand of the // second, i.e. we compute the following: // out_0 = alpha acc + pair[0] // acc' = out_1 = alpha out_0 + pair[1] - let gate = builder.num_gates(); - let out_0 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_first_output(), - ); + + let (gate, range) = if let Some((g, c_0, c_1)) = builder.free_arithmetic { + if g == builder.num_gates() - 1 && c_0 == F::ONE && c_1 == F::ONE { + (g, ArithmeticExtensionGate::::wires_third_output()) + } else { + ( + builder.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + } + } else { + ( + builder.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + }; + let out_0 = ExtensionTarget::from_range(gate, range); acc = builder .double_arithmetic_extension( F::ONE, @@ -198,6 +212,9 @@ impl ReducingFactorTarget { pair[1], ) .1; + // dbg!(countt, acc); + // builder.add_marked(acc.into(), &format!("acc {}", countt)); + countt += 1; } acc } From 7da4412de55e5d2dd7ccf99189015e69dc20e9d9 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 15:22:03 +0200 Subject: [PATCH 04/17] working --- src/gadgets/arithmetic_extension.rs | 68 +++++++++++++++++++---------- src/plonk/recursive_verifier.rs | 5 --- src/plonk/vanishing_poly.rs | 8 ++-- src/util/reducing.rs | 5 --- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index b76a2482..1d65180e 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -25,24 +25,6 @@ impl, const D: usize> CircuitBuilder { second_multiplicand_1: ExtensionTarget, second_addend: ExtensionTarget, ) -> (ExtensionTarget, ExtensionTarget) { - // for et in &mut [ - // first_multiplicand_0, - // first_multiplicand_1, - // first_addend, - // second_multiplicand_0, - // second_multiplicand_1, - // second_addend, - // ] { - // for t in &mut et.0 { - // if let Target::Wire(Wire { gate: g, input }) = t { - // if *g > gate { - // *g = gate; - // *input += 8 * D; - // dbg!(*g, *t); - // } - // } - // } - // } let wire_third_multiplicand_0 = ExtensionTarget::from_range( gate, ArithmeticExtensionGate::::wires_third_multiplicand_0(), @@ -497,10 +479,26 @@ impl, const D: usize> CircuitBuilder { c: ExtensionTarget, ) -> ExtensionTarget { let zero = self.zero_extension(); - let gate = self.num_gates(); - let first_out = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_first_output()); - self.double_arithmetic_extension(F::ONE, F::ZERO, a, b, zero, c, first_out, zero) + let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { + if g == self.num_gates() - 1 && c_0 == F::ONE && c_1 == F::ONE { + (g, ArithmeticExtensionGate::::wires_third_output()) + } else { + ( + self.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + } + } else { + ( + self.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + }; + let first_out = ExtensionTarget::from_range(gate, range); + // let gate = self.num_gates(); + // let first_out = + // ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_first_output()); + self.double_arithmetic_extension(F::ONE, F::ONE, a, b, zero, c, first_out, zero) .1 } @@ -763,6 +761,31 @@ mod tests { use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; + #[test] + fn test_gaga() -> Result<()> { + type F = CrandallField; + type FF = QuarticCrandallField; + const D: usize = 4; + + let config = CircuitConfig { + num_routed_wires: 64, + ..CircuitConfig::large_config() + }; + + let mut pw = PartialWitness::new(config.num_wires); + let mut builder = CircuitBuilder::::new(config); + + let n = 6; + let vs = FF::rand_vec(n); + let ts = builder.add_virtual_extension_targets(n); + pw.set_extension_targets(&ts, &vs); + let mul0 = builder.mul_many_extension(&ts); + let data = builder.build(); + let proof = data.prove(pw)?; + + verify(proof, &data.verifier_only, &data.common) + } + #[test] fn test_mul_many() -> Result<()> { type F = CrandallField; @@ -818,7 +841,6 @@ mod tests { let yt = builder.constant_extension(y); let zt = builder.constant_extension(z); let comp_zt = builder.mul_extension(xt, yt); - dbg!(comp_zt); builder.add_marked(zt.into(), "yo"); builder.add_marked(comp_zt.into(), "ya"); builder.assert_equal_extension(zt, comp_zt); diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 792c8270..ab8554b4 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -97,13 +97,8 @@ impl, const D: usize> CircuitBuilder { .chunks(inner_common_data.quotient_degree_factor) .enumerate() { - dbg!(chunk.len()); let recombined_quotient = scale.reduce(chunk, self); - self.add_marked(z_h_zeta.into(), &format!("zhz {}", i)); - self.add_marked(recombined_quotient.into(), &format!("recomb {}", i)); let computed_vanishing_poly = self.mul_extension(z_h_zeta, recombined_quotient); - self.add_marked(vanishing_polys_zeta[i].into(), &format!("yo {}", i)); - self.add_marked(computed_vanishing_poly.into(), &format!("ya {}", i)); self.named_assert_equal_extension( vanishing_polys_zeta[i], computed_vanishing_poly, diff --git a/src/plonk/vanishing_poly.rs b/src/plonk/vanishing_poly.rs index 1f7526e2..a2a97d4b 100644 --- a/src/plonk/vanishing_poly.rs +++ b/src/plonk/vanishing_poly.rs @@ -363,8 +363,9 @@ pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( .chunks(max_degree) .zip(partial_product_check.iter_mut()) .for_each(|(d, q)| { - let tmp = builder.mul_many_extension(d); - *q = builder.mul_extension(*q, tmp); + let mut v = d.to_vec(); + v.push(*q); + *q = builder.mul_many_extension(&v); }); vanishing_partial_products_terms.extend(partial_product_check); @@ -382,9 +383,6 @@ pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( ] .concat(); - for (i, &v) in vanishing_terms.iter().enumerate() { - builder.add_marked(v.into(), &format!("v {}", i)); - } alphas .iter() .map(|&alpha| { diff --git a/src/util/reducing.rs b/src/util/reducing.rs index 479e7e39..3d10956a 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -176,8 +176,6 @@ impl ReducingFactorTarget { terms_vec.reverse(); let mut acc = zero; - let mut countt = 0; - dbg!(terms_vec.len()); for pair in terms_vec.chunks(2) { // We will route the output of the first arithmetic operation to the multiplicand of the // second, i.e. we compute the following: @@ -212,9 +210,6 @@ impl ReducingFactorTarget { pair[1], ) .1; - // dbg!(countt, acc); - // builder.add_marked(acc.into(), &format!("acc {}", countt)); - countt += 1; } acc } From 1c789657638b194b5884719913799a39c49bacda Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 15:24:38 +0200 Subject: [PATCH 05/17] better --- src/gadgets/arithmetic_extension.rs | 6 +++--- src/util/reducing.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 1d65180e..25328f25 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -72,7 +72,7 @@ impl, const D: usize> CircuitBuilder { second_addend: ExtensionTarget, ) -> (ExtensionTarget, ExtensionTarget) { if let Some((g, c_0, c_1)) = self.free_arithmetic { - if g == self.num_gates() - 1 && c_0 == const_0 && c_1 == const_1 { + if c_0 == const_0 && c_1 == const_1 { return self.yo( g, first_multiplicand_0, @@ -236,7 +236,7 @@ impl, const D: usize> CircuitBuilder { let (a0, b0) = chunk[0]; let (a1, b1) = chunk[1]; let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { - if g == self.num_gates() - 1 && c_0 == constant && c_1 == F::ONE { + if c_0 == constant && c_1 == F::ONE { (g, ArithmeticExtensionGate::::wires_third_output()) } else { ( @@ -480,7 +480,7 @@ impl, const D: usize> CircuitBuilder { ) -> ExtensionTarget { let zero = self.zero_extension(); let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { - if g == self.num_gates() - 1 && c_0 == F::ONE && c_1 == F::ONE { + if c_0 == F::ONE && c_1 == F::ONE { (g, ArithmeticExtensionGate::::wires_third_output()) } else { ( diff --git a/src/util/reducing.rs b/src/util/reducing.rs index 3d10956a..459454db 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -183,7 +183,7 @@ impl ReducingFactorTarget { // acc' = out_1 = alpha out_0 + pair[1] let (gate, range) = if let Some((g, c_0, c_1)) = builder.free_arithmetic { - if g == builder.num_gates() - 1 && c_0 == F::ONE && c_1 == F::ONE { + if c_0 == F::ONE && c_1 == F::ONE { (g, ArithmeticExtensionGate::::wires_third_output()) } else { ( From 611c1767b1968cedf5ffe37ded549dee25c0374a Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 16:04:31 +0200 Subject: [PATCH 06/17] add reducing ext gate --- src/gates/mod.rs | 1 + src/gates/reducing_ext.rs | 217 +++++++++++++++++++++++++++++++++++ src/plonk/circuit_builder.rs | 2 +- src/plonk/circuit_data.rs | 2 +- src/util/reducing.rs | 135 +++++++++++++++------- 5 files changed, 311 insertions(+), 46 deletions(-) create mode 100644 src/gates/reducing_ext.rs diff --git a/src/gates/mod.rs b/src/gates/mod.rs index dcb96b96..24cf8159 100644 --- a/src/gates/mod.rs +++ b/src/gates/mod.rs @@ -14,6 +14,7 @@ pub(crate) mod noop; pub(crate) mod public_input; pub mod random_access; pub mod reducing; +pub mod reducing_ext; #[cfg(test)] mod gate_testing; diff --git a/src/gates/reducing_ext.rs b/src/gates/reducing_ext.rs new file mode 100644 index 00000000..fc83d17d --- /dev/null +++ b/src/gates/reducing_ext.rs @@ -0,0 +1,217 @@ +use std::ops::Range; + +use crate::field::extension_field::target::ExtensionTarget; +use crate::field::extension_field::Extendable; +use crate::field::extension_field::FieldExtension; +use crate::gates::gate::Gate; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::target::Target; +use crate::iop::witness::PartialWitness; +use crate::plonk::circuit_builder::CircuitBuilder; +use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; + +/// Computes `sum alpha^i c_i` for a vector `c_i` of `num_coeffs` elements of the extension field. +#[derive(Debug, Clone)] +pub struct ReducingExtGate { + pub num_coeffs: usize, +} + +impl ReducingExtGate { + pub fn new(num_coeffs: usize) -> Self { + Self { num_coeffs } + } + + pub fn max_coeffs_len(num_wires: usize, num_routed_wires: usize) -> usize { + ((num_routed_wires - 3 * D) / D).min((num_wires - 2 * D) / (D * 2)) + } + + pub fn wires_output() -> Range { + 0..D + } + pub fn wires_alpha() -> Range { + D..2 * D + } + pub fn wires_old_acc() -> Range { + 2 * D..3 * D + } + const START_COEFFS: usize = 3 * D; + pub fn wires_coeff(i: usize) -> Range { + Self::START_COEFFS + i * D..Self::START_COEFFS + (i + 1) * D + } + fn start_accs(&self) -> usize { + Self::START_COEFFS + self.num_coeffs * D + } + fn wires_accs(&self, i: usize) -> Range { + if i == self.num_coeffs - 1 { + // The last accumulator is the output. + return Self::wires_output(); + } + self.start_accs() + D * i..self.start_accs() + D * (i + 1) + } +} + +impl, const D: usize> Gate for ReducingExtGate { + fn id(&self) -> String { + format!("{:?}", self) + } + + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { + let alpha = vars.get_local_ext_algebra(Self::wires_alpha()); + let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc()); + let coeffs = (0..self.num_coeffs) + .map(|i| vars.get_local_ext_algebra(Self::wires_coeff(i))) + .collect::>(); + let accs = (0..self.num_coeffs) + .map(|i| vars.get_local_ext_algebra(self.wires_accs(i))) + .collect::>(); + + let mut constraints = Vec::with_capacity(>::num_constraints(self)); + let mut acc = old_acc; + for i in 0..self.num_coeffs { + constraints.push(acc * alpha + coeffs[i] - accs[i]); + acc = accs[i]; + } + + constraints + .into_iter() + .flat_map(|alg| alg.to_basefield_array()) + .collect() + } + + fn eval_unfiltered_base(&self, vars: EvaluationVarsBase) -> Vec { + let alpha = vars.get_local_ext(Self::wires_alpha()); + let old_acc = vars.get_local_ext(Self::wires_old_acc()); + let coeffs = (0..self.num_coeffs) + .map(|i| vars.get_local_ext(Self::wires_coeff(i))) + .collect::>(); + let accs = (0..self.num_coeffs) + .map(|i| vars.get_local_ext(self.wires_accs(i))) + .collect::>(); + + let mut constraints = Vec::with_capacity(>::num_constraints(self)); + let mut acc = old_acc; + for i in 0..self.num_coeffs { + constraints.extend((acc * alpha + coeffs[i] - accs[i]).to_basefield_array()); + acc = accs[i]; + } + + constraints + } + + fn eval_unfiltered_recursively( + &self, + builder: &mut CircuitBuilder, + vars: EvaluationTargets, + ) -> Vec> { + let alpha = vars.get_local_ext_algebra(Self::wires_alpha()); + let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc()); + let coeffs = (0..self.num_coeffs) + .map(|i| vars.get_local_ext_algebra(Self::wires_coeff(i))) + .collect::>(); + let accs = (0..self.num_coeffs) + .map(|i| vars.get_local_ext_algebra(self.wires_accs(i))) + .collect::>(); + + let mut constraints = Vec::with_capacity(>::num_constraints(self)); + let mut acc = old_acc; + for i in 0..self.num_coeffs { + let coeff = coeffs[i]; + let mut tmp = builder.mul_add_ext_algebra(acc, alpha, coeff); + tmp = builder.sub_ext_algebra(tmp, accs[i]); + constraints.push(tmp); + acc = accs[i]; + } + + constraints + .into_iter() + .flat_map(|alg| alg.to_ext_target_array()) + .collect() + } + + fn generators( + &self, + gate_index: usize, + _local_constants: &[F], + ) -> Vec>> { + vec![Box::new(ReducingGenerator { + gate_index, + gate: self.clone(), + })] + } + + fn num_wires(&self) -> usize { + 2 * D + 2 * D * self.num_coeffs + } + + fn num_constants(&self) -> usize { + 0 + } + + fn degree(&self) -> usize { + 2 + } + + fn num_constraints(&self) -> usize { + D * self.num_coeffs + } +} + +struct ReducingGenerator { + gate_index: usize, + gate: ReducingExtGate, +} + +impl, const D: usize> SimpleGenerator for ReducingGenerator { + fn dependencies(&self) -> Vec { + ReducingExtGate::::wires_alpha() + .chain(ReducingExtGate::::wires_old_acc()) + .chain((0..self.gate.num_coeffs).flat_map(|i| ReducingExtGate::::wires_coeff(i))) + .map(|i| Target::wire(self.gate_index, i)) + .collect() + } + + fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { + let extract_extension = |range: Range| -> F::Extension { + let t = ExtensionTarget::from_range(self.gate_index, range); + witness.get_extension_target(t) + }; + + let alpha = extract_extension(ReducingExtGate::::wires_alpha()); + let old_acc = extract_extension(ReducingExtGate::::wires_old_acc()); + let coeffs = (0..self.gate.num_coeffs) + .map(|i| extract_extension(ReducingExtGate::::wires_coeff(i))) + .collect::>(); + let accs = (0..self.gate.num_coeffs) + .map(|i| ExtensionTarget::from_range(self.gate_index, self.gate.wires_accs(i))) + .collect::>(); + let output = + ExtensionTarget::from_range(self.gate_index, ReducingExtGate::::wires_output()); + + let mut acc = old_acc; + for i in 0..self.gate.num_coeffs { + let computed_acc = acc * alpha + coeffs[i]; + out_buffer.set_extension_target(accs[i], computed_acc); + acc = computed_acc; + } + out_buffer.set_extension_target(output, acc); + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + + use crate::field::crandall_field::CrandallField; + use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; + use crate::gates::reducing_ext::ReducingExtGate; + + #[test] + fn low_degree() { + test_low_degree::(ReducingExtGate::new(22)); + } + + #[test] + fn eval_fns() -> Result<()> { + test_eval_fns::(ReducingExtGate::new(22)) + } +} diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index bae4b5d6..955fb98b 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -39,7 +39,7 @@ pub struct CircuitBuilder, const D: usize> { gates: HashSet>, /// The concrete placement of each gate. - gate_instances: Vec>, + pub gate_instances: Vec>, /// Targets to be made public. public_inputs: Vec, diff --git a/src/plonk/circuit_data.rs b/src/plonk/circuit_data.rs index 59aaa485..861bf1b0 100644 --- a/src/plonk/circuit_data.rs +++ b/src/plonk/circuit_data.rs @@ -62,7 +62,7 @@ impl CircuitConfig { pub(crate) fn large_config() -> Self { Self { num_wires: 126, - num_routed_wires: 33, + num_routed_wires: 64, security_bits: 128, rate_bits: 3, num_challenges: 3, diff --git a/src/util/reducing.rs b/src/util/reducing.rs index 459454db..7e19f9d7 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -7,6 +7,7 @@ use crate::field::extension_field::{Extendable, Frobenius}; use crate::field::field_types::Field; use crate::gates::arithmetic::ArithmeticExtensionGate; use crate::gates::reducing::ReducingGate; +use crate::gates::reducing_ext::ReducingExtGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::polynomial::polynomial::PolynomialCoeffs; @@ -164,54 +165,89 @@ impl ReducingFactorTarget { where F: Extendable, { - let zero = builder.zero_extension(); - let l = terms.len(); - self.count += l as u64; - - let mut terms_vec = terms.to_vec(); - // If needed, we pad the original vector so that it has even length. - if terms_vec.len().is_odd() { - terms_vec.push(zero); + let max_coeffs_len = ReducingExtGate::::max_coeffs_len( + builder.config.num_wires, + builder.config.num_routed_wires, + ); + self.count += terms.len() as u64; + let zero_ext = builder.zero_extension(); + let mut acc = zero_ext; + let mut reversed_terms = terms.to_vec(); + while reversed_terms.len() % max_coeffs_len != 0 { + reversed_terms.push(zero_ext); } - terms_vec.reverse(); + reversed_terms.reverse(); + for chunk in reversed_terms.chunks_exact(max_coeffs_len) { + let gate = ReducingExtGate::new(max_coeffs_len); + let gate_index = builder.add_gate(gate.clone(), Vec::new()); - let mut acc = zero; - for pair in terms_vec.chunks(2) { - // We will route the output of the first arithmetic operation to the multiplicand of the - // second, i.e. we compute the following: - // out_0 = alpha acc + pair[0] - // acc' = out_1 = alpha out_0 + pair[1] + builder.route_extension( + self.base, + ExtensionTarget::from_range(gate_index, ReducingGate::::wires_alpha()), + ); + builder.route_extension( + acc, + ExtensionTarget::from_range(gate_index, ReducingGate::::wires_old_acc()), + ); + for (i, &t) in chunk.iter().enumerate() { + builder.route_extension( + t, + ExtensionTarget::from_range(gate_index, ReducingExtGate::::wires_coeff(i)), + ); + } - let (gate, range) = if let Some((g, c_0, c_1)) = builder.free_arithmetic { - if c_0 == F::ONE && c_1 == F::ONE { - (g, ArithmeticExtensionGate::::wires_third_output()) - } else { - ( - builder.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - } - } else { - ( - builder.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - }; - let out_0 = ExtensionTarget::from_range(gate, range); - acc = builder - .double_arithmetic_extension( - F::ONE, - F::ONE, - self.base, - acc, - pair[0], - self.base, - out_0, - pair[1], - ) - .1; + acc = ExtensionTarget::from_range(gate_index, ReducingGate::::wires_output()); } + acc + // let zero = builder.zero_extension(); + // let l = terms.len(); + // self.count += l as u64; + // + // let mut terms_vec = terms.to_vec(); + // // If needed, we pad the original vector so that it has even length. + // if terms_vec.len().is_odd() { + // terms_vec.push(zero); + // } + // terms_vec.reverse(); + // + // let mut acc = zero; + // for pair in terms_vec.chunks(2) { + // // We will route the output of the first arithmetic operation to the multiplicand of the + // // second, i.e. we compute the following: + // // out_0 = alpha acc + pair[0] + // // acc' = out_1 = alpha out_0 + pair[1] + // + // let (gate, range) = if let Some((g, c_0, c_1)) = builder.free_arithmetic { + // if c_0 == F::ONE && c_1 == F::ONE { + // (g, ArithmeticExtensionGate::::wires_third_output()) + // } else { + // ( + // builder.num_gates(), + // ArithmeticExtensionGate::::wires_first_output(), + // ) + // } + // } else { + // ( + // builder.num_gates(), + // ArithmeticExtensionGate::::wires_first_output(), + // ) + // }; + // let out_0 = ExtensionTarget::from_range(gate, range); + // acc = builder + // .double_arithmetic_extension( + // F::ONE, + // F::ONE, + // self.base, + // acc, + // pair[0], + // self.base, + // out_0, + // pair[1], + // ) + // .1; + // } + // acc } pub fn shift( @@ -301,7 +337,10 @@ mod tests { type FF = QuarticCrandallField; const D: usize = 4; - let config = CircuitConfig::large_config(); + let config = CircuitConfig { + num_routed_wires: 64, + ..CircuitConfig::large_config() + }; let pw = PartialWitness::new(config.num_wires); let mut builder = CircuitBuilder::::new(config); @@ -321,6 +360,9 @@ mod tests { builder.assert_equal_extension(manual_reduce, circuit_reduce); + for g in &builder.gate_instances { + println!("{}", g.gate_ref.0.id()); + } let data = builder.build(); let proof = data.prove(pw)?; @@ -332,6 +374,11 @@ mod tests { test_reduce_gadget(10) } + #[test] + fn test_yo() -> Result<()> { + test_reduce_gadget(100) + } + #[test] fn test_reduce_gadget_odd() -> Result<()> { test_reduce_gadget(11) From d0aae8c2a7325b1f00dca2aa63c79fb46870e755 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 16:39:26 +0200 Subject: [PATCH 07/17] clean --- src/fri/recursive_verifier.rs | 5 ----- src/plonk/prover.rs | 38 +++++++++++++++++------------------ 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index d8f6b0ef..0e7fa381 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -215,7 +215,6 @@ impl, const D: usize> CircuitBuilder { precomputed_reduced_evals: PrecomputedReducedEvalsTarget, common_data: &CommonCircuitData, ) -> ExtensionTarget { - println!("combine initial: {}", self.num_gates()); assert!(D > 1, "Not implemented for D=1."); let config = self.config.clone(); let degree_log = common_data.degree_bits; @@ -252,7 +251,6 @@ impl, const D: usize> CircuitBuilder { sum = self.div_add_extension(single_numerator, vanish_zeta, sum); alpha.reset(); - println!("done single: {}", self.num_gates()); // Polynomials opened at `x` and `g x`, i.e., the Zs polynomials. let zs_evals = proof .unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge) @@ -276,7 +274,6 @@ impl, const D: usize> CircuitBuilder { let (mut sum, zs_denominator) = alpha.shift_and_mul(sum, vanish_zeta, vanish_zeta_right, self); sum = self.div_add_extension(zs_numerator, zs_denominator, sum); - println!("done doubles: {}", self.num_gates()); sum } @@ -294,7 +291,6 @@ impl, const D: usize> CircuitBuilder { round_proof: &FriQueryRoundTarget, common_data: &CommonCircuitData, ) { - println!("query round: {}", self.num_gates()); let config = &common_data.config.fri_config; let n_log = log2_strict(n); // TODO: Do we need to range check `x_index` to a target smaller than `p`? @@ -353,7 +349,6 @@ impl, const D: usize> CircuitBuilder { ); for (i, &arity_bits) in config.reduction_arity_bits.iter().enumerate() { - println!("query round, {}-th arity: {}", i, self.num_gates()); let evals = &round_proof.steps[i].evals; // Split x_index into the index of the coset x is in, and the index of x within that coset. diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 026fc4b7..71743b4d 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -68,25 +68,25 @@ pub(crate) fn prove, const D: usize>( partial_witness.full_witness(degree, num_wires) ); - { - let mut count = 0; - let mut count_bad = 0; - for i in 0..degree { - if prover_data.gate_instances[i].gate_ref.0.id() - != "ArithmeticExtensionGate".to_string() - { - continue; - } - count += 1; - let row = witness.wire_values.iter().map(|c| c[i]).collect::>(); - // println!("{} {:?}", i, &row); - if row[16..].iter().all(|x| x.is_zero()) { - println!("{} {:?}", i, row); - count_bad += 1; - } - } - println!("{} {}", count, count_bad); - } + // { + // let mut count = 0; + // let mut count_bad = 0; + // for i in 0..degree { + // if prover_data.gate_instances[i].gate_ref.0.id() + // != "ArithmeticExtensionGate".to_string() + // { + // continue; + // } + // count += 1; + // let row = witness.wire_values.iter().map(|c| c[i]).collect::>(); + // // println!("{} {:?}", i, &row); + // if row[16..].iter().all(|x| x.is_zero()) { + // println!("{} {:?}", i, row); + // count_bad += 1; + // } + // } + // println!("{} {}", count, count_bad); + // } let wires_values: Vec> = timed!( timing, From 68af28e9a2c066899e6c456cd5c6e1915c9a7d69 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 17:41:26 +0200 Subject: [PATCH 08/17] Fix tests --- src/fri/commitment.rs | 1 + src/gadgets/select.rs | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/fri/commitment.rs b/src/fri/commitment.rs index d62fa33d..f665e058 100644 --- a/src/fri/commitment.rs +++ b/src/fri/commitment.rs @@ -288,6 +288,7 @@ mod tests { config: CircuitConfig { fri_config, num_routed_wires: 6, + zero_knowledge: true, ..CircuitConfig::large_config() }, degree_bits, diff --git a/src/gadgets/select.rs b/src/gadgets/select.rs index 58de09c6..f77a38f5 100644 --- a/src/gadgets/select.rs +++ b/src/gadgets/select.rs @@ -14,10 +14,23 @@ impl, const D: usize> CircuitBuilder { x: ExtensionTarget, y: ExtensionTarget, ) -> ExtensionTarget { - let gate = self.num_gates(); // Holds `by - y`. - let first_out = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_first_output()); + let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { + if c_0 == F::ONE && c_1 == F::NEG_ONE { + (g, ArithmeticExtensionGate::::wires_third_output()) + } else { + ( + self.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + } + } else { + ( + self.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + }; + let first_out = ExtensionTarget::from_range(gate, range); self.double_arithmetic_extension(F::ONE, F::NEG_ONE, b, y, y, b, x, first_out) .1 } From 237ef4d0ec0149b4cedc34b29fdbe2e48bc6d487 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 18:24:46 +0200 Subject: [PATCH 09/17] Change FRI params to get below 2^13 --- src/plonk/recursive_verifier.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index ab8554b4..62b8f888 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -428,14 +428,14 @@ mod tests { num_wires: 126, num_routed_wires: 64, security_bits: 128, - rate_bits: 3, + rate_bits: 4, num_challenges: 3, zero_knowledge: false, cap_height: 3, fri_config: FriConfig { proof_of_work_bits: 1, reduction_arity_bits: vec![3, 3, 3], - num_query_rounds: 40, + num_query_rounds: 33, cap_height: 3, }, }; From ceae6b958861fb873d3cbab69694f2bc48414ca1 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 20:12:20 +0200 Subject: [PATCH 10/17] Cleaning --- src/gadgets/arithmetic_extension.rs | 146 +++++++++------------------- src/gadgets/interpolation.rs | 5 +- src/plonk/circuit_builder.rs | 2 +- src/plonk/prover.rs | 20 ---- src/plonk/recursive_verifier.rs | 2 +- src/util/reducing.rs | 129 ++++++++---------------- 6 files changed, 94 insertions(+), 210 deletions(-) diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 25328f25..c762aa17 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -15,51 +15,6 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; impl, const D: usize> CircuitBuilder { - pub fn yo( - &mut self, - gate: usize, - first_multiplicand_0: ExtensionTarget, - first_multiplicand_1: ExtensionTarget, - first_addend: ExtensionTarget, - second_multiplicand_0: ExtensionTarget, - second_multiplicand_1: ExtensionTarget, - second_addend: ExtensionTarget, - ) -> (ExtensionTarget, ExtensionTarget) { - let wire_third_multiplicand_0 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_third_multiplicand_0(), - ); - let wire_third_multiplicand_1 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_third_multiplicand_1(), - ); - let wire_third_addend = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_addend()); - let wire_fourth_multiplicand_0 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_fourth_multiplicand_0(), - ); - let wire_fourth_multiplicand_1 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_fourth_multiplicand_1(), - ); - let wire_fourth_addend = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_addend()); - let wire_third_output = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_output()); - let wire_fourth_output = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_output()); - - self.route_extension(first_multiplicand_0, wire_third_multiplicand_0); - self.route_extension(first_multiplicand_1, wire_third_multiplicand_1); - self.route_extension(first_addend, wire_third_addend); - self.route_extension(second_multiplicand_0, wire_fourth_multiplicand_0); - self.route_extension(second_multiplicand_1, wire_fourth_multiplicand_1); - self.route_extension(second_addend, wire_fourth_addend); - self.free_arithmetic = None; - - (wire_third_output, wire_fourth_output) - } pub fn double_arithmetic_extension( &mut self, const_0: F, @@ -73,7 +28,7 @@ impl, const D: usize> CircuitBuilder { ) -> (ExtensionTarget, ExtensionTarget) { if let Some((g, c_0, c_1)) = self.free_arithmetic { if c_0 == const_0 && c_1 == const_1 { - return self.yo( + return self.arithmetic_reusing_gate( g, first_multiplicand_0, first_multiplicand_1, @@ -121,6 +76,52 @@ impl, const D: usize> CircuitBuilder { (wire_first_output, wire_second_output) } + fn arithmetic_reusing_gate( + &mut self, + gate: usize, + first_multiplicand_0: ExtensionTarget, + first_multiplicand_1: ExtensionTarget, + first_addend: ExtensionTarget, + second_multiplicand_0: ExtensionTarget, + second_multiplicand_1: ExtensionTarget, + second_addend: ExtensionTarget, + ) -> (ExtensionTarget, ExtensionTarget) { + let wire_third_multiplicand_0 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_third_multiplicand_0(), + ); + let wire_third_multiplicand_1 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_third_multiplicand_1(), + ); + let wire_third_addend = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_addend()); + let wire_fourth_multiplicand_0 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_fourth_multiplicand_0(), + ); + let wire_fourth_multiplicand_1 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_fourth_multiplicand_1(), + ); + let wire_fourth_addend = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_addend()); + let wire_third_output = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_output()); + let wire_fourth_output = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_output()); + + self.route_extension(first_multiplicand_0, wire_third_multiplicand_0); + self.route_extension(first_multiplicand_1, wire_third_multiplicand_1); + self.route_extension(first_addend, wire_third_addend); + self.route_extension(second_multiplicand_0, wire_fourth_multiplicand_0); + self.route_extension(second_multiplicand_1, wire_fourth_multiplicand_1); + self.route_extension(second_addend, wire_fourth_addend); + self.free_arithmetic = None; + + (wire_third_output, wire_fourth_output) + } + pub fn arithmetic_extension( &mut self, const_0: F, @@ -761,31 +762,6 @@ mod tests { use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::verifier::verify; - #[test] - fn test_gaga() -> Result<()> { - type F = CrandallField; - type FF = QuarticCrandallField; - const D: usize = 4; - - let config = CircuitConfig { - num_routed_wires: 64, - ..CircuitConfig::large_config() - }; - - let mut pw = PartialWitness::new(config.num_wires); - let mut builder = CircuitBuilder::::new(config); - - let n = 6; - let vs = FF::rand_vec(n); - let ts = builder.add_virtual_extension_targets(n); - pw.set_extension_targets(&ts, &vs); - let mul0 = builder.mul_many_extension(&ts); - let data = builder.build(); - let proof = data.prove(pw)?; - - verify(proof, &data.verifier_only, &data.common) - } - #[test] fn test_mul_many() -> Result<()> { type F = CrandallField; @@ -823,34 +799,6 @@ mod tests { verify(proof, &data.verifier_only, &data.common) } - #[test] - fn test_mul() -> Result<()> { - type F = CrandallField; - type FF = QuarticCrandallField; - const D: usize = 4; - - let config = CircuitConfig::large_config(); - - let pw = PartialWitness::new(config.num_wires); - let mut builder = CircuitBuilder::::new(config); - - let x = FF::ONE; - let y = FF::TWO; - let z = x * y; - let xt = builder.constant_extension(x); - let yt = builder.constant_extension(y); - let zt = builder.constant_extension(z); - let comp_zt = builder.mul_extension(xt, yt); - builder.add_marked(zt.into(), "yo"); - builder.add_marked(comp_zt.into(), "ya"); - builder.assert_equal_extension(zt, comp_zt); - - let data = builder.build(); - let proof = data.prove(pw)?; - - verify(proof, &data.verifier_only, &data.common) - } - #[test] fn test_div_extension() -> Result<()> { type F = CrandallField; diff --git a/src/gadgets/interpolation.rs b/src/gadgets/interpolation.rs index dd8a1334..92090d90 100644 --- a/src/gadgets/interpolation.rs +++ b/src/gadgets/interpolation.rs @@ -12,10 +12,9 @@ impl, const D: usize> CircuitBuilder { interpolation_points: [(ExtensionTarget, ExtensionTarget); 2], evaluation_point: ExtensionTarget, ) -> ExtensionTarget { - // a0 -> a1 : zeta -> precomp0 - // b0 -> b1 : g*zeta -> precomp1 + // a0 -> a1 + // b0 -> b1 // x -> a1 + (x-a0)*(b1-a1)/(b0-a0) - // x -> precomp0 + (x-zeta)*(precomp1-precomp0)/(g*zeta - zeta) let (x_m_a0, b1_m_a1) = self.sub_two_extension( evaluation_point, diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 955fb98b..bae4b5d6 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -39,7 +39,7 @@ pub struct CircuitBuilder, const D: usize> { gates: HashSet>, /// The concrete placement of each gate. - pub gate_instances: Vec>, + gate_instances: Vec>, /// Targets to be made public. public_inputs: Vec, diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 71743b4d..0d66daa8 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -68,26 +68,6 @@ pub(crate) fn prove, const D: usize>( partial_witness.full_witness(degree, num_wires) ); - // { - // let mut count = 0; - // let mut count_bad = 0; - // for i in 0..degree { - // if prover_data.gate_instances[i].gate_ref.0.id() - // != "ArithmeticExtensionGate".to_string() - // { - // continue; - // } - // count += 1; - // let row = witness.wire_values.iter().map(|c| c[i]).collect::>(); - // // println!("{} {:?}", i, &row); - // if row[16..].iter().all(|x| x.is_zero()) { - // println!("{} {:?}", i, row); - // count_bad += 1; - // } - // } - // println!("{} {}", count, count_bad); - // } - let wires_values: Vec> = timed!( timing, "compute wire polynomials", diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 62b8f888..e4b51f08 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -435,7 +435,7 @@ mod tests { fri_config: FriConfig { proof_of_work_bits: 1, reduction_arity_bits: vec![3, 3, 3], - num_query_rounds: 33, + num_query_rounds: 32, cap_height: 3, }, }; diff --git a/src/util/reducing.rs b/src/util/reducing.rs index 7e19f9d7..a4fc97b3 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -165,89 +165,54 @@ impl ReducingFactorTarget { where F: Extendable, { - let max_coeffs_len = ReducingExtGate::::max_coeffs_len( - builder.config.num_wires, - builder.config.num_routed_wires, - ); - self.count += terms.len() as u64; - let zero_ext = builder.zero_extension(); - let mut acc = zero_ext; - let mut reversed_terms = terms.to_vec(); - while reversed_terms.len() % max_coeffs_len != 0 { - reversed_terms.push(zero_ext); + let zero = builder.zero_extension(); + let l = terms.len(); + self.count += l as u64; + + let mut terms_vec = terms.to_vec(); + // If needed, we pad the original vector so that it has even length. + if terms_vec.len().is_odd() { + terms_vec.push(zero); } - reversed_terms.reverse(); - for chunk in reversed_terms.chunks_exact(max_coeffs_len) { - let gate = ReducingExtGate::new(max_coeffs_len); - let gate_index = builder.add_gate(gate.clone(), Vec::new()); + terms_vec.reverse(); - builder.route_extension( - self.base, - ExtensionTarget::from_range(gate_index, ReducingGate::::wires_alpha()), - ); - builder.route_extension( - acc, - ExtensionTarget::from_range(gate_index, ReducingGate::::wires_old_acc()), - ); - for (i, &t) in chunk.iter().enumerate() { - builder.route_extension( - t, - ExtensionTarget::from_range(gate_index, ReducingExtGate::::wires_coeff(i)), - ); - } + let mut acc = zero; + for pair in terms_vec.chunks(2) { + // We will route the output of the first arithmetic operation to the multiplicand of the + // second, i.e. we compute the following: + // out_0 = alpha acc + pair[0] + // acc' = out_1 = alpha out_0 + pair[1] - acc = ExtensionTarget::from_range(gate_index, ReducingGate::::wires_output()); + let (gate, range) = if let Some((g, c_0, c_1)) = builder.free_arithmetic { + if c_0 == F::ONE && c_1 == F::ONE { + (g, ArithmeticExtensionGate::::wires_third_output()) + } else { + ( + builder.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + } + } else { + ( + builder.num_gates(), + ArithmeticExtensionGate::::wires_first_output(), + ) + }; + let out_0 = ExtensionTarget::from_range(gate, range); + acc = builder + .double_arithmetic_extension( + F::ONE, + F::ONE, + self.base, + acc, + pair[0], + self.base, + out_0, + pair[1], + ) + .1; } - acc - // let zero = builder.zero_extension(); - // let l = terms.len(); - // self.count += l as u64; - // - // let mut terms_vec = terms.to_vec(); - // // If needed, we pad the original vector so that it has even length. - // if terms_vec.len().is_odd() { - // terms_vec.push(zero); - // } - // terms_vec.reverse(); - // - // let mut acc = zero; - // for pair in terms_vec.chunks(2) { - // // We will route the output of the first arithmetic operation to the multiplicand of the - // // second, i.e. we compute the following: - // // out_0 = alpha acc + pair[0] - // // acc' = out_1 = alpha out_0 + pair[1] - // - // let (gate, range) = if let Some((g, c_0, c_1)) = builder.free_arithmetic { - // if c_0 == F::ONE && c_1 == F::ONE { - // (g, ArithmeticExtensionGate::::wires_third_output()) - // } else { - // ( - // builder.num_gates(), - // ArithmeticExtensionGate::::wires_first_output(), - // ) - // } - // } else { - // ( - // builder.num_gates(), - // ArithmeticExtensionGate::::wires_first_output(), - // ) - // }; - // let out_0 = ExtensionTarget::from_range(gate, range); - // acc = builder - // .double_arithmetic_extension( - // F::ONE, - // F::ONE, - // self.base, - // acc, - // pair[0], - // self.base, - // out_0, - // pair[1], - // ) - // .1; - // } - // acc } pub fn shift( @@ -360,9 +325,6 @@ mod tests { builder.assert_equal_extension(manual_reduce, circuit_reduce); - for g in &builder.gate_instances { - println!("{}", g.gate_ref.0.id()); - } let data = builder.build(); let proof = data.prove(pw)?; @@ -374,11 +336,6 @@ mod tests { test_reduce_gadget(10) } - #[test] - fn test_yo() -> Result<()> { - test_reduce_gadget(100) - } - #[test] fn test_reduce_gadget_odd() -> Result<()> { test_reduce_gadget(11) From bb548fe1485b399611db8db42ccae70ef00a18df Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 20:31:04 +0200 Subject: [PATCH 11/17] More cleaning --- src/gadgets/arithmetic_extension.rs | 3 - src/gates/mod.rs | 1 - src/gates/reducing_ext.rs | 217 ---------------------------- src/util/reducing.rs | 1 - 4 files changed, 222 deletions(-) delete mode 100644 src/gates/reducing_ext.rs diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index c762aa17..cf1bc82b 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -496,9 +496,6 @@ impl, const D: usize> CircuitBuilder { ) }; let first_out = ExtensionTarget::from_range(gate, range); - // let gate = self.num_gates(); - // let first_out = - // ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_first_output()); self.double_arithmetic_extension(F::ONE, F::ONE, a, b, zero, c, first_out, zero) .1 } diff --git a/src/gates/mod.rs b/src/gates/mod.rs index 24cf8159..dcb96b96 100644 --- a/src/gates/mod.rs +++ b/src/gates/mod.rs @@ -14,7 +14,6 @@ pub(crate) mod noop; pub(crate) mod public_input; pub mod random_access; pub mod reducing; -pub mod reducing_ext; #[cfg(test)] mod gate_testing; diff --git a/src/gates/reducing_ext.rs b/src/gates/reducing_ext.rs deleted file mode 100644 index fc83d17d..00000000 --- a/src/gates/reducing_ext.rs +++ /dev/null @@ -1,217 +0,0 @@ -use std::ops::Range; - -use crate::field::extension_field::target::ExtensionTarget; -use crate::field::extension_field::Extendable; -use crate::field::extension_field::FieldExtension; -use crate::gates::gate::Gate; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; -use crate::iop::target::Target; -use crate::iop::witness::PartialWitness; -use crate::plonk::circuit_builder::CircuitBuilder; -use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; - -/// Computes `sum alpha^i c_i` for a vector `c_i` of `num_coeffs` elements of the extension field. -#[derive(Debug, Clone)] -pub struct ReducingExtGate { - pub num_coeffs: usize, -} - -impl ReducingExtGate { - pub fn new(num_coeffs: usize) -> Self { - Self { num_coeffs } - } - - pub fn max_coeffs_len(num_wires: usize, num_routed_wires: usize) -> usize { - ((num_routed_wires - 3 * D) / D).min((num_wires - 2 * D) / (D * 2)) - } - - pub fn wires_output() -> Range { - 0..D - } - pub fn wires_alpha() -> Range { - D..2 * D - } - pub fn wires_old_acc() -> Range { - 2 * D..3 * D - } - const START_COEFFS: usize = 3 * D; - pub fn wires_coeff(i: usize) -> Range { - Self::START_COEFFS + i * D..Self::START_COEFFS + (i + 1) * D - } - fn start_accs(&self) -> usize { - Self::START_COEFFS + self.num_coeffs * D - } - fn wires_accs(&self, i: usize) -> Range { - if i == self.num_coeffs - 1 { - // The last accumulator is the output. - return Self::wires_output(); - } - self.start_accs() + D * i..self.start_accs() + D * (i + 1) - } -} - -impl, const D: usize> Gate for ReducingExtGate { - fn id(&self) -> String { - format!("{:?}", self) - } - - fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let alpha = vars.get_local_ext_algebra(Self::wires_alpha()); - let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc()); - let coeffs = (0..self.num_coeffs) - .map(|i| vars.get_local_ext_algebra(Self::wires_coeff(i))) - .collect::>(); - let accs = (0..self.num_coeffs) - .map(|i| vars.get_local_ext_algebra(self.wires_accs(i))) - .collect::>(); - - let mut constraints = Vec::with_capacity(>::num_constraints(self)); - let mut acc = old_acc; - for i in 0..self.num_coeffs { - constraints.push(acc * alpha + coeffs[i] - accs[i]); - acc = accs[i]; - } - - constraints - .into_iter() - .flat_map(|alg| alg.to_basefield_array()) - .collect() - } - - fn eval_unfiltered_base(&self, vars: EvaluationVarsBase) -> Vec { - let alpha = vars.get_local_ext(Self::wires_alpha()); - let old_acc = vars.get_local_ext(Self::wires_old_acc()); - let coeffs = (0..self.num_coeffs) - .map(|i| vars.get_local_ext(Self::wires_coeff(i))) - .collect::>(); - let accs = (0..self.num_coeffs) - .map(|i| vars.get_local_ext(self.wires_accs(i))) - .collect::>(); - - let mut constraints = Vec::with_capacity(>::num_constraints(self)); - let mut acc = old_acc; - for i in 0..self.num_coeffs { - constraints.extend((acc * alpha + coeffs[i] - accs[i]).to_basefield_array()); - acc = accs[i]; - } - - constraints - } - - fn eval_unfiltered_recursively( - &self, - builder: &mut CircuitBuilder, - vars: EvaluationTargets, - ) -> Vec> { - let alpha = vars.get_local_ext_algebra(Self::wires_alpha()); - let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc()); - let coeffs = (0..self.num_coeffs) - .map(|i| vars.get_local_ext_algebra(Self::wires_coeff(i))) - .collect::>(); - let accs = (0..self.num_coeffs) - .map(|i| vars.get_local_ext_algebra(self.wires_accs(i))) - .collect::>(); - - let mut constraints = Vec::with_capacity(>::num_constraints(self)); - let mut acc = old_acc; - for i in 0..self.num_coeffs { - let coeff = coeffs[i]; - let mut tmp = builder.mul_add_ext_algebra(acc, alpha, coeff); - tmp = builder.sub_ext_algebra(tmp, accs[i]); - constraints.push(tmp); - acc = accs[i]; - } - - constraints - .into_iter() - .flat_map(|alg| alg.to_ext_target_array()) - .collect() - } - - fn generators( - &self, - gate_index: usize, - _local_constants: &[F], - ) -> Vec>> { - vec![Box::new(ReducingGenerator { - gate_index, - gate: self.clone(), - })] - } - - fn num_wires(&self) -> usize { - 2 * D + 2 * D * self.num_coeffs - } - - fn num_constants(&self) -> usize { - 0 - } - - fn degree(&self) -> usize { - 2 - } - - fn num_constraints(&self) -> usize { - D * self.num_coeffs - } -} - -struct ReducingGenerator { - gate_index: usize, - gate: ReducingExtGate, -} - -impl, const D: usize> SimpleGenerator for ReducingGenerator { - fn dependencies(&self) -> Vec { - ReducingExtGate::::wires_alpha() - .chain(ReducingExtGate::::wires_old_acc()) - .chain((0..self.gate.num_coeffs).flat_map(|i| ReducingExtGate::::wires_coeff(i))) - .map(|i| Target::wire(self.gate_index, i)) - .collect() - } - - fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { - let extract_extension = |range: Range| -> F::Extension { - let t = ExtensionTarget::from_range(self.gate_index, range); - witness.get_extension_target(t) - }; - - let alpha = extract_extension(ReducingExtGate::::wires_alpha()); - let old_acc = extract_extension(ReducingExtGate::::wires_old_acc()); - let coeffs = (0..self.gate.num_coeffs) - .map(|i| extract_extension(ReducingExtGate::::wires_coeff(i))) - .collect::>(); - let accs = (0..self.gate.num_coeffs) - .map(|i| ExtensionTarget::from_range(self.gate_index, self.gate.wires_accs(i))) - .collect::>(); - let output = - ExtensionTarget::from_range(self.gate_index, ReducingExtGate::::wires_output()); - - let mut acc = old_acc; - for i in 0..self.gate.num_coeffs { - let computed_acc = acc * alpha + coeffs[i]; - out_buffer.set_extension_target(accs[i], computed_acc); - acc = computed_acc; - } - out_buffer.set_extension_target(output, acc); - } -} - -#[cfg(test)] -mod tests { - use anyhow::Result; - - use crate::field::crandall_field::CrandallField; - use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; - use crate::gates::reducing_ext::ReducingExtGate; - - #[test] - fn low_degree() { - test_low_degree::(ReducingExtGate::new(22)); - } - - #[test] - fn eval_fns() -> Result<()> { - test_eval_fns::(ReducingExtGate::new(22)) - } -} diff --git a/src/util/reducing.rs b/src/util/reducing.rs index a4fc97b3..228795f6 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -7,7 +7,6 @@ use crate::field::extension_field::{Extendable, Frobenius}; use crate::field::field_types::Field; use crate::gates::arithmetic::ArithmeticExtensionGate; use crate::gates::reducing::ReducingGate; -use crate::gates::reducing_ext::ReducingExtGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::polynomial::polynomial::PolynomialCoeffs; From 630b7f22813262f48b76fb474f542eddb4a7db18 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 13 Aug 2021 22:42:22 +0200 Subject: [PATCH 12/17] Smaller parameters --- src/plonk/recursive_verifier.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index e4b51f08..64846567 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -428,14 +428,14 @@ mod tests { num_wires: 126, num_routed_wires: 64, security_bits: 128, - rate_bits: 4, + rate_bits: 3, num_challenges: 3, zero_knowledge: false, cap_height: 3, fri_config: FriConfig { - proof_of_work_bits: 1, + proof_of_work_bits: 20, reduction_arity_bits: vec![3, 3, 3], - num_query_rounds: 32, + num_query_rounds: 27, cap_height: 3, }, }; From b366482866cb7264523331c077b0b2db30338070 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 16 Aug 2021 10:18:10 +0200 Subject: [PATCH 13/17] The mother of all arithmetic optimizations --- src/fri/recursive_verifier.rs | 51 ++--- src/gadgets/arithmetic.rs | 10 - src/gadgets/arithmetic_extension.rs | 311 +++++----------------------- src/gadgets/interpolation.rs | 58 ------ src/gadgets/select.rs | 21 +- src/gates/arithmetic.rs | 256 +++++++---------------- src/gates/gmimc.rs | 14 +- src/plonk/circuit_builder.rs | 6 +- src/plonk/recursive_verifier.rs | 4 +- src/plonk/vanishing_poly.rs | 13 +- src/util/reducing.rs | 58 +----- 11 files changed, 157 insertions(+), 645 deletions(-) diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index c9f15aec..2784ceef 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -41,23 +41,14 @@ impl, const D: usize> CircuitBuilder { let coset_start = self.mul(start, x); // The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta. - let g_powers = g + let points = g .powers() - .take(arity) - .map(|y| self.constant(y)) + .zip(evals) + .map(|(y, v)| { + let yc = self.constant(y); + (self.mul(coset_start, yc), v) + }) .collect::>(); - let mut coset = Vec::new(); - for i in 0..arity / 2 { - let res = self.mul_two( - coset_start, - g_powers[2 * i], - coset_start, - g_powers[2 * i + 1], - ); - coset.push(res.0); - coset.push(res.1); - } - let points = coset.into_iter().zip(evals).collect::>(); self.interpolate(&points, beta) } @@ -265,14 +256,11 @@ impl, const D: usize> CircuitBuilder { precomputed_reduced_evals.slope, precomputed_reduced_evals.zs, ); - let (zs_numerator, vanish_zeta_right) = self.sub_two_extension( - zs_composition_eval, - interpol_val, - subgroup_x, - precomputed_reduced_evals.zeta_right, - ); - let (mut sum, zs_denominator) = - alpha.shift_and_mul(sum, vanish_zeta, vanish_zeta_right, self); + let zs_numerator = self.sub_extension(zs_composition_eval, interpol_val); + let vanish_zeta_right = + self.sub_extension(subgroup_x, precomputed_reduced_evals.zeta_right); + sum = alpha.shift(sum, self); + let zs_denominator = self.mul_extension(vanish_zeta, vanish_zeta_right); sum = self.div_add_extension(zs_numerator, zs_denominator, sum); sum @@ -319,17 +307,9 @@ impl, const D: usize> CircuitBuilder { let phi_ext = self.convert_to_ext(phi); let zero = self.zero_extension(); // `subgroup_x = g*phi, vanish_zeta = g*phi - zeta` - let tmp = self.double_arithmetic_extension( - F::ONE, - F::NEG_ONE, - g_ext, - phi_ext, - zero, - g_ext, - phi_ext, - zeta, - ); - (tmp.0 .0[0], tmp.1) + let subgroup_x = self.mul(g, phi); + let vanish_zeta = self.mul_sub_extension(g_ext, phi_ext, zeta); + (subgroup_x, vanish_zeta) }); // old_eval is the last derived evaluation; it will be checked for consistency with its @@ -440,7 +420,8 @@ impl PrecomputedReducedEvalsTarget { let g = builder.constant_extension(F::Extension::primitive_root_of_unity(degree_log)); let zeta_right = builder.mul_extension(g, zeta); - let (numerator, denominator) = builder.sub_two_extension(zs_right, zs, zeta_right, zeta); + let numerator = builder.sub_extension(zs_right, zs); + let denominator = builder.sub_extension(zeta_right, zeta); Self { single, diff --git a/src/gadgets/arithmetic.rs b/src/gadgets/arithmetic.rs index 2c41482e..52b1d660 100644 --- a/src/gadgets/arithmetic.rs +++ b/src/gadgets/arithmetic.rs @@ -86,16 +86,6 @@ impl, const D: usize> CircuitBuilder { self.arithmetic(F::ONE, x, y, F::ZERO, x) } - /// Computes `x * y`. - pub fn mul_two(&mut self, a0: Target, b0: Target, a1: Target, b1: Target) -> (Target, Target) { - let a0_ext = self.convert_to_ext(a0); - let b0_ext = self.convert_to_ext(b0); - let a1_ext = self.convert_to_ext(a1); - let b1_ext = self.convert_to_ext(b1); - let res = self.mul_two_extension(a0_ext, b0_ext, a1_ext, b1_ext); - (res.0 .0[0], res.1 .0[0]) - } - /// Multiply `n` `Target`s with `ceil(n/2) + 1` `ArithmeticExtensionGate`s. pub fn mul_many(&mut self, terms: &[Target]) -> Target { let terms_ext = terms diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index 127600a1..a27da240 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -6,7 +6,7 @@ use num::Integer; use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; use crate::field::extension_field::{Extendable, OEF}; use crate::field::field_types::Field; -use crate::gates::arithmetic::ArithmeticExtensionGate; +use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; use crate::iop::wire::Wire; @@ -15,111 +15,25 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; impl, const D: usize> CircuitBuilder { - pub fn double_arithmetic_extension( - &mut self, - const_0: F, - const_1: F, - first_multiplicand_0: ExtensionTarget, - first_multiplicand_1: ExtensionTarget, - first_addend: ExtensionTarget, - second_multiplicand_0: ExtensionTarget, - second_multiplicand_1: ExtensionTarget, - second_addend: ExtensionTarget, - ) -> (ExtensionTarget, ExtensionTarget) { - if let Some((g, c_0, c_1)) = self.free_arithmetic { - if c_0 == const_0 && c_1 == const_1 { - return self.arithmetic_reusing_gate( - g, - first_multiplicand_0, - first_multiplicand_1, - first_addend, - second_multiplicand_0, - second_multiplicand_1, - second_addend, - ); - } + fn find_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) { + let (gate, i) = self + .free_arithmetic + .get(&(const_0, const_1)) + .copied() + .unwrap_or_else(|| { + let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]); + (gate, 0) + }); + + // Update `free_arithmetic` with new values. + if i < NUM_ARITHMETIC_OPS - 1 { + self.free_arithmetic + .insert((const_0, const_1), (gate, i + 1)); + } else { + self.free_arithmetic.remove(&(const_0, const_1)); } - let gate = self.add_gate(ArithmeticExtensionGate, vec![const_0, const_1]); - self.free_arithmetic = Some((gate, const_0, const_1)); - let wire_first_multiplicand_0 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_first_multiplicand_0(), - ); - let wire_first_multiplicand_1 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_first_multiplicand_1(), - ); - let wire_first_addend = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_first_addend()); - let wire_second_multiplicand_0 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_second_multiplicand_0(), - ); - let wire_second_multiplicand_1 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_second_multiplicand_1(), - ); - let wire_second_addend = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_second_addend()); - let wire_first_output = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_first_output()); - let wire_second_output = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_second_output()); - - self.route_extension(first_multiplicand_0, wire_first_multiplicand_0); - self.route_extension(first_multiplicand_1, wire_first_multiplicand_1); - self.route_extension(first_addend, wire_first_addend); - self.route_extension(second_multiplicand_0, wire_second_multiplicand_0); - self.route_extension(second_multiplicand_1, wire_second_multiplicand_1); - self.route_extension(second_addend, wire_second_addend); - (wire_first_output, wire_second_output) - } - - fn arithmetic_reusing_gate( - &mut self, - gate: usize, - first_multiplicand_0: ExtensionTarget, - first_multiplicand_1: ExtensionTarget, - first_addend: ExtensionTarget, - second_multiplicand_0: ExtensionTarget, - second_multiplicand_1: ExtensionTarget, - second_addend: ExtensionTarget, - ) -> (ExtensionTarget, ExtensionTarget) { - let wire_third_multiplicand_0 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_third_multiplicand_0(), - ); - let wire_third_multiplicand_1 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_third_multiplicand_1(), - ); - let wire_third_addend = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_addend()); - let wire_fourth_multiplicand_0 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_fourth_multiplicand_0(), - ); - let wire_fourth_multiplicand_1 = ExtensionTarget::from_range( - gate, - ArithmeticExtensionGate::::wires_fourth_multiplicand_1(), - ); - let wire_fourth_addend = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_addend()); - let wire_third_output = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_third_output()); - let wire_fourth_output = - ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_fourth_output()); - - self.route_extension(first_multiplicand_0, wire_third_multiplicand_0); - self.route_extension(first_multiplicand_1, wire_third_multiplicand_1); - self.route_extension(first_addend, wire_third_addend); - self.route_extension(second_multiplicand_0, wire_fourth_multiplicand_0); - self.route_extension(second_multiplicand_1, wire_fourth_multiplicand_1); - self.route_extension(second_addend, wire_fourth_addend); - self.free_arithmetic = None; - - (wire_third_output, wire_fourth_output) + (gate, i) } pub fn arithmetic_extension( @@ -141,18 +55,23 @@ impl, const D: usize> CircuitBuilder { return result; } - let zero = self.zero_extension(); - self.double_arithmetic_extension( - const_0, - const_1, - multiplicand_0, - multiplicand_1, - addend, - zero, - zero, - zero, - ) - .0 + let (gate, i) = self.find_arithmetic_gate(const_0, const_1); + let wires_multiplicand_0 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_ith_multiplicand_0(i), + ); + let wires_multiplicand_1 = ExtensionTarget::from_range( + gate, + ArithmeticExtensionGate::::wires_ith_multiplicand_1(i), + ); + let wires_addend = + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_ith_addend(i)); + + self.route_extension(multiplicand_0, wires_multiplicand_0); + self.route_extension(multiplicand_1, wires_multiplicand_1); + self.route_extension(addend, wires_addend); + + ExtensionTarget::from_range(gate, ArithmeticExtensionGate::::wires_ith_output(i)) } /// Checks for special cases where the value of @@ -233,37 +152,8 @@ impl, const D: usize> CircuitBuilder { pairs: Vec<(ExtensionTarget, ExtensionTarget)>, ) -> ExtensionTarget { let mut acc = starting_acc; - for chunk in pairs.chunks_exact(2) { - let (a0, b0) = chunk[0]; - let (a1, b1) = chunk[1]; - let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { - if c_0 == constant && c_1 == F::ONE { - (g, ArithmeticExtensionGate::::wires_third_output()) - } else { - ( - self.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - } - } else { - ( - self.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - }; - let first_out = ExtensionTarget::from_range(gate, range); - // let gate = self.num_gates(); - // let first_out = ExtensionTarget::from_range( - // gate, - // ArithmeticExtensionGate::::wires_first_output(), - // ); - acc = self - .double_arithmetic_extension(constant, F::ONE, a0, b0, acc, a1, b1, first_out) - .1; - } - if pairs.len().is_odd() { - let n = pairs.len() - 1; - acc = self.arithmetic_extension(constant, F::ONE, pairs[n].0, pairs[n].1, acc); + for (a, b) in pairs { + acc = self.arithmetic_extension(constant, F::ONE, a, b, acc); } acc } @@ -277,38 +167,15 @@ impl, const D: usize> CircuitBuilder { self.arithmetic_extension(F::ONE, F::ONE, one, a, b) } - /// Returns `(a0+b0, a1+b1)`. - pub fn add_two_extension( - &mut self, - a0: ExtensionTarget, - b0: ExtensionTarget, - a1: ExtensionTarget, - b1: ExtensionTarget, - ) -> (ExtensionTarget, ExtensionTarget) { - let one = self.one_extension(); - self.double_arithmetic_extension(F::ONE, F::ONE, one, a0, b0, one, a1, b1) - } - pub fn add_ext_algebra( &mut self, - a: ExtensionAlgebraTarget, + mut a: ExtensionAlgebraTarget, b: ExtensionAlgebraTarget, ) -> ExtensionAlgebraTarget { - // We run two additions in parallel. So `[a0,a1,a2,a3] + [b0,b1,b2,b3]` is computed with two - // `add_two_extension`, first `[a0,a1]+[b0,b1]` then `[a2,a3]+[b2,b3]`. - let mut res = Vec::with_capacity(D); - // We need some extra logic if D is odd. - let d_even = D & (D ^ 1); // = 2 * (D/2) - for mut chunk in &(0..d_even).chunks(2) { - let i = chunk.next().unwrap(); - let j = chunk.next().unwrap(); - let (o0, o1) = self.add_two_extension(a.0[i], b.0[i], a.0[j], b.0[j]); - res.extend([o0, o1]); + for i in 0..D { + a.0[i] = self.add_extension(a.0[i], b.0[i]); } - if D.is_odd() { - res.push(self.add_extension(a.0[D - 1], b.0[D - 1])); - } - ExtensionAlgebraTarget(res.try_into().unwrap()) + a } /// Add 3 `ExtensionTarget`s with 1 `ArithmeticExtensionGate`s. @@ -351,35 +218,15 @@ impl, const D: usize> CircuitBuilder { self.arithmetic_extension(F::ONE, F::NEG_ONE, one, a, b) } - pub fn sub_two_extension( - &mut self, - a0: ExtensionTarget, - b0: ExtensionTarget, - a1: ExtensionTarget, - b1: ExtensionTarget, - ) -> (ExtensionTarget, ExtensionTarget) { - let one = self.one_extension(); - self.double_arithmetic_extension(F::ONE, F::NEG_ONE, one, a0, b0, one, a1, b1) - } - pub fn sub_ext_algebra( &mut self, - a: ExtensionAlgebraTarget, + mut a: ExtensionAlgebraTarget, b: ExtensionAlgebraTarget, ) -> ExtensionAlgebraTarget { - // See `add_ext_algebra`. - let mut res = Vec::with_capacity(D); - let d_even = D & (D ^ 1); // = 2 * (D/2) - for mut chunk in &(0..d_even).chunks(2) { - let i = chunk.next().unwrap(); - let j = chunk.next().unwrap(); - let (o0, o1) = self.sub_two_extension(a.0[i], b.0[i], a.0[j], b.0[j]); - res.extend([o0, o1]); + for i in 0..D { + a.0[i] = self.sub_extension(a.0[i], b.0[i]); } - if D.is_odd() { - res.push(self.sub_extension(a.0[D - 1], b.0[D - 1])); - } - ExtensionAlgebraTarget(res.try_into().unwrap()) + a } pub fn mul_extension_with_const( @@ -389,17 +236,7 @@ impl, const D: usize> CircuitBuilder { multiplicand_1: ExtensionTarget, ) -> ExtensionTarget { let zero = self.zero_extension(); - self.double_arithmetic_extension( - const_0, - F::ZERO, - multiplicand_0, - multiplicand_1, - zero, - zero, - zero, - zero, - ) - .0 + self.arithmetic_extension(const_0, F::ZERO, multiplicand_0, multiplicand_1, zero) } pub fn mul_extension( @@ -410,18 +247,6 @@ impl, const D: usize> CircuitBuilder { self.mul_extension_with_const(F::ONE, multiplicand_0, multiplicand_1) } - /// Returns `(a0*b0, a1*b1)`. - pub fn mul_two_extension( - &mut self, - a0: ExtensionTarget, - b0: ExtensionTarget, - a1: ExtensionTarget, - b1: ExtensionTarget, - ) -> (ExtensionTarget, ExtensionTarget) { - let zero = self.zero_extension(); - self.double_arithmetic_extension(F::ONE, F::ZERO, a0, b0, zero, a1, b1, zero) - } - /// Computes `x^2`. pub fn square_extension(&mut self, x: ExtensionTarget) -> ExtensionTarget { self.mul_extension(x, x) @@ -479,25 +304,8 @@ impl, const D: usize> CircuitBuilder { b: ExtensionTarget, c: ExtensionTarget, ) -> ExtensionTarget { - let zero = self.zero_extension(); - let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { - if c_0 == F::ONE && c_1 == F::ONE { - (g, ArithmeticExtensionGate::::wires_third_output()) - } else { - ( - self.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - } - } else { - ( - self.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - }; - let first_out = ExtensionTarget::from_range(gate, range); - self.double_arithmetic_extension(F::ONE, F::ONE, a, b, zero, c, first_out, zero) - .1 + let tmp = self.mul_extension(a, b); + self.mul_extension(tmp, c) } /// Multiply `n` `ExtensionTarget`s with `n/2` `ArithmeticExtensionGate`s. @@ -574,22 +382,8 @@ impl, const D: usize> CircuitBuilder { b: ExtensionAlgebraTarget, mut c: ExtensionAlgebraTarget, ) -> ExtensionAlgebraTarget { - for i in 0..D / 2 { - let res = self.double_arithmetic_extension( - F::ONE, - F::ONE, - a, - b.0[2 * i], - c.0[2 * i], - a, - b.0[2 * i + 1], - c.0[2 * i + 1], - ); - c.0[2 * i] = res.0; - c.0[2 * i + 1] = res.1; - } - if D.is_odd() { - c.0[D - 1] = self.arithmetic_extension(F::ONE, F::ONE, a, b.0[D - 1], c.0[D - 1]); + for i in 0..D { + c.0[i] = self.mul_add_extension(a, b.0[i], c.0[i]); } c } @@ -670,11 +464,10 @@ impl, const D: usize> CircuitBuilder { }); // Enforce that x times its purported inverse equals 1. - let (y_inv, res) = - self.double_arithmetic_extension(F::ONE, F::ONE, y, inv, zero, x, inv, z); + let y_inv = self.mul_extension(y, inv); self.assert_equal_extension(y_inv, one); - res + self.mul_add_extension(x, inv, z) } /// Computes `1 / x`. Results in an unsatisfiable instance if `x = 0`. diff --git a/src/gadgets/interpolation.rs b/src/gadgets/interpolation.rs index 9d48a204..6db70b6e 100644 --- a/src/gadgets/interpolation.rs +++ b/src/gadgets/interpolation.rs @@ -5,29 +5,6 @@ use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; impl, const D: usize> CircuitBuilder { - /// Interpolate two points. No need for an `InterpolationGate` since the coefficients - /// of the linear interpolation polynomial can be easily computed with arithmetic operations. - pub fn interpolate2( - &mut self, - interpolation_points: [(ExtensionTarget, ExtensionTarget); 2], - evaluation_point: ExtensionTarget, - ) -> ExtensionTarget { - // a0 -> a1 - // b0 -> b1 - // x -> a1 + (x-a0)*(b1-a1)/(b0-a0) - - let (x_m_a0, b1_m_a1) = self.sub_two_extension( - evaluation_point, - interpolation_points[0].0, - interpolation_points[1].1, - interpolation_points[0].1, - ); - let b0_m_a0 = self.sub_extension(interpolation_points[1].0, interpolation_points[0].0); - let quotient = self.div_extension(b1_m_a1, b0_m_a0); - - self.mul_add_extension(x_m_a0, quotient, interpolation_points[0].1) - } - /// Interpolate a list of point/evaluation pairs at a given point. /// Returns the evaluation of the interpolated polynomial at `evaluation_point`. pub fn interpolate( @@ -108,39 +85,4 @@ mod tests { verify(proof, &data.verifier_only, &data.common) } - - #[test] - fn test_interpolate2() -> Result<()> { - type F = CrandallField; - type FF = QuarticCrandallField; - let config = CircuitConfig::large_zk_config(); - let pw = PartialWitness::new(config.num_wires); - let mut builder = CircuitBuilder::::new(config); - - let len = 2; - let points = (0..len) - .map(|_| (FF::rand(), FF::rand())) - .collect::>(); - - let true_interpolant = interpolant(&points); - - let z = FF::rand(); - let true_eval = true_interpolant.eval(z); - - let points_target = points - .iter() - .map(|&(p, v)| (builder.constant_extension(p), builder.constant_extension(v))) - .collect::>(); - - let zt = builder.constant_extension(z); - - let eval = builder.interpolate2(points_target.try_into().unwrap(), zt); - let true_eval_target = builder.constant_extension(true_eval); - builder.assert_equal_extension(eval, true_eval_target); - - let data = builder.build(); - let proof = data.prove(pw)?; - - verify(proof, &data.verifier_only, &data.common) - } } diff --git a/src/gadgets/select.rs b/src/gadgets/select.rs index fbfdb6e8..8591a631 100644 --- a/src/gadgets/select.rs +++ b/src/gadgets/select.rs @@ -25,25 +25,8 @@ impl, const D: usize> CircuitBuilder { x: ExtensionTarget, y: ExtensionTarget, ) -> ExtensionTarget { - // Holds `by - y`. - let (gate, range) = if let Some((g, c_0, c_1)) = self.free_arithmetic { - if c_0 == F::ONE && c_1 == F::NEG_ONE { - (g, ArithmeticExtensionGate::::wires_third_output()) - } else { - ( - self.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - } - } else { - ( - self.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - }; - let first_out = ExtensionTarget::from_range(gate, range); - self.double_arithmetic_extension(F::ONE, F::NEG_ONE, b, y, y, b, x, first_out) - .1 + let tmp = self.mul_sub_extension(b, y, y); + self.mul_sub_extension(b, x, tmp) } /// See `select_ext`. diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 7c780671..5b608519 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -10,61 +10,25 @@ use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +/// Number of arithmetic operations performed by an arithmetic gate. +pub const NUM_ARITHMETIC_OPS: usize = 4; + /// A gate which can a linear combination `c0*x*y+c1*z` twice with the same `x`. #[derive(Debug)] pub struct ArithmeticExtensionGate; impl ArithmeticExtensionGate { - pub fn wires_first_multiplicand_0() -> Range { - 0..D + pub fn wires_ith_multiplicand_0(i: usize) -> Range { + 4 * D * i..4 * D * i + D } - pub fn wires_first_multiplicand_1() -> Range { - D..2 * D + pub fn wires_ith_multiplicand_1(i: usize) -> Range { + 4 * D * i + D..4 * D * i + 2 * D } - pub fn wires_first_addend() -> Range { - 2 * D..3 * D + pub fn wires_ith_addend(i: usize) -> Range { + 4 * D * i + 2 * D..4 * D * i + 3 * D } - pub fn wires_first_output() -> Range { - 3 * D..4 * D - } - - pub fn wires_second_multiplicand_0() -> Range { - 4 * D..5 * D - } - pub fn wires_second_multiplicand_1() -> Range { - 5 * D..6 * D - } - pub fn wires_second_addend() -> Range { - 6 * D..7 * D - } - pub fn wires_second_output() -> Range { - 7 * D..8 * D - } - - pub fn wires_third_multiplicand_0() -> Range { - 8 * D..9 * D - } - pub fn wires_third_multiplicand_1() -> Range { - 9 * D..10 * D - } - pub fn wires_third_addend() -> Range { - 10 * D..11 * D - } - pub fn wires_third_output() -> Range { - 11 * D..12 * D - } - - pub fn wires_fourth_multiplicand_0() -> Range { - 12 * D..13 * D - } - pub fn wires_fourth_multiplicand_1() -> Range { - 13 * D..14 * D - } - pub fn wires_fourth_addend() -> Range { - 14 * D..15 * D - } - pub fn wires_fourth_output() -> Range { - 15 * D..16 * D + pub fn wires_ith_output(i: usize) -> Range { + 4 * D * i + 3 * D..4 * D * i + 4 * D } } @@ -77,38 +41,18 @@ impl, const D: usize> Gate for ArithmeticExtensionGate let const_0 = vars.local_constants[0]; let const_1 = vars.local_constants[1]; - let first_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_0()); - let first_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_1()); - let first_addend = vars.get_local_ext_algebra(Self::wires_first_addend()); - let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0()); - let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1()); - let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend()); - let third_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_0()); - let third_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_1()); - let third_addend = vars.get_local_ext_algebra(Self::wires_third_addend()); - let fourth_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_0()); - let fourth_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_1()); - let fourth_addend = vars.get_local_ext_algebra(Self::wires_fourth_addend()); - let first_output = vars.get_local_ext_algebra(Self::wires_first_output()); - let second_output = vars.get_local_ext_algebra(Self::wires_second_output()); - let third_output = vars.get_local_ext_algebra(Self::wires_third_output()); - let fourth_output = vars.get_local_ext_algebra(Self::wires_fourth_output()); + let mut constraints = Vec::new(); + for i in 0..NUM_ARITHMETIC_OPS { + let multiplicand_0 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_0(i)); + let multiplicand_1 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_1(i)); + let addend = vars.get_local_ext_algebra(Self::wires_ith_addend(i)); + let output = vars.get_local_ext_algebra(Self::wires_ith_output(i)); + let computed_output = + multiplicand_0 * multiplicand_1 * const_0.into() + addend * const_1.into(); - let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into() - + first_addend * const_1.into(); - let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into() - + second_addend * const_1.into(); - let third_computed_output = third_multiplicand_0 * third_multiplicand_1 * const_0.into() - + third_addend * const_1.into(); - let fourth_computed_output = fourth_multiplicand_0 * fourth_multiplicand_1 * const_0.into() - + fourth_addend * const_1.into(); + constraints.extend((output - computed_output).to_basefield_array()); + } - let mut constraints = (first_output - first_computed_output) - .to_basefield_array() - .to_vec(); - constraints.extend((second_output - second_computed_output).to_basefield_array()); - constraints.extend((third_output - third_computed_output).to_basefield_array()); - constraints.extend((fourth_output - fourth_computed_output).to_basefield_array()); constraints } @@ -116,38 +60,18 @@ impl, const D: usize> Gate for ArithmeticExtensionGate let const_0 = vars.local_constants[0]; let const_1 = vars.local_constants[1]; - let first_multiplicand_0 = vars.get_local_ext(Self::wires_first_multiplicand_0()); - let first_multiplicand_1 = vars.get_local_ext(Self::wires_first_multiplicand_1()); - let first_addend = vars.get_local_ext(Self::wires_first_addend()); - let second_multiplicand_0 = vars.get_local_ext(Self::wires_second_multiplicand_0()); - let second_multiplicand_1 = vars.get_local_ext(Self::wires_second_multiplicand_1()); - let second_addend = vars.get_local_ext(Self::wires_second_addend()); - let third_multiplicand_0 = vars.get_local_ext(Self::wires_third_multiplicand_0()); - let third_multiplicand_1 = vars.get_local_ext(Self::wires_third_multiplicand_1()); - let third_addend = vars.get_local_ext(Self::wires_third_addend()); - let fourth_multiplicand_0 = vars.get_local_ext(Self::wires_fourth_multiplicand_0()); - let fourth_multiplicand_1 = vars.get_local_ext(Self::wires_fourth_multiplicand_1()); - let fourth_addend = vars.get_local_ext(Self::wires_fourth_addend()); - let first_output = vars.get_local_ext(Self::wires_first_output()); - let second_output = vars.get_local_ext(Self::wires_second_output()); - let third_output = vars.get_local_ext(Self::wires_third_output()); - let fourth_output = vars.get_local_ext(Self::wires_fourth_output()); + let mut constraints = Vec::new(); + for i in 0..NUM_ARITHMETIC_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 addend = vars.get_local_ext(Self::wires_ith_addend(i)); + let output = vars.get_local_ext(Self::wires_ith_output(i)); + let computed_output = + multiplicand_0 * multiplicand_1 * const_0.into() + addend * const_1.into(); - let first_computed_output = first_multiplicand_0 * first_multiplicand_1 * const_0.into() - + first_addend * const_1.into(); - let second_computed_output = second_multiplicand_0 * second_multiplicand_1 * const_0.into() - + second_addend * const_1.into(); - let third_computed_output = third_multiplicand_0 * third_multiplicand_1 * const_0.into() - + third_addend * const_1.into(); - let fourth_computed_output = fourth_multiplicand_0 * fourth_multiplicand_1 * const_0.into() - + fourth_addend * const_1.into(); + constraints.extend((output - computed_output).to_basefield_array()); + } - let mut constraints = (first_output - first_computed_output) - .to_basefield_array() - .to_vec(); - constraints.extend((second_output - second_computed_output).to_basefield_array()); - constraints.extend((third_output - third_computed_output).to_basefield_array()); - constraints.extend((fourth_output - fourth_computed_output).to_basefield_array()); constraints } @@ -159,61 +83,23 @@ impl, const D: usize> Gate for ArithmeticExtensionGate let const_0 = vars.local_constants[0]; let const_1 = vars.local_constants[1]; - let first_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_0()); - let first_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_first_multiplicand_1()); - let first_addend = vars.get_local_ext_algebra(Self::wires_first_addend()); - let second_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_0()); - let second_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_second_multiplicand_1()); - let second_addend = vars.get_local_ext_algebra(Self::wires_second_addend()); - let third_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_0()); - let third_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_third_multiplicand_1()); - let third_addend = vars.get_local_ext_algebra(Self::wires_third_addend()); - let fourth_multiplicand_0 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_0()); - let fourth_multiplicand_1 = vars.get_local_ext_algebra(Self::wires_fourth_multiplicand_1()); - let fourth_addend = vars.get_local_ext_algebra(Self::wires_fourth_addend()); - let first_output = vars.get_local_ext_algebra(Self::wires_first_output()); - let second_output = vars.get_local_ext_algebra(Self::wires_second_output()); - let third_output = vars.get_local_ext_algebra(Self::wires_third_output()); - let fourth_output = vars.get_local_ext_algebra(Self::wires_fourth_output()); + let mut constraints = Vec::new(); + for i in 0..NUM_ARITHMETIC_OPS { + let multiplicand_0 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_0(i)); + let multiplicand_1 = vars.get_local_ext_algebra(Self::wires_ith_multiplicand_1(i)); + let addend = vars.get_local_ext_algebra(Self::wires_ith_addend(i)); + let output = vars.get_local_ext_algebra(Self::wires_ith_output(i)); + let computed_output = { + let mul = builder.mul_ext_algebra(multiplicand_0, multiplicand_1); + let scaled_mul = builder.scalar_mul_ext_algebra(const_0, mul); + let scaled_addend = builder.scalar_mul_ext_algebra(const_1, addend); + builder.add_ext_algebra(scaled_mul, scaled_addend) + }; - let first_computed_output = - builder.mul_ext_algebra(first_multiplicand_0, first_multiplicand_1); - let first_computed_output = builder.scalar_mul_ext_algebra(const_0, first_computed_output); - let first_scaled_addend = builder.scalar_mul_ext_algebra(const_1, first_addend); - let first_computed_output = - builder.add_ext_algebra(first_computed_output, first_scaled_addend); + let diff = builder.sub_ext_algebra(output, computed_output); + constraints.extend(diff.to_ext_target_array()); + } - let second_computed_output = - builder.mul_ext_algebra(second_multiplicand_0, second_multiplicand_1); - let second_computed_output = - builder.scalar_mul_ext_algebra(const_0, second_computed_output); - let second_scaled_addend = builder.scalar_mul_ext_algebra(const_1, second_addend); - let second_computed_output = - builder.add_ext_algebra(second_computed_output, second_scaled_addend); - - let third_computed_output = - builder.mul_ext_algebra(third_multiplicand_0, third_multiplicand_1); - let third_computed_output = builder.scalar_mul_ext_algebra(const_0, third_computed_output); - let third_scaled_addend = builder.scalar_mul_ext_algebra(const_1, third_addend); - let third_computed_output = - builder.add_ext_algebra(third_computed_output, third_scaled_addend); - - let fourth_computed_output = - builder.mul_ext_algebra(fourth_multiplicand_0, fourth_multiplicand_1); - let fourth_computed_output = - builder.scalar_mul_ext_algebra(const_0, fourth_computed_output); - let fourth_scaled_addend = builder.scalar_mul_ext_algebra(const_1, fourth_addend); - let fourth_computed_output = - builder.add_ext_algebra(fourth_computed_output, fourth_scaled_addend); - - let diff_0 = builder.sub_ext_algebra(first_output, first_computed_output); - let diff_1 = builder.sub_ext_algebra(second_output, second_computed_output); - let diff_2 = builder.sub_ext_algebra(third_output, third_computed_output); - let diff_3 = builder.sub_ext_algebra(fourth_output, fourth_computed_output); - let mut constraints = diff_0.to_ext_target_array().to_vec(); - constraints.extend(diff_1.to_ext_target_array()); - constraints.extend(diff_2.to_ext_target_array()); - constraints.extend(diff_3.to_ext_target_array()); constraints } @@ -222,24 +108,21 @@ impl, const D: usize> Gate for ArithmeticExtensionGate gate_index: usize, local_constants: &[F], ) -> Vec>> { - let gens = (0..4) - .map(|i| ArithmeticExtensionGenerator { - gate_index, - const_0: local_constants[0], - const_1: local_constants[1], - i, + (0..4) + .map(|i| { + let g: Box> = Box::new(ArithmeticExtensionGenerator { + gate_index, + const_0: local_constants[0], + const_1: local_constants[1], + i, + }); + g }) - .collect::>(); - vec![ - Box::new(gens[0].clone()), - Box::new(gens[1].clone()), - Box::new(gens[2].clone()), - Box::new(gens[3].clone()), - ] + .collect::>() } fn num_wires(&self) -> usize { - 16 * D + NUM_ARITHMETIC_OPS * 4 * D } fn num_constants(&self) -> usize { @@ -251,7 +134,7 @@ impl, const D: usize> Gate for ArithmeticExtensionGate } fn num_constraints(&self) -> usize { - 4 * D + NUM_ARITHMETIC_OPS * D } } @@ -265,7 +148,11 @@ struct ArithmeticExtensionGenerator, const D: usize> { impl, const D: usize> SimpleGenerator for ArithmeticExtensionGenerator { fn dependencies(&self) -> Vec { - (4 * self.i * D..(4 * self.i + 3) * D) + ArithmeticExtensionGate::::wires_ith_multiplicand_0(self.i) + .chain(ArithmeticExtensionGate::::wires_ith_multiplicand_1( + self.i, + )) + .chain(ArithmeticExtensionGate::::wires_ith_addend(self.i)) .map(|i| Target::wire(self.gate_index, i)) .collect() } @@ -276,13 +163,18 @@ impl, const D: usize> SimpleGenerator for ArithmeticExtensio witness.get_extension_target(t) }; - let start = 4 * self.i * D; - let multiplicand_0 = extract_extension(start..start + D); - let multiplicand_1 = extract_extension(start + D..start + 2 * D); - let addend = extract_extension(start + 2 * D..start + 3 * D); + let multiplicand_0 = extract_extension( + ArithmeticExtensionGate::::wires_ith_multiplicand_0(self.i), + ); + let multiplicand_1 = extract_extension( + ArithmeticExtensionGate::::wires_ith_multiplicand_1(self.i), + ); + let addend = extract_extension(ArithmeticExtensionGate::::wires_ith_addend(self.i)); - let output_target = - ExtensionTarget::from_range(self.gate_index, start + 3 * D..start + 4 * D); + let output_target = ExtensionTarget::from_range( + self.gate_index, + ArithmeticExtensionGate::::wires_ith_output(self.i), + ); let computed_output = multiplicand_0 * multiplicand_1 * self.const_0.into() + addend * self.const_1.into(); diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 003c9ab0..070bb81e 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -197,18 +197,8 @@ impl, const D: usize, const R: usize> Gate for GMiMCGate< let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; constraints.push(builder.sub_extension(cubing_input, cubing_input_wire)); let f = builder.cube_extension(cubing_input_wire); - // addition_buffer += f - // state[active] -= f - (addition_buffer, state[active]) = builder.double_arithmetic_extension( - F::ONE, - F::ONE, - one, - addition_buffer, - f, - neg_one, - f, - state[active], - ); + addition_buffer = builder.add_extension(addition_buffer, f); + state[active] = builder.sub_extension(state[active], f); } for i in 0..W { diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 25f760c0..573e0532 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -61,7 +61,9 @@ pub struct CircuitBuilder, const D: usize> { constants_to_targets: HashMap, targets_to_constants: HashMap, - pub(crate) free_arithmetic: Option<(usize, F, F)>, + /// A map `(c0, c1) -> (g, i)` from constants `(c0,c1)` to an available arithmetic gate using + /// these constants with gate index `g` and already using `i` arithmetic operations. + pub(crate) free_arithmetic: HashMap<(F, F), (usize, usize)>, } impl, const D: usize> CircuitBuilder { @@ -78,7 +80,7 @@ impl, const D: usize> CircuitBuilder { generators: Vec::new(), constants_to_targets: HashMap::new(), targets_to_constants: HashMap::new(), - free_arithmetic: None, + free_arithmetic: HashMap::new(), } } diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index a551c809..413294fd 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -427,9 +427,9 @@ mod tests { zero_knowledge: false, cap_height: 3, fri_config: FriConfig { - proof_of_work_bits: 20, + proof_of_work_bits: 1, reduction_arity_bits: vec![3, 3, 3], - num_query_rounds: 27, + num_query_rounds: 40, }, }; let (proof_with_pis, vd, cd) = { diff --git a/src/plonk/vanishing_poly.rs b/src/plonk/vanishing_poly.rs index a2a97d4b..73acab42 100644 --- a/src/plonk/vanishing_poly.rs +++ b/src/plonk/vanishing_poly.rs @@ -306,17 +306,8 @@ pub(crate) fn eval_vanishing_poly_recursively, const D: usize>( // Holds `k[i] * x`. let mut s_ids = Vec::new(); - for j in 0..common_data.config.num_routed_wires / 2 { - let k_0 = builder.constant(common_data.k_is[2 * j]); - let k_0_ext = builder.convert_to_ext(k_0); - let k_1 = builder.constant(common_data.k_is[2 * j + 1]); - let k_1_ext = builder.convert_to_ext(k_1); - let tmp = builder.mul_two_extension(k_0_ext, x, k_1_ext, x); - s_ids.push(tmp.0); - s_ids.push(tmp.1); - } - if common_data.config.num_routed_wires.is_odd() { - let k = builder.constant(common_data.k_is[common_data.k_is.len() - 1]); + for j in 0..common_data.config.num_routed_wires { + let k = builder.constant(common_data.k_is[j]); let k_ext = builder.convert_to_ext(k); s_ids.push(builder.mul_extension(k_ext, x)); } diff --git a/src/util/reducing.rs b/src/util/reducing.rs index 459454db..863f3246 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -164,52 +164,15 @@ impl ReducingFactorTarget { where F: Extendable, { - let zero = builder.zero_extension(); let l = terms.len(); self.count += l as u64; let mut terms_vec = terms.to_vec(); - // If needed, we pad the original vector so that it has even length. - if terms_vec.len().is_odd() { - terms_vec.push(zero); - } + let mut acc = terms_vec.pop().unwrap(); terms_vec.reverse(); - let mut acc = zero; - for pair in terms_vec.chunks(2) { - // We will route the output of the first arithmetic operation to the multiplicand of the - // second, i.e. we compute the following: - // out_0 = alpha acc + pair[0] - // acc' = out_1 = alpha out_0 + pair[1] - - let (gate, range) = if let Some((g, c_0, c_1)) = builder.free_arithmetic { - if c_0 == F::ONE && c_1 == F::ONE { - (g, ArithmeticExtensionGate::::wires_third_output()) - } else { - ( - builder.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - } - } else { - ( - builder.num_gates(), - ArithmeticExtensionGate::::wires_first_output(), - ) - }; - let out_0 = ExtensionTarget::from_range(gate, range); - acc = builder - .double_arithmetic_extension( - F::ONE, - F::ONE, - self.base, - acc, - pair[0], - self.base, - out_0, - pair[1], - ) - .1; + for x in terms_vec { + acc = builder.mul_add_extension(self.base, acc, x); } acc } @@ -227,21 +190,6 @@ impl ReducingFactorTarget { builder.mul_extension(exp, x) } - pub fn shift_and_mul( - &mut self, - x: ExtensionTarget, - a: ExtensionTarget, - b: ExtensionTarget, - builder: &mut CircuitBuilder, - ) -> (ExtensionTarget, ExtensionTarget) - where - F: Extendable, - { - let exp = builder.exp_u64_extension(self.base, self.count); - self.count = 0; - builder.mul_two_extension(exp, x, a, b) - } - pub fn reset(&mut self) { self.count = 0; } From 3d83d9ff42ad6cddef7f343f5f7ce844b74b3f6c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 16 Aug 2021 10:28:08 +0200 Subject: [PATCH 14/17] Minor --- src/plonk/recursive_verifier.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 413294fd..66c1ec6f 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -427,9 +427,9 @@ mod tests { zero_knowledge: false, cap_height: 3, fri_config: FriConfig { - proof_of_work_bits: 1, + proof_of_work_bits: 20, reduction_arity_bits: vec![3, 3, 3], - num_query_rounds: 40, + num_query_rounds: 27, }, }; let (proof_with_pis, vd, cd) = { @@ -437,7 +437,7 @@ mod tests { let mut builder = CircuitBuilder::::new(config.clone()); let _two = builder.two(); let mut _two = builder.hash_n_to_hash(vec![_two], true).elements[0]; - for _ in 0..20000 { + for _ in 0..10000 { _two = builder.mul(_two, _two); } let data = builder.build(); From 5a9c5b295cd0fcf033f08a7d72cf573549e325f0 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 16 Aug 2021 10:41:12 +0200 Subject: [PATCH 15/17] Minor --- src/fri/prover.rs | 2 +- src/fri/recursive_verifier.rs | 11 ++++------- src/gadgets/arithmetic_extension.rs | 3 --- src/gadgets/select.rs | 1 - src/gates/gmimc.rs | 4 +--- src/iop/generator.rs | 6 ------ src/plonk/recursive_verifier.rs | 2 +- src/plonk/vanishing_poly.rs | 2 -- src/util/reducing.rs | 3 --- 9 files changed, 7 insertions(+), 27 deletions(-) diff --git a/src/fri/prover.rs b/src/fri/prover.rs index c1f53a1c..abddfcd7 100644 --- a/src/fri/prover.rs +++ b/src/fri/prover.rs @@ -103,7 +103,7 @@ fn fri_committed_trees, const D: usize>( values = coeffs.coset_fft(shift.into()) } - /// The coefficients being removed here should always be zero. + // The coefficients being removed here should always be zero. coeffs.coeffs.truncate(coeffs.len() >> config.rate_bits); challenger.observe_extension_elements(&coeffs.coeffs); diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index 2784ceef..5ad9429f 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -91,7 +91,7 @@ impl, const D: usize> CircuitBuilder { // Size of the LDE domain. let n = proof.final_poly.len() << (total_arities + config.rate_bits); - challenger.observe_opening_set(&os); + challenger.observe_opening_set(os); // Scaling factor to combine polynomials. let alpha = challenger.get_extension_challenge(self); @@ -284,8 +284,8 @@ impl, const D: usize> CircuitBuilder { // TODO: Do we need to range check `x_index` to a target smaller than `p`? let x_index = challenger.get_challenge(self); let mut x_index_bits = self.low_bits(x_index, n_log, 64); - let cap_index = self - .le_sum(x_index_bits[x_index_bits.len() - common_data.config.cap_height..].into_iter()); + let cap_index = + self.le_sum(x_index_bits[x_index_bits.len() - common_data.config.cap_height..].iter()); with_context!( self, "check FRI initial proof", @@ -305,7 +305,6 @@ impl, const D: usize> CircuitBuilder { let phi = self.exp_from_bits(phi, x_index_bits.iter().rev()); let g_ext = self.convert_to_ext(g); let phi_ext = self.convert_to_ext(phi); - let zero = self.zero_extension(); // `subgroup_x = g*phi, vanish_zeta = g*phi - zeta` let subgroup_x = self.mul(g, phi); let vanish_zeta = self.mul_sub_extension(g_ext, phi_ext, zeta); @@ -349,7 +348,7 @@ impl, const D: usize> CircuitBuilder { "infer evaluation using interpolation", self.compute_evaluation( subgroup_x, - &x_index_within_coset_bits, + x_index_within_coset_bits, arity_bits, evals, betas[i], @@ -389,7 +388,6 @@ impl, const D: usize> CircuitBuilder { struct PrecomputedReducedEvalsTarget { pub single: ExtensionTarget, pub zs: ExtensionTarget, - pub zs_right: ExtensionTarget, /// Slope of the line from `(zeta, zs)` to `(zeta_right, zs_right)`. pub slope: ExtensionTarget, pub zeta_right: ExtensionTarget, @@ -426,7 +424,6 @@ impl PrecomputedReducedEvalsTarget { Self { single, zs, - zs_right, slope: builder.div_extension(numerator, denominator), zeta_right, } diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index a27da240..b7d7a39a 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -1,6 +1,5 @@ use std::convert::TryInto; -use itertools::Itertools; use num::Integer; use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget}; @@ -9,7 +8,6 @@ use crate::field::field_types::Field; use crate::gates::arithmetic::{ArithmeticExtensionGate, NUM_ARITHMETIC_OPS}; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; -use crate::iop::wire::Wire; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; @@ -455,7 +453,6 @@ impl, const D: usize> CircuitBuilder { z: ExtensionTarget, ) -> ExtensionTarget { let inv = self.add_virtual_extension_target(); - let zero = self.zero_extension(); let one = self.one_extension(); self.add_generator(QuotientGeneratorExtension { numerator: one, diff --git a/src/gadgets/select.rs b/src/gadgets/select.rs index 8591a631..3be3455c 100644 --- a/src/gadgets/select.rs +++ b/src/gadgets/select.rs @@ -1,6 +1,5 @@ use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::gates::arithmetic::ArithmeticExtensionGate; use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; diff --git a/src/gates/gmimc.rs b/src/gates/gmimc.rs index 070bb81e..5e8540ae 100644 --- a/src/gates/gmimc.rs +++ b/src/gates/gmimc.rs @@ -139,7 +139,7 @@ impl, const D: usize, const R: usize> Gate for GMiMCGate< for r in 0..R { let active = r % W; - let cubing_input = state[active] + addition_buffer + self.constants[r].into(); + let cubing_input = state[active] + addition_buffer + self.constants[r]; let cubing_input_wire = vars.local_wires[Self::wire_cubing_input(r)]; constraints.push(cubing_input - cubing_input_wire); let f = cubing_input_wire.cube(); @@ -160,8 +160,6 @@ impl, const D: usize, const R: usize> Gate for GMiMCGate< builder: &mut CircuitBuilder, vars: EvaluationTargets, ) -> Vec> { - let one = builder.one_extension(); - let neg_one = builder.neg_one_extension(); let mut constraints = Vec::with_capacity(self.num_constraints()); let swap = vars.local_wires[Self::WIRE_SWAP]; diff --git a/src/iop/generator.rs b/src/iop/generator.rs index 189648c5..17567a4c 100644 --- a/src/iop/generator.rs +++ b/src/iop/generator.rs @@ -1,4 +1,3 @@ -use std::convert::identity; use std::fmt::Debug; use crate::field::extension_field::target::ExtensionTarget; @@ -75,11 +74,6 @@ pub(crate) fn generate_partial_witness( pending_generator_indices = next_pending_generator_indices; } - - // assert!( - // generator_is_expired.into_iter().all(identity), - // "Some generators weren't run." - // ); } /// A generator participates in the generation of the witness. diff --git a/src/plonk/recursive_verifier.rs b/src/plonk/recursive_verifier.rs index 66c1ec6f..6789d114 100644 --- a/src/plonk/recursive_verifier.rs +++ b/src/plonk/recursive_verifier.rs @@ -37,7 +37,7 @@ impl, const D: usize> CircuitBuilder { self.constants(&inner_common_data.circuit_digest.elements), ); challenger.observe_hash(&digest); - challenger.observe_hash(&public_inputs_hash); + challenger.observe_hash(public_inputs_hash); challenger.observe_cap(&proof.wires_cap); let betas = challenger.get_n_challenges(self, num_challenges); diff --git a/src/plonk/vanishing_poly.rs b/src/plonk/vanishing_poly.rs index 73acab42..6a282be9 100644 --- a/src/plonk/vanishing_poly.rs +++ b/src/plonk/vanishing_poly.rs @@ -1,5 +1,3 @@ -use num::Integer; - use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field_types::Field; diff --git a/src/util/reducing.rs b/src/util/reducing.rs index 863f3246..ca0dd9e8 100644 --- a/src/util/reducing.rs +++ b/src/util/reducing.rs @@ -1,11 +1,8 @@ use std::borrow::Borrow; -use num::Integer; - use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::{Extendable, Frobenius}; use crate::field::field_types::Field; -use crate::gates::arithmetic::ArithmeticExtensionGate; use crate::gates::reducing::ReducingGate; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; From 9a5454011650b7df5d6b4a1d11719d8bad28c57c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 16 Aug 2021 11:08:26 +0200 Subject: [PATCH 16/17] Minor --- src/fri/commitment.rs | 1 - src/gadgets/arithmetic_extension.rs | 3 +++ src/gates/arithmetic.rs | 2 +- src/plonk/copy_constraint.rs | 1 - 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/fri/commitment.rs b/src/fri/commitment.rs index bd051e3d..7e7dab6e 100644 --- a/src/fri/commitment.rs +++ b/src/fri/commitment.rs @@ -288,7 +288,6 @@ mod tests { config: CircuitConfig { fri_config, num_routed_wires: 6, - zero_knowledge: true, ..CircuitConfig::large_config() }, degree_bits, diff --git a/src/gadgets/arithmetic_extension.rs b/src/gadgets/arithmetic_extension.rs index b7d7a39a..b11447df 100644 --- a/src/gadgets/arithmetic_extension.rs +++ b/src/gadgets/arithmetic_extension.rs @@ -13,6 +13,9 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; impl, const D: usize> CircuitBuilder { + /// Finds the last available arithmetic gate with the given constants or add one if there aren't any. + /// Returns `(g,i)` such that there is an arithmetic gate with the given constants at index + /// `g` and the gate's `i`-th operation is available. fn find_arithmetic_gate(&mut self, const_0: F, const_1: F) -> (usize, usize) { let (gate, i) = self .free_arithmetic diff --git a/src/gates/arithmetic.rs b/src/gates/arithmetic.rs index 5b608519..c8f8f59c 100644 --- a/src/gates/arithmetic.rs +++ b/src/gates/arithmetic.rs @@ -108,7 +108,7 @@ impl, const D: usize> Gate for ArithmeticExtensionGate gate_index: usize, local_constants: &[F], ) -> Vec>> { - (0..4) + (0..NUM_ARITHMETIC_OPS) .map(|i| { let g: Box> = Box::new(ArithmeticExtensionGenerator { gate_index, diff --git a/src/plonk/copy_constraint.rs b/src/plonk/copy_constraint.rs index a04fc75b..a838ed37 100644 --- a/src/plonk/copy_constraint.rs +++ b/src/plonk/copy_constraint.rs @@ -1,7 +1,6 @@ use crate::iop::target::Target; /// A named copy constraint. -#[derive(Debug)] pub struct CopyConstraint { pub pair: (Target, Target), pub name: String, From d9b0778eefe6fc3e3f16683bb8d3d3ebf7839044 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 17 Aug 2021 08:47:52 +0200 Subject: [PATCH 17/17] Change zip order --- src/fri/recursive_verifier.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index 5ad9429f..4cfd837a 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -43,11 +43,11 @@ impl, const D: usize> CircuitBuilder { // The answer is gotten by interpolating {(x*g^i, P(x*g^i))} and evaluating at beta. let points = g .powers() - .zip(evals) - .map(|(y, v)| { + .map(|y| { let yc = self.constant(y); - (self.mul(coset_start, yc), v) + self.mul(coset_start, yc) }) + .zip(evals) .collect::>(); self.interpolate(&points, beta)