Skip to content

Commit

Permalink
WIP started work on recursive executor
Browse files Browse the repository at this point in the history
  • Loading branch information
robinhundt committed Mar 26, 2024
1 parent 2166cfa commit 419e45f
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 23 deletions.
2 changes: 1 addition & 1 deletion crates/seec/src/circuit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub mod builder;
pub(crate) mod circuit_connections;
pub mod dyn_layers;
pub mod static_layers;
mod sub_circuit;
pub(crate) mod sub_circuit;

pub use crate::protocols::boolean_gmw::BooleanGate;
use crate::protocols::Gate;
Expand Down
54 changes: 32 additions & 22 deletions crates/seec/src/circuit/sub_circuit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::circuit::{base_circuit, BaseCircuit, GateIdx};
use crate::circuit::{base_circuit, BaseCircuit, GateIdx, LayerIterable};
use crate::protocols::Gate;
use crate::GateId;
use ahash::HashMap;
Expand Down Expand Up @@ -52,7 +52,7 @@ impl<Idx: GateIdx> CallMap<Idx> {
}

#[derive(Debug)]
struct SubCircIter<'base, G, Idx: GateIdx> {
pub(crate) struct SubCircIter<'base, G, Idx: GateIdx> {
circ: &'base Circuit<G, Idx>,
base_iter: base_circuit::BaseLayerIter<'base, G, Idx, ()>,
sub_circ_iters: HashMap<CallId, ChildOrParent<Self>>,
Expand Down Expand Up @@ -103,16 +103,38 @@ impl<'base, G: Gate, Idx: GateIdx> ChildOrParent<SubCircIter<'base, G, Idx>> {
}
}

