mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-08 08:43:06 +00:00
progress
This commit is contained in:
parent
a574fecc4d
commit
2ab37e688f
@ -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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
&mut self,
|
||||
a: [Target; CHUNK_SIZE],
|
||||
b: [Target; CHUNK_SIZE],
|
||||
) -> (
|
||||
SwitchGate<F, D, CHUNK_SIZE>,
|
||||
usize,
|
||||
[Target; CHUNK_SIZE],
|
||||
[Target; CHUNK_SIZE],
|
||||
) {
|
||||
let gate = SwitchGate::<F, D, CHUNK_SIZE>::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::<F, D, CHUNK_SIZE>::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::<F, D, CHUNK_SIZE>::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::<F, D, CHUNK_SIZE>::wire_first_input(0, e),
|
||||
),
|
||||
);
|
||||
self.route(
|
||||
b[e],
|
||||
Target::wire(
|
||||
gate_index,
|
||||
SwitchGate::<F, D, CHUNK_SIZE>::wire_second_input(0, e),
|
||||
),
|
||||
);
|
||||
c.push(Target::wire(
|
||||
gate_index,
|
||||
SwitchGate::<F, D, CHUNK_SIZE>::wire_first_output(0, e),
|
||||
));
|
||||
d.push(Target::wire(
|
||||
gate_index,
|
||||
SwitchGate::<F, D, CHUNK_SIZE>::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::<F, D, CHUNK_SIZE>::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<const CHUNK_SIZE: usize>(
|
||||
@ -102,12 +138,12 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
};
|
||||
|
||||
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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
struct PermutationGenerator<const CHUNK_SIZE: usize> {
|
||||
gate_index: usize,
|
||||
fn route_one_layer<F: Field, const CHUNK_SIZE: usize>(
|
||||
a_values: Vec<F>,
|
||||
b_values: Vec<F>,
|
||||
a_wires: Vec<[Target; CHUNK_SIZE]>,
|
||||
b_wires: Vec<[Target; CHUNK_SIZE]>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
impl<F: Field, const CHUNK_SIZE: usize> SimpleGenerator<F> for PermutationGenerator<CHUNK_SIZE> {
|
||||
struct PermutationGenerator<F: Field, const CHUNK_SIZE: usize> {
|
||||
a_values: Vec<F>,
|
||||
b_values: Vec<F>,
|
||||
a_wires: Vec<[Target; CHUNK_SIZE]>,
|
||||
b_wires: Vec<[Target; CHUNK_SIZE]>,
|
||||
}
|
||||
|
||||
impl<F: Field, const CHUNK_SIZE: usize> SimpleGenerator<F> for PermutationGenerator<F, CHUNK_SIZE> {
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
todo!()
|
||||
self.a_wires
|
||||
.iter()
|
||||
.map(|arr| arr.to_vec())
|
||||
.flatten()
|
||||
.collect()
|
||||
//.chain(self.b_wires.iter()).collect()
|
||||
}
|
||||
|
||||
fn run_once(&self, witness: &PartialWitness<F>, out_buffer: &mut GeneratedValues<F>) {
|
||||
|
||||
@ -32,37 +32,32 @@ impl<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> SwitchGate<F, D,
|
||||
Self::new(num_copies)
|
||||
}
|
||||
|
||||
fn max_num_copies(num_routed_wires: usize) -> 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<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> Gate<F, D>
|
||||
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<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> Gate<F, D>
|
||||
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<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> Gate<F, D>
|
||||
|
||||
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<F: Extendable<D>, const D: usize, const CHUNK_SIZE: usize> Gate<F, D>
|
||||
}
|
||||
|
||||
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<F: Extendable<D>, 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::<F, D, CHUNK_SIZE>::wire_first_input(c, e),
|
||||
));
|
||||
deps.push(local_target(
|
||||
SwitchGate::<F, D, CHUNK_SIZE>::wire_second_input(c, e),
|
||||
));
|
||||
deps.push(local_target(
|
||||
SwitchGate::<F, D, CHUNK_SIZE>::wire_first_output(c, e),
|
||||
));
|
||||
deps.push(local_target(
|
||||
SwitchGate::<F, D, CHUNK_SIZE>::wire_second_output(c, e),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,12 +227,19 @@ impl<F: Extendable<D>, 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::<F, D, CHUNK_SIZE>::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::<F, D, CHUNK_SIZE>::wire_first_input(c, e));
|
||||
let second_input =
|
||||
get_local_wire(SwitchGate::<F, D, CHUNK_SIZE>::wire_second_input(c, e));
|
||||
let first_output =
|
||||
get_local_wire(SwitchGate::<F, D, CHUNK_SIZE>::wire_first_output(c, e));
|
||||
let second_output =
|
||||
get_local_wire(SwitchGate::<F, D, CHUNK_SIZE>::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::<CrandallField, 4, 3> {
|
||||
num_copies: 3,
|
||||
type SG = SwitchGate<CrandallField, 4, 3>;
|
||||
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]
|
||||
|
||||
@ -40,7 +40,7 @@ pub struct CircuitBuilder<F: Extendable<D>, const D: usize> {
|
||||
gates: HashSet<GateRef<F, D>>,
|
||||
|
||||
/// The concrete placement of each gate.
|
||||
gate_instances: Vec<GateInstance<F, D>>,
|
||||
pub(crate) gate_instances: Vec<GateInstance<F, D>>,
|
||||
|
||||
/// Targets to be made public.
|
||||
public_inputs: Vec<Target>,
|
||||
@ -65,6 +65,8 @@ pub struct CircuitBuilder<F: Extendable<D>, 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<Option<(usize, usize)>>,
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
@ -82,6 +84,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
constants_to_targets: HashMap::new(),
|
||||
targets_to_constants: HashMap::new(),
|
||||
free_arithmetic: HashMap::new(),
|
||||
current_switch_gates: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user