Skip to content

Commit

Permalink
Inner Value not just for inner uses
Browse files Browse the repository at this point in the history
  • Loading branch information
rebenkoy committed Nov 22, 2023
1 parent 6674f62 commit 3584e61
Show file tree
Hide file tree
Showing 7 changed files with 869 additions and 739 deletions.
6 changes: 4 additions & 2 deletions benches/bench_ecmul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ pub fn ecmul_pseudo_fold(c: &mut Criterion) {

assemble_ecmul_circuit(&mut circuit, &pi, num_limbs);

let mut instance = circuit.finalize();
let constructed = circuit.finalize();
let mut instance = constructed.spawn();

let pi_a_ext = (pi[0], pi[1]);
let pi_b_ext = (pi[2], pi[3]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band
Expand Down Expand Up @@ -141,7 +142,8 @@ pub fn ecmul_msm(c: &mut Criterion) {

assemble_ecmul_circuit(&mut circuit, &pi, num_limbs);

let mut instance = circuit.finalize();
let constructed = circuit.finalize();
let mut instance = constructed.spawn();

let pi_a_ext = (pi[0], pi[1]);
let pi_b_ext = (pi[2], pi[3]); // a*(1+9+...+9^{nl-1})+b=0 must be checked out of band
Expand Down
6 changes: 4 additions & 2 deletions benches/bench_poseidons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ pub fn poseidons_pseudo_fold(c: &mut Criterion) {

assemble_poseidon_circuit(&mut circuit, &cfg, pi);

let mut instance = circuit.finalize();
let constructed = circuit.finalize();
let mut instance = constructed.spawn();

instance.set_ext(pi, F::random(OsRng));
instance.execute(0);
Expand Down Expand Up @@ -99,7 +100,8 @@ pub fn poseidons_msm(c: &mut Criterion) {
let pi = circuit.ext_val(1)[0];
assemble_poseidon_circuit(&mut circuit, &cfg, pi);

let mut instance = circuit.finalize();
let constructed = circuit.finalize();
let mut instance = constructed.spawn();

instance.set_ext(pi, F::random(OsRng));
instance.execute(0);
Expand Down
32 changes: 15 additions & 17 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{rc::{Rc, Weak}, marker::PhantomData, iter::repeat_with, cell::RefCell}
use elsa::map::FrozenMap;
use ff::PrimeField;

use crate::{witness::CSWtns, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub} };
use crate::{witness::CSWtns, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub}, external_interface::{RunIndex, RunAllocator} };

use self::circuit_operations::CircuitOperation;

Expand Down Expand Up @@ -310,7 +310,7 @@ where
pub fn finalize(self) -> ConstructedCircuit<'circuit, F, G> {
ConstructedCircuit {
circuit: self,
num_runs: RefCell::new(0),
run_allocator: RefCell::new(RunAllocator::new()),
}
}

Expand All @@ -323,33 +323,24 @@ where
}
}

pub struct RunIndex {
idx: usize,
}

impl RunIndex {
fn new(idx: usize) -> Self {
Self {
idx,
}
}
}

pub struct ConstructedCircuit<'circuit, F: PrimeField, G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>> {
circuit: Circuit<'circuit, F, G>,
num_runs: RefCell<usize>,
run_allocator: RefCell<RunAllocator>,
}

impl<'circuit, F: PrimeField, G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>> ConstructedCircuit<'circuit, F, G> {
pub fn spawn<'constructed>(&'constructed self) -> CircuitRun<'constructed, 'circuit, F, G> {
*self.num_runs.borrow_mut() += 1;
CircuitRun {
constructed: &self,
cs: CSWtns::<F,G>::new(&self.circuit.cs),
round_counter: 0,
run_idx: RunIndex::new(*self.num_runs.borrow() - 1),
run_idx: self.run_allocator.borrow_mut().allocate(),
}
}

fn deallocate<'constructed>(&'constructed self, idx: RunIndex) {
self.run_allocator.borrow_mut().deallocate(idx);
}
}

