mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 23:03:08 +00:00
insertion gadget (test fails)
This commit is contained in:
parent
ea07db14ac
commit
d3127c73d3
@ -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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// 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<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
element: ExtensionTarget<D>,
|
||||
v: Vec<ExtensionTarget<D>>,
|
||||
) -> Vec<ExtensionTarget<D>> {
|
||||
let mut already_inserted = self.zero();
|
||||
let mut new_list = Vec::new();
|
||||
let gate = InsertionGate::<F, D> {
|
||||
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::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user