struct SubCircLayer<'sc_iter, 'base, G, Idx: GateIdx> {
pub(crate) struct SubCircLayer<'sc_iter, 'base, G, Idx: GateIdx> {
/// CallId for the sub-circuit of this layer from the callers perspective
call_id: CallId,
base_layer: base_circuit::CircuitLayer<G, Idx>,
pub(crate) call_id: CallId,
pub(crate) base_layer: base_circuit::CircuitLayer<G, Idx>,
sub_circ_iter: &'sc_iter mut SubCircIter<'base, G, Idx>,
dealloc: Vec<CallId>,
}

impl<'base, G: Gate, Idx: GateIdx> SubCircIter<'base, G, Idx> {
fn next(&mut self) -> Option<SubCircLayer<'_, 'base, G, Idx>> {
pub fn new_main(circ: &'base Circuit<G, Idx>) -> Self {
let mut main_base_iter = circ
.base_circuits
.get(0)
.expect("circ has no main circuit")
.layer_iter();
// because in our next implementation we have reversed the order of processing
// to_visit and swap, we call swap at the beginning so that the initial gates are
// present in to_visit
main_base_iter.swap_next_layer();
let (tx, rx) = mpsc::channel();
SubCircIter {
circ: &circ,
base_iter: main_base_iter,
sub_circ_iters: Default::default(),
sub_circuit: circ.main.clone(),
own_returned_gates_tx: tx,
own_returned_gates_rx: rx,
parent_returned_gates_tx: None,
}
}

pub(crate) fn next(&mut self) -> Option<SubCircLayer<'_, 'base, G, Idx>> {
// If self.base_iter is exhausted all sub circ iterators must have finished as their
// outputs feed back into this sub circuit
if self.base_iter.is_exhausted() {
Expand Down Expand Up @@ -168,21 +190,21 @@ impl<'base, G: Gate, Idx: GateIdx> SubCircIter<'base, G, Idx> {
}

impl<'sc_iter, 'base, G, Idx: GateIdx> SubCircLayer<'sc_iter, 'base, G, Idx> {
fn sub_layer_iter(&mut self) -> SubLayerIter<'_, 'base, G, Idx> {
pub(crate) fn sub_layer_iter(&mut self) -> SubLayerIter<'_, 'base, G, Idx> {
SubLayerIter {
to_dealloc: &mut self.dealloc,
iter: self.sub_circ_iter.sub_circ_iters.iter_mut(),
}
}

fn dealloc_exhausted_iters(&mut self) {
pub(crate) fn dealloc_exhausted_iters(&mut self) {
for call_id in self.dealloc.drain(..) {
self.sub_circ_iter.sub_circ_iters.remove(&call_id);
}
}
}

struct SubLayerIter<'a, 'base, G, Idx: GateIdx> {
pub(crate) struct SubLayerIter<'a, 'base, G, Idx: GateIdx> {
to_dealloc: &'a mut Vec<CallId>,
iter: hash_map::IterMut<'a, CallId, ChildOrParent<SubCircIter<'base, G, Idx>>>,
}
Expand Down Expand Up @@ -255,7 +277,6 @@ impl<'sc_iter, 'base, G: Debug, Idx: GateIdx> Debug for SubCircLayer<'sc_iter, '
// handle_layer(layer)
//


#[cfg(test)]
mod tests {
use crate::circuit::sub_circuit::{
Expand Down Expand Up @@ -340,18 +361,7 @@ mod tests {
base_circuits: vec![main, bc1, bc2],
main: main_sc,
};
let mut main_base_iter = circ.base_circuits[0].layer_iter();
main_base_iter.swap_next_layer();
let (tx, rx) = mpsc::channel();
let mut sc_iter = SubCircIter {
circ: &circ,
base_iter: main_base_iter,
sub_circ_iters: Default::default(),
sub_circuit: circ.main.clone(),
own_returned_gates_tx: tx,
own_returned_gates_rx: rx,
parent_returned_gates_tx: None,
};
let mut sc_iter = SubCircIter::new_main(&circ);

fn handle_layer<'sc_iter, 'base, G: Gate, Idx: GateIdx>(
mut layer: SubCircLayer<'sc_iter, 'base, G, Idx>,
Expand Down
1 change: 1 addition & 0 deletions crates/seec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ pub mod parse;
pub mod private_test_utils;
pub mod protocols;
pub mod secret;
pub mod sub_circ_executor;
pub(crate) mod utils;
79 changes: 79 additions & 0 deletions crates/seec/src/sub_circ_executor/layer_executor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use crate::circuit::sub_circuit::{SubCircIter, SubCircLayer};
use crate::circuit::{base_circuit, GateIdx};
use crate::executor::DynFDSetup;
use crate::protocols::{Protocol, ShareStorage};
use crate::sub_circ_executor::storage::Storage;
use std::mem;
use std::ops::Range;

pub enum LayerExecutor<P: Protocol, Idx: GateIdx> {
ConstructMsg {
base_layer: base_circuit::CircuitLayer<P::Gate, Idx>,
sub_executors: Vec<Self>,
},
ProcessMsg {
base_layer: base_circuit::CircuitLayer<P::Gate, Idx>,
setup: P::SetupStorage,
sub_executors: Vec<Self>,
msg_range: Range<usize>,
},
}

impl<P: Protocol, Idx: GateIdx> LayerExecutor<P, Idx> {
async fn construct_msg(
&mut self,
layer: &mut SubCircLayer<'_, '_, P::Gate, Idx>,
storage: &mut Storage<P::ShareStorage>,
setup: &mut DynFDSetup<'_, P, Idx>,
msg_buf: &mut (),
) {
match self {
LayerExecutor::ConstructMsg {
base_layer,
sub_executors,
} => {
// handle the non-interactive part of base_layer
// drop non-interactive part
let setup_data = setup.request_setup_output(42).await.unwrap();
// handle interactive part, write msg to msg_buf -> record msg offset
// change self type to process_msg

for mut sub_layer in layer.sub_layer_iter() {
let mut sub_executor = LayerExecutor::ConstructMsg {
base_layer: mem::take(&mut sub_layer.base_layer),
sub_executors: vec![],
};
let sub_storage = storage.sub_storage_mut(sub_layer.call_id);
sub_executor
.construct_msg(&mut sub_layer, sub_storage, setup, msg_buf)
.await;
sub_executors.push(sub_executor);
}
}
LayerExecutor::ProcessMsg { .. } => {
unreachable!()
}
}

todo!()
}

fn process_msg(
&mut self,
storage: &mut Storage<P::ShareStorage>,
own_msg_buf: &mut (),
other_msg_buf: &mut (),
) {
todo!()
}
}

// impl LayerExecutor {
// fn handle_before() {
// handle_non_interactive(layer)
// let msg_idx = handle_interactive(layer, &mut msg_buf)
// for sub_layer in layer:
// sub_executor = LayerExecutor::BeforeInteractive { layer: sub_layer, ... }
// sub_executor.handle_before()
// self.sub_executors.push(sub_executor)
// }
59 changes: 59 additions & 0 deletions crates/seec/src/sub_circ_executor/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::circuit::sub_circuit::SubCircIter;
use crate::circuit::{sub_circuit, GateIdx};
use crate::errors::ExecutorError;
use crate::executor::DynFDSetup;
use crate::protocols::Protocol;
use crate::sub_circ_executor::storage::{ScalarOrSimd, Storage};
use seec_channel::{Receiver, Sender};
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};

mod layer_executor;
mod storage;

pub struct PartyId(pub usize);

pub struct Executor<'c, P: Protocol, Idx> {
circuit: &'c sub_circuit::Circuit<P::Gate, Idx>,
setup: DynFDSetup<'c, P, Idx>,
layer_executor: LayerExecutor<P>,
}

struct LayerExecutor<P: Protocol> {
protocol_state: P,
storage: Storage<P::ShareStorage>,
party_id: PartyId,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct ExecutorMsg<Msg, SimdMsg> {
scalar: Msg,
simd: Option<SimdMsg>,
}

pub type Message<P> = ExecutorMsg<<P as Protocol>::Msg, <P as Protocol>::SimdMsg>;

impl<'c, P: Protocol, Idx: GateIdx> Executor<'c, P, Idx> {
#[tracing::instrument(skip_all, fields(party_id = %self.layer_executor.party_id), err)]
pub async fn execute(
&mut self,
inputs: ScalarOrSimd<P::ShareStorage>,
sender: &mut Sender<Message<P>>,
receiver: &mut Receiver<Message<P>>,
) -> Result<ScalarOrSimd<P::ShareStorage>, ExecutorError> {
let mut main_iter = SubCircIter::new_main(&self.circuit);

while let Some(layer) = main_iter.next() {}
todo!()
}
}

impl<P: Protocol> LayerExecutor<P> {
fn handle_layer(&mut self) {}
}

impl Display for PartyId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
25 changes: 25 additions & 0 deletions crates/seec/src/sub_circ_executor/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::circuit::sub_circuit::CallId;
use crate::circuit::GateIdx;
use crate::GateId;
use serde::{Deserialize, Serialize};
use std::ops::Index;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ScalarOrSimd<Shares> {
Scalar(Shares),
Simd(Vec<Shares>),
}

pub struct Storage<Shares> {
own: ScalarOrSimd<Shares>,
sub_circuit: Vec<Storage<Shares>>,
}

impl<Shares> Storage<Shares> {
pub(crate) fn sub_storage_mut(&mut self, call_id: CallId) -> &mut Self {
let CallId::Call(id) = call_id else {
panic!("Can't index storage with CallId::Ret")
};
&mut self.sub_circuit[id as usize]
}
}

0 comments on commit 419e45f

Please sign in to comment.