From 1ccff4d004b2a862b7c9dd62bcb3504671fe38cd Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Thu, 19 Aug 2021 10:38:46 -0700 Subject: [PATCH] progress --- src/gates/switch.rs | 115 +++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/src/gates/switch.rs b/src/gates/switch.rs index 3ee5e563..e9e34cd7 100644 --- a/src/gates/switch.rs +++ b/src/gates/switch.rs @@ -34,39 +34,41 @@ impl, const D: usize, const CHUNK_SIZE: usize> SwitchGate usize { debug_assert!(copy < self.num_copies); debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE + 1) + 1 + element } - pub fn wire_second_input(&self, copy: usize, element: usize) { + pub fn wire_second_input(&self, copy: usize, element: usize) -> usize { debug_assert!(copy < self.num_copies); debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE + 1) + 1 + CHUNK_SIZE + element } - pub fn wire_first_output(&self, copy: usize, element: usize) { + pub fn wire_first_output(&self, copy: usize, element: usize) -> usize { debug_assert!(copy < self.num_copies); debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE + 1) + 1 + 2 * CHUNK_SIZE + element } - pub fn wire_second_output(&self, copy: usize, element: usize) { + pub fn wire_second_output(&self, copy: usize, element: usize) -> usize { debug_assert!(copy < self.num_copies); debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE + 1) + 1 + 3 * CHUNK_SIZE + element } } -impl, const D: usize, const CHUNK_SIZE: usize> Gate for SwitchGate { +impl, const D: usize, const CHUNK_SIZE: usize> Gate + for SwitchGate +{ fn id(&self) -> String { format!("{:?}", self, D) } fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let mut constraints = Vec::with_capacity(self.num_constraints()); - + for c in 0..self.num_copies { let switch_bool = vars.local_wires[self.wire_switch_bool(c)]; @@ -75,20 +77,21 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate for S let second_input = vars.local_wires[self.wire_second_input(c, e)]; let first_output = vars.local_wires[self.wire_first_output(c, e)]; let second_output = vars.local_wires[self.wire_second_output(c, e)]; - + constraints.push(switch_bool * (first_input - second_output)); constraints.push(switch_bool * (second_input - first_output)); constraints.push((F::Extension::ONE - switch_bool) * (first_input - first_output)); - constraints.push((F::Extension::ONE - switch_bool) * (second_input - second_output)); + constraints + .push((F::Extension::ONE - switch_bool) * (second_input - second_output)); } } constraints } - fn eval_unfiltered_base(&self, vars: EvaluationVarsBase) -> Vec { + fn eval_unfiltered_base(&self, vars: EvaluationVarsBase) -> Vec { let mut constraints = Vec::with_capacity(self.num_constraints()); - + for c in 0..self.num_copies { let switch_bool = vars.local_wires[self.wire_switch_bool(c)]; @@ -97,7 +100,7 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate for S let second_input = vars.local_wires[self.wire_second_input(c, e)]; let first_output = vars.local_wires[self.wire_first_output(c, e)]; let second_output = vars.local_wires[self.wire_second_output(c, e)]; - + constraints.push(switch_bool * (first_input - second_output)); constraints.push(switch_bool * (second_input - first_output)); constraints.push((F::ONE - switch_bool) * (first_input - first_output)); @@ -114,7 +117,7 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate for S vars: EvaluationTargets, ) -> Vec> { let mut constraints = Vec::with_capacity(self.num_constraints()); - + let one = builder.one_extension(); for c in 0..self.num_copies { let switch_bool = vars.local_wires[self.wire_switch_bool(c)]; @@ -125,22 +128,24 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate for S let second_input = vars.local_wires[self.wire_second_input(c, e)]; let first_output = vars.local_wires[self.wire_first_output(c, e)]; let second_output = vars.local_wires[self.wire_second_output(c, e)]; - - + let first_switched = builder.sub_extension(first_input, second_output); let first_switched_constraint = builder.mul_extension(switch_bool, first_switched); constraints.push(first_switched_constraint); let second_switched = builder.sub_extension(second_input, first_output); - let second_switched_constraint = builder.mul_extension(switch_bool, second_switched); + let second_switched_constraint = + builder.mul_extension(switch_bool, second_switched); constraints.push(second_switched_constraint); let first_not_switched = builder.sub_extension(first_input, first_output); - let first_not_switched_constraint = builder.mul_extension(not_switch, first_not_switched); + let first_not_switched_constraint = + builder.mul_extension(not_switch, first_not_switched); constraints.push(first_not_switched_constraint); let second_not_switched = builder.sub_extension(second_input, second_output); - let second_not_switched_constraint = builder.mul_extension(not_switch, second_not_switched); + let second_not_switched_constraint = + builder.mul_extension(not_switch, second_not_switched); constraints.push(second_not_switched_constraint); } } @@ -183,7 +188,9 @@ struct SwitchGenerator, const D: usize, const CHUNK_SIZE: usize gate: SwitchGate, } -impl, const D: usize, const CHUNK_SIZE: usize> SimpleGenerator for SwitchGenerator { +impl, const D: usize, const CHUNK_SIZE: usize> SimpleGenerator + for SwitchGenerator +{ fn dependencies(&self) -> Vec { let local_target = |input| Target::wire(self.gate_index, input); @@ -252,6 +259,7 @@ mod tests { use crate::gates::gate_testing::{test_eval_fns, test_low_degree}; use crate::gates::switch::SwitchGate; use crate::hash::hash_types::HashOut; + use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::EvaluationVars; #[test] @@ -261,7 +269,6 @@ mod tests { _phantom: PhantomData, }; - assert_eq!(gate.wire_switch_bool(0), 0); assert_eq!(gate.wire_first_input(0, 0), 1); assert_eq!(gate.wire_first_input(0, 2), 3); @@ -290,67 +297,55 @@ mod tests { type F = CrandallField; type FF = QuarticCrandallField; const D: usize = 4; + const CHUNK_SIZE: usize = 4; + let num_copies = 3; /// Returns the local wires for a random access gate given the vector, element to compare, /// and index. - fn get_wires(list: Vec, access_index: usize, claimed_element: FF) -> Vec { - let vec_size = list.len(); + fn get_wires( + first_inputs: Vec>, + second_inputs: Vec>, + switch_bools: Vec, + ) -> Vec { + let num_copies = first_inputs.len(); let mut v = Vec::new(); - v.push(F::from_canonical_usize(access_index)); - v.extend(claimed_element.0); - for j in 0..vec_size { - v.extend(list[j].0); - } - - let mut equality_dummy_vals = Vec::new(); - let mut index_matches_vals = Vec::new(); - for i in 0..vec_size { - if i == access_index { - equality_dummy_vals.push(F::ONE); - index_matches_vals.push(F::ONE); - } else { - equality_dummy_vals.push( - (F::from_canonical_usize(i) - F::from_canonical_usize(access_index)) - .inverse(), - ); - index_matches_vals.push(F::ZERO); + for c in 0..num_copies { + let switch = switch_bools[c]; + v.push(F::from_bool(switch)); + for e in 0..CHUNK_SIZE { + let first_input = first_inputs[c][e]; + let second_input = second_inputs[c][e]; + let first_output = if switch { second_input } else { first_input }; + let second_output = if switch { first_input } else { second_input }; + v.push(first_input); + v.push(second_input); + v.push(first_output); + v.push(second_output); } } - v.extend(equality_dummy_vals); - v.extend(index_matches_vals); - v.iter().map(|&x| x.into()).collect::>() } - let list = vec![FF::rand(); 3]; - let access_index = 1; - let gate = SwitchGate:: { - vec_size: 3, + let first_inputs = vec![vec![F::rand(); CHUNK_SIZE]; num_copies]; + let second_inputs = vec![vec![F::rand(); CHUNK_SIZE]; num_copies]; + let switch_bools = vec![true, false, true]; + + let gate = SwitchGate:: { + num_copies, _phantom: PhantomData, }; - let good_claimed_element = list[access_index]; - let good_vars = EvaluationVars { + let vars = EvaluationVars { local_constants: &[], - local_wires: &get_wires(list.clone(), access_index, good_claimed_element), - public_inputs_hash: &HashOut::rand(), - }; - let bad_claimed_element = FF::rand(); - let bad_vars = EvaluationVars { - local_constants: &[], - local_wires: &get_wires(list, access_index, bad_claimed_element), + local_wires: &get_wires(first_inputs, second_inputs, switch_bools), public_inputs_hash: &HashOut::rand(), }; assert!( - gate.eval_unfiltered(good_vars).iter().all(|x| x.is_zero()), + gate.eval_unfiltered(vars).iter().all(|x| x.is_zero()), "Gate constraints are not satisfied." ); - assert!( - !gate.eval_unfiltered(bad_vars).iter().all(|x| x.is_zero()), - "Gate constraints are satisfied but shouold not be." - ); } }