pub struct CircuitRun<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From<PolyOp<'circuit, F>>>{
Expand Down Expand Up @@ -393,5 +384,12 @@ where
pub fn iter_constraints(&self) -> impl Iterator<Item = &Constraint<'circuit, F, G>> {
self.constructed.circuit.cs.iter_constraints()
}

pub fn finish(self) -> (CSWtns<'circuit, F, G>, &'constructed ConstraintSystem<'circuit, F, G>) {
let Self {constructed, cs, round_counter: _, run_idx} = self;

constructed.deallocate(run_idx);
(cs, &constructed.circuit.cs)
}
}

105 changes: 105 additions & 0 deletions src/external_interface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use std::{cell::RefCell, rc::Rc};

pub struct RunAllocator {
free_slots: Vec<usize>,
total_spawned: usize,
active: usize,
allocated: usize,
}

impl RunAllocator {
pub fn new() -> Self {
Self { free_slots: vec![], total_spawned: 0, active: 0, allocated: 0 }
}

pub fn allocate(&mut self) -> RunIndex {
let slot = self.free_slots.pop().unwrap_or_else(|| {
self.allocated += 1;
self.allocated - 1
});
self.active += 1;
self.total_spawned += 1;
RunIndex { muid: self.total_spawned - 1, slot }
}

pub fn deallocate(&mut self, idx: RunIndex) {
self.free_slots.push(idx.slot);
self.active -= 1;
}
}

#[derive(Debug)]
pub struct RunIndex {
pub(crate) muid: usize,
pub(crate) slot: usize,
}

struct CuratedSlot<T> {
value: T,
muid: usize,
}

#[derive(Clone)]
pub struct InnerValue<T: Clone> {
data: Rc<RefCell<Vec<Option<CuratedSlot<T>>>>>
}

impl<T: Clone> InnerValue<T> {
pub fn new() -> Self {
Self {
data: Rc::new(RefCell::new(vec![])),
}
}

pub fn get(&self, idx: &RunIndex) -> Option<T> {
match self.data.borrow().get(idx.slot) {
Some(opt) => match opt {
Some(CuratedSlot{value, muid}) => match muid == &idx.muid {
true => Some(value.clone()),
false => match muid < &idx.muid {
true => None,
false => panic!("Accessing value with muid {} by idx: {:?}", muid, idx),
},
},
None => None,
},
None => None,
}

}

pub fn set(&self, idx: &RunIndex, value: T) {
assert!(self.replace(idx, value).is_none(), "Attempting to set value by idx: {:?}, but is already set", idx)
}

#[must_use = "if you intended to set a value, consider `set` method instead"]
pub fn replace(&self, idx: &RunIndex, value: T) -> Option<T> {
let mut data = self.data.borrow_mut();
if data.len() <= idx.slot {
data.resize_with(idx.slot + 1, || None);
}
match data[idx.slot] {
Some(CuratedSlot{muid, value: _}) => assert!(muid <= idx.muid, "Writing value with muid {} by idx: {:?}", muid, idx),
None => (),
}
data[idx.slot].replace(CuratedSlot { value: value.clone(), muid: idx.muid }).and_then(|CuratedSlot{value, muid}| if muid == idx.muid {Some(value)} else {None})
}
}


#[test]
fn normal_usage() {
let x = InnerValue::new();

x.set(&RunIndex { muid: 0, slot: 0 }, 0);
x.set(&RunIndex { muid: 1, slot: 1 }, 1);
x.set(&RunIndex { muid: 2, slot: 2 }, 2);
assert_eq!(x.get(&RunIndex { muid: 0, slot: 0 }), Some(0));
assert_eq!(x.get(&RunIndex { muid: 1, slot: 1 }), Some(1));
assert_eq!(x.get(&RunIndex { muid: 2, slot: 2 }), Some(2));
assert_eq!(x.get(&RunIndex { muid: 3, slot: 0 }), None);
x.set(&RunIndex { muid: 3, slot: 0 }, 3);
assert_eq!(x.get(&RunIndex { muid: 3, slot: 0 }), Some(3));
assert_eq!(x.replace(&RunIndex { muid: 1, slot: 1 }, 5), Some(1))
}

Loading

0 comments on commit 3584e61

Please sign in to comment.