From 419e45fd77fac5323e91ae714bcb08a20232efb4 Mon Sep 17 00:00:00 2001 From: Robin Hundt <24554122+robinhundt@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:10:23 +0100 Subject: [PATCH] WIP started work on recursive executor --- crates/seec/src/circuit/mod.rs | 2 +- crates/seec/src/circuit/sub_circuit.rs | 54 +++++++------ crates/seec/src/lib.rs | 1 + .../src/sub_circ_executor/layer_executor.rs | 79 +++++++++++++++++++ crates/seec/src/sub_circ_executor/mod.rs | 59 ++++++++++++++ crates/seec/src/sub_circ_executor/storage.rs | 25 ++++++ 6 files changed, 197 insertions(+), 23 deletions(-) create mode 100644 crates/seec/src/sub_circ_executor/layer_executor.rs create mode 100644 crates/seec/src/sub_circ_executor/mod.rs create mode 100644 crates/seec/src/sub_circ_executor/storage.rs diff --git a/crates/seec/src/circuit/mod.rs b/crates/seec/src/circuit/mod.rs index 69e28d5..9ca6287 100644 --- a/crates/seec/src/circuit/mod.rs +++ b/crates/seec/src/circuit/mod.rs @@ -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; diff --git a/crates/seec/src/circuit/sub_circuit.rs b/crates/seec/src/circuit/sub_circuit.rs index 55947a4..a0d82bc 100644 --- a/crates/seec/src/circuit/sub_circuit.rs +++ b/crates/seec/src/circuit/sub_circuit.rs @@ -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; @@ -52,7 +52,7 @@ impl CallMap { } #[derive(Debug)] -struct SubCircIter<'base, G, Idx: GateIdx> { +pub(crate) struct SubCircIter<'base, G, Idx: GateIdx> { circ: &'base Circuit, base_iter: base_circuit::BaseLayerIter<'base, G, Idx, ()>, sub_circ_iters: HashMap>, @@ -103,16 +103,38 @@ impl<'base, G: Gate, Idx: GateIdx> ChildOrParent> { } } -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, + pub(crate) call_id: CallId, + pub(crate) base_layer: base_circuit::CircuitLayer, sub_circ_iter: &'sc_iter mut SubCircIter<'base, G, Idx>, dealloc: Vec, } impl<'base, G: Gate, Idx: GateIdx> SubCircIter<'base, G, Idx> { - fn next(&mut self) -> Option> { + pub fn new_main(circ: &'base Circuit) -> 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> { // 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() { @@ -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, iter: hash_map::IterMut<'a, CallId, ChildOrParent>>, } @@ -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::{ @@ -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>, diff --git a/crates/seec/src/lib.rs b/crates/seec/src/lib.rs index 3585236..bcb1cf8 100644 --- a/crates/seec/src/lib.rs +++ b/crates/seec/src/lib.rs @@ -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; diff --git a/crates/seec/src/sub_circ_executor/layer_executor.rs b/crates/seec/src/sub_circ_executor/layer_executor.rs new file mode 100644 index 0000000..9caf3cf --- /dev/null +++ b/crates/seec/src/sub_circ_executor/layer_executor.rs @@ -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 { + ConstructMsg { + base_layer: base_circuit::CircuitLayer, + sub_executors: Vec, + }, + ProcessMsg { + base_layer: base_circuit::CircuitLayer, + setup: P::SetupStorage, + sub_executors: Vec, + msg_range: Range, + }, +} + +impl LayerExecutor { + async fn construct_msg( + &mut self, + layer: &mut SubCircLayer<'_, '_, P::Gate, Idx>, + storage: &mut Storage, + 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, + 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) +// } diff --git a/crates/seec/src/sub_circ_executor/mod.rs b/crates/seec/src/sub_circ_executor/mod.rs new file mode 100644 index 0000000..b3810c7 --- /dev/null +++ b/crates/seec/src/sub_circ_executor/mod.rs @@ -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, + setup: DynFDSetup<'c, P, Idx>, + layer_executor: LayerExecutor

, +} + +struct LayerExecutor { + protocol_state: P, + storage: Storage, + party_id: PartyId, +} + +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct ExecutorMsg { + scalar: Msg, + simd: Option, +} + +pub type Message

= ExecutorMsg<

::Msg,

::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, + sender: &mut Sender>, + receiver: &mut Receiver>, + ) -> Result, ExecutorError> { + let mut main_iter = SubCircIter::new_main(&self.circuit); + + while let Some(layer) = main_iter.next() {} + todo!() + } +} + +impl LayerExecutor

{ + fn handle_layer(&mut self) {} +} + +impl Display for PartyId { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} diff --git a/crates/seec/src/sub_circ_executor/storage.rs b/crates/seec/src/sub_circ_executor/storage.rs new file mode 100644 index 0000000..092d640 --- /dev/null +++ b/crates/seec/src/sub_circ_executor/storage.rs @@ -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 { + Scalar(Shares), + Simd(Vec), +} + +pub struct Storage { + own: ScalarOrSimd, + sub_circuit: Vec>, +} + +impl Storage { + 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] + } +}