From 2ab37e688f06edb02bfbd340d5a717c96e38730e Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 24 Aug 2021 18:35:30 -0700 Subject: [PATCH] progress --- src/gadgets/permutation.rs | 95 +++++++++++++++++++++------- src/gates/switch.rs | 117 +++++++++++++++++++---------------- src/plonk/circuit_builder.rs | 5 +- 3 files changed, 143 insertions(+), 74 deletions(-) diff --git a/src/gadgets/permutation.rs b/src/gadgets/permutation.rs index e5f67ea6..4b301c04 100644 --- a/src/gadgets/permutation.rs +++ b/src/gadgets/permutation.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use crate::field::{extension_field::Extendable, field_types::Field}; use crate::gates::switch::SwitchGate; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; -use crate::iop::target::Target; +use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -45,7 +45,7 @@ impl, const D: usize> CircuitBuilder { c: [Target; CHUNK_SIZE], d: [Target; CHUNK_SIZE], ) { - let (_, _, gate_c, gate_d) = self.create_switch(a, b); + let (_, gate_c, gate_d) = self.create_switch(a, b); for e in 0..CHUNK_SIZE { self.route(c[e], gate_c[e]); self.route(d[e], gate_d[e]); @@ -56,28 +56,64 @@ impl, const D: usize> CircuitBuilder { &mut self, a: [Target; CHUNK_SIZE], b: [Target; CHUNK_SIZE], - ) -> ( - SwitchGate, - usize, - [Target; CHUNK_SIZE], - [Target; CHUNK_SIZE], - ) { - let gate = SwitchGate::::new(1); - let gate_index = self.add_gate(gate.clone(), vec![]); + ) -> (usize, [Target; CHUNK_SIZE], [Target; CHUNK_SIZE]) { + if self.current_switch_gates.len() < CHUNK_SIZE { + self.current_switch_gates + .extend(vec![None; CHUNK_SIZE - self.current_switch_gates.len()]); + } + + let (gate_index, mut next_copy) = match self.current_switch_gates[CHUNK_SIZE - 1] { + None => { + let gate = SwitchGate::::new_from_config(self.config.clone()); + let gate_index = self.add_gate(gate.clone(), vec![]); + (gate_index, 0) + } + Some((idx, next_copy)) => (idx, next_copy), + }; + + let num_copies = + SwitchGate::::max_num_copies(self.config.num_routed_wires); let mut c = Vec::new(); let mut d = Vec::new(); for e in 0..CHUNK_SIZE { - self.route(a[e], Target::wire(gate_index, gate.wire_first_input(0, e))); - self.route(b[e], Target::wire(gate_index, gate.wire_second_input(0, e))); - c.push(Target::wire(gate_index, gate.wire_first_output(0, e))); - d.push(Target::wire(gate_index, gate.wire_second_output(0, e))); + self.route( + a[e], + Target::wire( + gate_index, + SwitchGate::::wire_first_input(0, e), + ), + ); + self.route( + b[e], + Target::wire( + gate_index, + SwitchGate::::wire_second_input(0, e), + ), + ); + c.push(Target::wire( + gate_index, + SwitchGate::::wire_first_output(0, e), + )); + d.push(Target::wire( + gate_index, + SwitchGate::::wire_second_output(0, e), + )); } let c_arr: [Target; CHUNK_SIZE] = c.try_into().unwrap(); let d_arr: [Target; CHUNK_SIZE] = d.try_into().unwrap(); - (gate, gate_index, c_arr, d_arr) + next_copy += 1; + if next_copy == num_copies { + let new_gate = SwitchGate::::new_from_config(self.config.clone()); + let new_gate_index = self.add_gate(new_gate.clone(), vec![]); + self.current_switch_gates[CHUNK_SIZE - 1] = Some((new_gate_index, 0)); + } else { + self.current_switch_gates[CHUNK_SIZE - 1] = Some((gate_index, next_copy)); + } + + (gate_index, c_arr, d_arr) } fn assert_permutation_recursive( @@ -102,12 +138,12 @@ impl, const D: usize> CircuitBuilder { }; for i in 0..a_num_switches { - let (_, _, out_1, out_2) = self.create_switch(a[i * 2], a[i * 2 + 1]); + let (_, out_1, out_2) = self.create_switch(a[i * 2], a[i * 2 + 1]); child_1_a.push(out_1); child_2_a.push(out_2); } for i in 0..b_num_switches { - let (_, _, out_1, out_2) = self.create_switch(b[i * 2], b[i * 2 + 1]); + let (_, out_1, out_2) = self.create_switch(b[i * 2], b[i * 2 + 1]); child_1_b.push(out_1); child_2_b.push(out_2); } @@ -126,13 +162,30 @@ impl, const D: usize> CircuitBuilder { } } -struct PermutationGenerator { - gate_index: usize, +fn route_one_layer( + a_values: Vec, + b_values: Vec, + a_wires: Vec<[Target; CHUNK_SIZE]>, + b_wires: Vec<[Target; CHUNK_SIZE]>, +) { + todo!() } -impl SimpleGenerator for PermutationGenerator { +struct PermutationGenerator { + a_values: Vec, + b_values: Vec, + a_wires: Vec<[Target; CHUNK_SIZE]>, + b_wires: Vec<[Target; CHUNK_SIZE]>, +} + +impl SimpleGenerator for PermutationGenerator { fn dependencies(&self) -> Vec { - todo!() + self.a_wires + .iter() + .map(|arr| arr.to_vec()) + .flatten() + .collect() + //.chain(self.b_wires.iter()).collect() } fn run_once(&self, witness: &PartialWitness, out_buffer: &mut GeneratedValues) { diff --git a/src/gates/switch.rs b/src/gates/switch.rs index a48adb61..70bfd45d 100644 --- a/src/gates/switch.rs +++ b/src/gates/switch.rs @@ -32,37 +32,32 @@ impl, const D: usize, const CHUNK_SIZE: usize> SwitchGate usize { + pub fn max_num_copies(num_routed_wires: usize) -> usize { num_routed_wires / (4 * CHUNK_SIZE) } - pub fn wire_first_input(&self, copy: usize, element: usize) -> usize { - debug_assert!(copy < self.num_copies); + pub fn wire_first_input(copy: usize, element: usize) -> usize { debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE) + element } - pub fn wire_second_input(&self, copy: usize, element: usize) -> usize { - debug_assert!(copy < self.num_copies); + pub fn wire_second_input(copy: usize, element: usize) -> usize { debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE) + CHUNK_SIZE + element } - pub fn wire_first_output(&self, copy: usize, element: usize) -> usize { - debug_assert!(copy < self.num_copies); + pub fn wire_first_output(copy: usize, element: usize) -> usize { debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE) + 2 * CHUNK_SIZE + element } - pub fn wire_second_output(&self, copy: usize, element: usize) -> usize { - debug_assert!(copy < self.num_copies); + pub fn wire_second_output(copy: usize, element: usize) -> usize { debug_assert!(element < CHUNK_SIZE); copy * (4 * CHUNK_SIZE) + 3 * CHUNK_SIZE + element } - pub fn wire_switch_bool(&self, copy: usize) -> usize { - debug_assert!(copy < self.num_copies); - self.num_copies * (4 * CHUNK_SIZE) + copy + pub fn wire_switch_bool(num_copies: usize, copy: usize) -> usize { + num_copies * (4 * CHUNK_SIZE) + copy } } @@ -77,14 +72,14 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate 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)]; + let switch_bool = vars.local_wires[Self::wire_switch_bool(self.num_wires(), c)]; let not_switch = F::Extension::ONE - switch_bool; for e in 0..CHUNK_SIZE { - let first_input = vars.local_wires[self.wire_first_input(c, e)]; - 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_input = vars.local_wires[Self::wire_first_input(c, e)]; + 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)); @@ -100,14 +95,14 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate 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)]; + let switch_bool = vars.local_wires[Self::wire_switch_bool(self.num_copies, c)]; let not_switch = F::ONE - switch_bool; for e in 0..CHUNK_SIZE { - let first_input = vars.local_wires[self.wire_first_input(c, e)]; - 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_input = vars.local_wires[Self::wire_first_input(c, e)]; + 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)); @@ -128,14 +123,14 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate let one = builder.one_extension(); for c in 0..self.num_copies { - let switch_bool = vars.local_wires[self.wire_switch_bool(c)]; + let switch_bool = vars.local_wires[Self::wire_switch_bool(self.num_copies, c)]; let not_switch = builder.sub_extension(one, switch_bool); for e in 0..CHUNK_SIZE { - let first_input = vars.local_wires[self.wire_first_input(c, e)]; - 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_input = vars.local_wires[Self::wire_first_input(c, e)]; + 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); @@ -174,7 +169,7 @@ impl, const D: usize, const CHUNK_SIZE: usize> Gate } fn num_wires(&self) -> usize { - self.wire_second_output(self.num_copies - 1, CHUNK_SIZE - 1) + 1 + Self::wire_second_output(self.num_copies - 1, CHUNK_SIZE - 1) + 1 } fn num_constants(&self) -> usize { @@ -205,10 +200,18 @@ impl, const D: usize, const CHUNK_SIZE: usize> SimpleGenerator< let mut deps = Vec::new(); for c in 0..self.gate.num_copies { for e in 0..CHUNK_SIZE { - deps.push(local_target(self.gate.wire_first_input(c, e))); - deps.push(local_target(self.gate.wire_second_input(c, e))); - deps.push(local_target(self.gate.wire_first_output(c, e))); - deps.push(local_target(self.gate.wire_second_output(c, e))); + deps.push(local_target( + SwitchGate::::wire_first_input(c, e), + )); + deps.push(local_target( + SwitchGate::::wire_second_input(c, e), + )); + deps.push(local_target( + SwitchGate::::wire_first_output(c, e), + )); + deps.push(local_target( + SwitchGate::::wire_second_output(c, e), + )); } } @@ -224,12 +227,19 @@ impl, const D: usize, const CHUNK_SIZE: usize> SimpleGenerator< let get_local_wire = |input| witness.get_wire(local_wire(input)); for c in 0..self.gate.num_copies { - let switch_bool_wire = local_wire(self.gate.wire_switch_bool(c)); + let switch_bool_wire = local_wire(SwitchGate::::wire_switch_bool( + self.gate.num_copies, + c, + )); for e in 0..CHUNK_SIZE { - let first_input = get_local_wire(self.gate.wire_first_input(c, e)); - let second_input = get_local_wire(self.gate.wire_second_input(c, e)); - let first_output = get_local_wire(self.gate.wire_first_output(c, e)); - let second_output = get_local_wire(self.gate.wire_second_output(c, e)); + let first_input = + get_local_wire(SwitchGate::::wire_first_input(c, e)); + let second_input = + get_local_wire(SwitchGate::::wire_second_input(c, e)); + let first_output = + get_local_wire(SwitchGate::::wire_first_output(c, e)); + let second_output = + get_local_wire(SwitchGate::::wire_second_output(c, e)); if first_input == first_output { out_buffer.set_wire(switch_bool_wire, F::ONE); @@ -259,24 +269,27 @@ mod tests { #[test] fn wire_indices() { - let gate = SwitchGate:: { - num_copies: 3, + type SG = SwitchGate; + let num_copies = 3; + + let gate = SG { + num_copies, _phantom: PhantomData, }; - assert_eq!(gate.wire_first_input(0, 0), 0); - assert_eq!(gate.wire_first_input(0, 2), 2); - assert_eq!(gate.wire_second_input(0, 0), 3); - assert_eq!(gate.wire_second_input(0, 2), 5); - assert_eq!(gate.wire_first_output(0, 0), 6); - assert_eq!(gate.wire_second_output(0, 2), 11); - assert_eq!(gate.wire_first_input(1, 0), 12); - assert_eq!(gate.wire_second_output(1, 2), 23); - assert_eq!(gate.wire_first_input(2, 0), 24); - assert_eq!(gate.wire_second_output(2, 2), 35); - assert_eq!(gate.wire_switch_bool(0), 36); - assert_eq!(gate.wire_switch_bool(1), 37); - assert_eq!(gate.wire_switch_bool(2), 38); + assert_eq!(SG::wire_first_input(0, 0), 0); + assert_eq!(SG::wire_first_input(0, 2), 2); + assert_eq!(SG::wire_second_input(0, 0), 3); + assert_eq!(SG::wire_second_input(0, 2), 5); + assert_eq!(SG::wire_first_output(0, 0), 6); + assert_eq!(SG::wire_second_output(0, 2), 11); + assert_eq!(SG::wire_first_input(1, 0), 12); + assert_eq!(SG::wire_second_output(1, 2), 23); + assert_eq!(SG::wire_first_input(2, 0), 24); + assert_eq!(SG::wire_second_output(2, 2), 35); + assert_eq!(SG::wire_switch_bool(num_copies, 0), 36); + assert_eq!(SG::wire_switch_bool(num_copies, 1), 37); + assert_eq!(SG::wire_switch_bool(num_copies, 2), 38); } #[test] diff --git a/src/plonk/circuit_builder.rs b/src/plonk/circuit_builder.rs index 7a5b57bc..0daa4943 100644 --- a/src/plonk/circuit_builder.rs +++ b/src/plonk/circuit_builder.rs @@ -40,7 +40,7 @@ pub struct CircuitBuilder, const D: usize> { gates: HashSet>, /// The concrete placement of each gate. - gate_instances: Vec>, + pub(crate) gate_instances: Vec>, /// Targets to be made public. public_inputs: Vec, @@ -65,6 +65,8 @@ pub struct CircuitBuilder, const D: usize> { /// 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)>, + + pub(crate) current_switch_gates: Vec>, } impl, const D: usize> CircuitBuilder { @@ -82,6 +84,7 @@ impl, const D: usize> CircuitBuilder { constants_to_targets: HashMap::new(), targets_to_constants: HashMap::new(), free_arithmetic: HashMap::new(), + current_switch_gates: Vec::new(), } }