2022-11-04 16:26:22 -07:00
|
|
|
use alloc::vec;
|
|
|
|
|
use alloc::vec::Vec;
|
|
|
|
|
|
2022-06-27 07:18:21 -07:00
|
|
|
use plonky2::field::extension::Extendable;
|
2021-12-28 11:51:13 -08:00
|
|
|
use plonky2::hash::hash_types::RichField;
|
|
|
|
|
use plonky2::iop::ext_target::ExtensionTarget;
|
|
|
|
|
use plonky2::iop::target::Target;
|
|
|
|
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
2021-06-14 15:15:22 +02:00
|
|
|
|
2021-12-28 11:51:13 -08:00
|
|
|
use crate::insertion_gate::InsertionGate;
|
|
|
|
|
|
|
|
|
|
pub trait CircuitBuilderInsert<F: RichField + Extendable<D>, const D: usize> {
|
2021-07-12 11:56:53 -07:00
|
|
|
/// Inserts a `Target` in a vector at a non-deterministic index.
|
2021-06-14 15:15:22 +02:00
|
|
|
/// Note: `index` is not range-checked.
|
2021-12-28 11:51:13 -08:00
|
|
|
fn insert(
|
|
|
|
|
&mut self,
|
|
|
|
|
index: Target,
|
|
|
|
|
element: ExtensionTarget<D>,
|
|
|
|
|
v: Vec<ExtensionTarget<D>>,
|
|
|
|
|
) -> Vec<ExtensionTarget<D>>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilderInsert<F, D>
|
|
|
|
|
for CircuitBuilder<F, D>
|
|
|
|
|
{
|
|
|
|
|
fn insert(
|
2021-06-14 15:15:22 +02:00
|
|
|
&mut self,
|
|
|
|
|
index: Target,
|
|
|
|
|
element: ExtensionTarget<D>,
|
2021-06-16 11:37:07 +02:00
|
|
|
v: Vec<ExtensionTarget<D>>,
|
2021-06-14 15:15:22 +02:00
|
|
|
) -> Vec<ExtensionTarget<D>> {
|
2021-07-22 23:48:03 -07:00
|
|
|
let gate = InsertionGate::new(v.len());
|
2022-05-17 19:32:51 +02:00
|
|
|
let row = self.add_gate(gate.clone(), vec![]);
|
2021-06-30 14:02:20 -07:00
|
|
|
|
2021-07-15 13:57:50 -07:00
|
|
|
v.iter().enumerate().for_each(|(i, &val)| {
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect_extension(
|
2021-07-14 23:54:22 -07:00
|
|
|
val,
|
2022-05-17 19:32:51 +02:00
|
|
|
ExtensionTarget::from_range(row, gate.wires_original_list_item(i)),
|
2021-07-14 23:54:22 -07:00
|
|
|
);
|
|
|
|
|
});
|
2022-05-17 19:32:51 +02:00
|
|
|
self.connect(index, Target::wire(row, gate.wires_insertion_index()));
|
2021-08-24 08:25:11 +02:00
|
|
|
self.connect_extension(
|
2021-07-14 23:54:22 -07:00
|
|
|
element,
|
2022-05-17 19:32:51 +02:00
|
|
|
ExtensionTarget::from_range(row, gate.wires_element_to_insert()),
|
2021-07-14 23:54:22 -07:00
|
|
|
);
|
2021-06-30 07:08:36 -07:00
|
|
|
|
2021-07-15 13:57:50 -07:00
|
|
|
(0..=v.len())
|
2022-05-17 19:32:51 +02:00
|
|
|
.map(|i| ExtensionTarget::from_range(row, gate.wires_output_list_item(i)))
|
2021-07-15 13:57:50 -07:00
|
|
|
.collect::<Vec<_>>()
|
2021-06-16 10:43:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
2021-07-14 23:54:22 -07:00
|
|
|
|
2021-06-16 10:43:18 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
2021-07-18 23:14:48 -07:00
|
|
|
use anyhow::Result;
|
2022-11-03 08:26:03 -07:00
|
|
|
use plonky2::field::types::{Field, Sample};
|
2021-12-28 11:51:13 -08:00
|
|
|
use plonky2::iop::witness::PartialWitness;
|
|
|
|
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
|
|
|
|
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
2021-07-18 23:14:48 -07:00
|
|
|
|
2021-06-16 10:43:18 +02:00
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
fn real_insert<const D: usize>(
|
|
|
|
|
index: usize,
|
|
|
|
|
element: ExtensionTarget<D>,
|
|
|
|
|
v: &[ExtensionTarget<D>],
|
|
|
|
|
) -> Vec<ExtensionTarget<D>> {
|
|
|
|
|
let mut res = v.to_vec();
|
|
|
|
|
res.insert(index, element);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-18 23:14:48 -07:00
|
|
|
fn test_insert_given_len(len_log: usize) -> Result<()> {
|
2021-11-05 10:56:23 +01:00
|
|
|
const D: usize = 2;
|
|
|
|
|
type C = PoseidonGoldilocksConfig;
|
|
|
|
|
type F = <C as GenericConfig<D>>::F;
|
|
|
|
|
type FF = <C as GenericConfig<D>>::FE;
|
2021-06-16 10:43:18 +02:00
|
|
|
let len = 1 << len_log;
|
2021-11-03 14:30:32 -07:00
|
|
|
let config = CircuitConfig::standard_recursion_config();
|
2021-08-20 11:56:57 +02:00
|
|
|
let pw = PartialWitness::new();
|
2021-11-05 10:56:23 +01:00
|
|
|
let mut builder = CircuitBuilder::<F, D>::new(config);
|
2021-06-16 10:43:18 +02:00
|
|
|
let v = (0..len - 1)
|
|
|
|
|
.map(|_| builder.constant_extension(FF::rand()))
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
|
|
for i in 0..len {
|
|
|
|
|
let it = builder.constant(F::from_canonical_usize(i));
|
|
|
|
|
let elem = builder.constant_extension(FF::rand());
|
|
|
|
|
let inserted = real_insert(i, elem, &v);
|
|
|
|
|
let purported_inserted = builder.insert(it, elem, v.clone());
|
|
|
|
|
|
2021-07-12 12:16:13 -07:00
|
|
|
assert_eq!(inserted.len(), purported_inserted.len());
|
|
|
|
|
|
2021-06-16 10:43:18 +02:00
|
|
|
for (x, y) in inserted.into_iter().zip(purported_inserted) {
|
2021-08-24 08:25:11 +02:00
|
|
|
builder.connect_extension(x, y);
|
2021-06-16 10:43:18 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-05 10:56:23 +01:00
|
|
|
let data = builder.build::<C>();
|
2021-08-06 15:14:38 +02:00
|
|
|
let proof = data.prove(pw)?;
|
2021-07-08 15:13:29 +02:00
|
|
|
|
2021-12-28 11:51:13 -08:00
|
|
|
data.verify(proof)
|
2021-06-16 10:43:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-07-18 23:14:48 -07:00
|
|
|
fn test_insert() -> Result<()> {
|
2021-06-16 10:43:18 +02:00
|
|
|
for len_log in 1..3 {
|
2021-07-18 23:14:48 -07:00
|
|
|
test_insert_given_len(len_log)?;
|
2021-06-16 10:43:18 +02:00
|
|
|
}
|
2021-07-18 23:14:48 -07:00
|
|
|
Ok(())
|
2021-06-14 15:15:22 +02:00
|
|
|
}
|
|
|
|
|
}
|