From d3127c73d309f0bde723ff4ff06a13a10e652b8d Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Wed, 14 Jul 2021 23:54:22 -0700 Subject: [PATCH] insertion gadget (test fails) --- src/gadgets/insert.rs | 81 +++++++++++++------------------------------ 1 file changed, 25 insertions(+), 56 deletions(-) diff --git a/src/gadgets/insert.rs b/src/gadgets/insert.rs index 734b6c03..0d0f3f37 100644 --- a/src/gadgets/insert.rs +++ b/src/gadgets/insert.rs @@ -1,42 +1,12 @@ +use std::marker::PhantomData; + use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; -use crate::generator::NonzeroTestGenerator; +use crate::gates::insertion::InsertionGate; use crate::target::Target; impl, const D: usize> CircuitBuilder { - /// Evaluates to 0 if `x` equals zero, 1 otherwise. - /// From section 2 of https://github.com/mir-protocol/r1cs-workshop/blob/master/workshop.pdf, - /// based on an idea from https://eprint.iacr.org/2012/598.pdf. - pub fn is_nonzero(&mut self, x: Target) -> Target { - // Dummy variable. - let m = self.add_virtual_target(); - - // The prover sets this the dummy variable to 1/x if x != 0, or to an arbitrary value if - // x == 0. - self.add_generator(NonzeroTestGenerator { - to_test: x, - dummy: m, - }); - - // Evaluates to (0) * (0) = 0 if x == 0 and (x) * (1/x) = 1 otherwise. - let y = self.mul(x, m); - - // Enforce that (1 - y) * x == 0. - let prod = self.arithmetic(F::NEG_ONE, x, y, F::ONE, x); - self.assert_zero(prod); - - y - } - - /// Evaluates to 1 if `x` and `y` are equal, 0 otherwise. - pub fn is_equal(&mut self, x: Target, y: Target) -> Target { - let difference = self.sub(x, y); - let not_equal = self.is_nonzero(difference); - let one = self.one(); - self.sub(one, not_equal) - } - /// Inserts a `Target` in a vector at a non-deterministic index. /// Note: `index` is not range-checked. pub fn insert( @@ -45,32 +15,31 @@ impl, const D: usize> CircuitBuilder { element: ExtensionTarget, v: Vec>, ) -> Vec> { - let mut already_inserted = self.zero(); - let mut new_list = Vec::new(); + let gate = InsertionGate:: { + vec_size: v.len(), + _phantom: PhantomData, + }; + let gate_index = + self.add_gate_no_constants(InsertionGate::new(v.len())); + + v.iter().enumerate().map(|(i, &val)| { + self.route_extension( + val, + ExtensionTarget::from_range(gate_index, gate.wires_original_list_item(i)), + ); + }); + self.route(index, Target::wire(gate_index, gate.wires_insertion_index())); + self.route_extension( + element, + ExtensionTarget::from_range(gate_index, gate.wires_element_to_insert()), + ); - let one = self.one(); - for i in 0..=v.len() { - let cur_index = self.constant(F::from_canonical_usize(i)); - let insert_here = self.is_equal(cur_index, index); - - let mut new_item = self.zero_extension(); - new_item = self.scalar_mul_add_extension(insert_here, element, new_item); - if i > 0 { - new_item = self.scalar_mul_add_extension(already_inserted, v[i - 1], new_item); - } - already_inserted = self.add(already_inserted, insert_here); - - let not_already_inserted = self.sub(one, already_inserted); - if i < v.len() { - new_item = self.scalar_mul_add_extension(not_already_inserted, v[i], new_item); - } - - new_list.push(new_item); - } - - new_list + (0..=v.len()).map(|i| { + ExtensionTarget::from_range(gate_index, gate.wires_output_list_item(i)) + }).collect::>() } } + #[cfg(test)] mod tests { use super::*;