From afae54fc81639aa574e56743d25eade97a9a4d02 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 20:48:03 -0800 Subject: [PATCH 01/13] Context trait Need to clean up the following * Remove `bind` * Relax `narrow` * Introduce a small context struct that clone will refer to --- src/protocol/attribution/accumulate_credit.rs | 5 +- src/protocol/boolean/bitwise_lt.rs | 10 +- src/protocol/boolean/bitwise_sum.rs | 4 +- src/protocol/boolean/carries.rs | 10 +- src/protocol/boolean/or.rs | 4 +- src/protocol/boolean/prefix_or.rs | 16 +- src/protocol/boolean/xor.rs | 4 +- src/protocol/check_zero.rs | 4 +- src/protocol/context.rs | 453 ++++++++++++++---- src/protocol/context_traits.rs | 7 +- src/protocol/malicious.rs | 6 +- .../modulus_conversion/convert_shares.rs | 10 +- .../modulus_conversion/specialized_mul.rs | 6 +- src/protocol/mul/malicious.rs | 5 +- src/protocol/mul/mod.rs | 6 +- src/protocol/mul/semi_honest.rs | 8 +- src/protocol/reveal/mod.rs | 15 +- src/protocol/sort/bit_permutation.rs | 9 +- src/protocol/sort/compose.rs | 3 +- .../sort/generate_sort_permutation.rs | 7 +- src/protocol/sort/reshare.rs | 3 +- src/protocol/sort/secureapplyinv.rs | 3 +- src/protocol/sort/shuffle.rs | 10 +- src/test_fixture/circuit.rs | 1 + src/test_fixture/mod.rs | 15 +- 25 files changed, 455 insertions(+), 169 deletions(-) diff --git a/src/protocol/attribution/accumulate_credit.rs b/src/protocol/attribution/accumulate_credit.rs index a4a7ed1eb..cccdfdb9c 100644 --- a/src/protocol/attribution/accumulate_credit.rs +++ b/src/protocol/attribution/accumulate_credit.rs @@ -12,6 +12,7 @@ use crate::{ }; use futures::future::{try_join, try_join_all}; use std::iter::{repeat, zip}; +use crate::protocol::context::SemiHonestProtocolContext; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum Step { @@ -54,7 +55,7 @@ impl<'a, F: Field> AccumulateCredit<'a, F> { #[allow(dead_code)] pub async fn execute( &self, - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, ) -> Result>, Error> { #[allow(clippy::cast_possible_truncation)] let num_rows = self.input.len() as RecordIndex; @@ -160,7 +161,7 @@ impl<'a, F: Field> AccumulateCredit<'a, F> { } async fn get_accumulated_credit( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, current: AccumulateCreditInputRow, successor: AccumulateCreditInputRow, diff --git a/src/protocol/boolean/bitwise_lt.rs b/src/protocol/boolean/bitwise_lt.rs index 42a41bc54..481d65656 100644 --- a/src/protocol/boolean/bitwise_lt.rs +++ b/src/protocol/boolean/bitwise_lt.rs @@ -7,6 +7,7 @@ use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; +use crate::protocol::context::SemiHonestProtocolContext; /// This is an implementation of Bitwise Less-Than on bitwise-shared numbers. /// @@ -39,7 +40,7 @@ impl BitwiseLessThan { async fn step1( a: &[Replicated], b: &[Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let xor = zip(a, b).enumerate().map(|(i, (a_bit, b_bit))| { @@ -67,7 +68,7 @@ impl BitwiseLessThan { /// ``` async fn step2( e: &mut [Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { e.reverse(); @@ -107,7 +108,7 @@ impl BitwiseLessThan { async fn step5( g: &[Replicated], b: &[Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let mul = zip(repeat(ctx), zip(g, b)) @@ -130,7 +131,7 @@ impl BitwiseLessThan { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &[Replicated], b: &[Replicated], @@ -176,6 +177,7 @@ mod tests { }; use futures::future::try_join_all; use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, RngCore}; + use crate::protocol::context::ProtocolContext; /// From `Vec<[Replicated; 3]>`, create `Vec>` taking `i`'th share per row fn transpose(x: &[[Replicated; 3]], i: usize) -> Vec> { diff --git a/src/protocol/boolean/bitwise_sum.rs b/src/protocol/boolean/bitwise_sum.rs index 54799753c..869926447 100644 --- a/src/protocol/boolean/bitwise_sum.rs +++ b/src/protocol/boolean/bitwise_sum.rs @@ -2,6 +2,7 @@ use super::carries::Carries; use crate::error::BoxError; use crate::ff::Field; use crate::protocol::{context::ProtocolContext, RecordId}; +use crate::protocol::context::SemiHonestProtocolContext; use crate::secret_sharing::Replicated; /// This is an implementation of Bitwise Sum on bitwise-shared numbers. @@ -31,7 +32,7 @@ impl BitwiseSum { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &[Replicated], b: &[Replicated], @@ -91,6 +92,7 @@ mod tests { }; use futures::future::try_join_all; use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, Rng, RngCore}; + use crate::protocol::context::ProtocolContext; /// From `Vec<[Replicated; 3]>`, create `Vec>` taking the `i`'th share per row fn transpose(x: &[[Replicated; 3]], i: usize) -> Vec> { diff --git a/src/protocol/boolean/carries.rs b/src/protocol/boolean/carries.rs index ed75e127a..2004f0d31 100644 --- a/src/protocol/boolean/carries.rs +++ b/src/protocol/boolean/carries.rs @@ -5,6 +5,7 @@ use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; +use crate::protocol::context::SemiHonestProtocolContext; #[derive(Clone, Debug)] /// This struct represents set/propagate/kill bits used to compute the carries. @@ -38,7 +39,7 @@ impl Carries { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &[Replicated], b: &[Replicated], @@ -66,7 +67,7 @@ impl Carries { async fn step1( a: &[Replicated], b: &[Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let mul = zip(repeat(ctx), zip(a, b)) @@ -123,7 +124,7 @@ impl Carries { /// computes `([f_0],...,[f_l]) ← PRE○([e_0],...,[e_l])`. async fn step3( e: &[CarryPropagationShares], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let l = e.len(); @@ -149,7 +150,7 @@ impl Carries { #[allow(clippy::many_single_char_names)] async fn fan_in_carry_propagation( e: &[CarryPropagationShares], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result, Error> { let l = e.len(); @@ -238,6 +239,7 @@ mod tests { }; use futures::future::try_join_all; use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, RngCore}; + use crate::protocol::context::ProtocolContext; /// From `Vec<[Replicated; 3]>`, create `Vec>` taking `i`'th share per row fn transpose(x: &[[Replicated; 3]], i: usize) -> Vec> { diff --git a/src/protocol/boolean/or.rs b/src/protocol/boolean/or.rs index c057e8310..7078a375f 100644 --- a/src/protocol/boolean/or.rs +++ b/src/protocol/boolean/or.rs @@ -1,12 +1,13 @@ use crate::error::Error; use crate::ff::Field; use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; +use crate::protocol::context::SemiHonestProtocolContext; use crate::secret_sharing::Replicated; /// Secure XOR protocol with two inputs, `a, b ∈ {0,1} ⊆ F_p`. /// It computes `[a] + [b] - 2[ab]` pub async fn or( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -27,6 +28,7 @@ mod tests { }; use futures::future::try_join_all; use rand::rngs::mock::StepRng; + use crate::protocol::context::ProtocolContext; async fn or_fp31(a: Fp31, b: Fp31) -> Result { let world: TestWorld = make_world(QueryId); diff --git a/src/protocol/boolean/prefix_or.rs b/src/protocol/boolean/prefix_or.rs index aaf45b28b..d46b28237 100644 --- a/src/protocol/boolean/prefix_or.rs +++ b/src/protocol/boolean/prefix_or.rs @@ -5,6 +5,7 @@ use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; +use crate::protocol::context::SemiHonestProtocolContext; /// This is an implementation of Prefix-Or on bitwise-shared numbers. /// @@ -27,7 +28,7 @@ impl PrefixOr { async fn block_or( a: &[Replicated], k: usize, - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result, Error> { #[allow(clippy::cast_possible_truncation)] @@ -53,7 +54,7 @@ impl PrefixOr { async fn step1( a: &[Replicated], lambda: usize, - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let mut futures = Vec::with_capacity(lambda); @@ -74,7 +75,7 @@ impl PrefixOr { /// ``` async fn step2( x: &[Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = x.len(); @@ -116,7 +117,7 @@ impl PrefixOr { async fn step5( f: &[Replicated], a: &[Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = f.len(); @@ -160,7 +161,7 @@ impl PrefixOr { /// ``` async fn step7( c: &[Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = c.len(); @@ -186,7 +187,7 @@ impl PrefixOr { async fn step8( f: &[Replicated], b: &[Replicated], - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = f.len(); @@ -227,7 +228,7 @@ impl PrefixOr { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, input: &[Replicated], ) -> Result>, Error> { @@ -314,6 +315,7 @@ mod tests { use rand::distributions::{Distribution, Standard}; use rand::{rngs::mock::StepRng, Rng}; use std::iter::zip; + use crate::protocol::context::ProtocolContext; const BITS: [usize; 2] = [16, 32]; const TEST_TRIES: usize = 16; diff --git a/src/protocol/boolean/xor.rs b/src/protocol/boolean/xor.rs index b4f39e5dd..09cf05895 100644 --- a/src/protocol/boolean/xor.rs +++ b/src/protocol/boolean/xor.rs @@ -1,12 +1,13 @@ use crate::error::Error; use crate::ff::Field; use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; +use crate::protocol::context::SemiHonestProtocolContext; use crate::secret_sharing::Replicated; /// Secure XOR protocol with two inputs, `a, b ∈ {0,1} ⊆ F_p`. /// It computes `[a] + [b] - 2[ab]` pub async fn xor( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -26,6 +27,7 @@ mod tests { }; use futures::future::try_join_all; use rand::rngs::mock::StepRng; + use crate::protocol::context::ProtocolContext; async fn xor_fp31(a: Fp31, b: Fp31) -> Result { let world: TestWorld = make_world(QueryId); diff --git a/src/protocol/check_zero.rs b/src/protocol/check_zero.rs index e3a392972..044017916 100644 --- a/src/protocol/check_zero.rs +++ b/src/protocol/check_zero.rs @@ -7,6 +7,7 @@ use crate::{ secret_sharing::Replicated, }; use serde::{Deserialize, Serialize}; +use crate::protocol::context::SemiHonestProtocolContext; /// A message sent by each helper when they've multiplied their own shares #[derive(Debug, Serialize, Deserialize, Default)] @@ -62,7 +63,7 @@ impl AsRef for Step { /// back via the error response #[allow(dead_code)] pub async fn check_zero( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, v: &Replicated, ) -> Result { @@ -87,6 +88,7 @@ pub mod tests { use crate::ff::{Field, Fp31}; use crate::protocol::{check_zero::check_zero, QueryId, RecordId}; use crate::test_fixture::{make_contexts, make_world, share, TestWorld}; + use crate::protocol::context::ProtocolContext; #[tokio::test] async fn basic() -> Result<(), Error> { diff --git a/src/protocol/context.rs b/src/protocol/context.rs index d2b744f8e..e3587a787 100644 --- a/src/protocol/context.rs +++ b/src/protocol/context.rs @@ -13,166 +13,190 @@ use crate::{ }, protocol::{malicious::SecurityValidatorAccumulator, prss::Endpoint as PrssEndpoint}, }; +use crate::protocol::context_traits::ShareOfOne; +use crate::protocol::malicious::SecurityValidator; +use crate::protocol::mul::SecureMul; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; -/// Context used by each helper to perform computation. Currently they need access to shared -/// randomness generator (see `Participant`) and communication trait to send messages to each other. + +/// Context used by each helper to perform secure computation. Provides access to shared randomness +/// generator and communication channel. +pub trait ProtocolContext : Clone + + SecureMul>::Share> + + ShareOfOne>::Share> +{ + /// Secret sharing type this context supports. + type Share: SecretSharing; + + /// The role of this context. + fn role(&self) -> Role; + + /// A unique identifier for this stage of the protocol execution. + fn step(&self) -> &Step; + + /// Make a sub-context. + /// Note that each invocation of this should use a unique value of `step`. + #[must_use] + fn narrow(&self, step: &S) -> Self; + + /// Make a sub-context which is bound to a record in case the same step is bound to a different `record_id` + /// # Panics + /// Panics in case the context is already bound to the same `record_id` + fn bind(&self, record_id: RecordId) -> Self; + + /// Get the indexed PRSS instance for this step. It is safe to call this function + /// multiple times. + /// + /// # Panics + /// If `prss_rng()` is invoked for the same context, this will panic. Use of + /// these two functions are mutually exclusive. + #[must_use] + fn prss(&self) -> Arc; + + /// Get a pair of PRSS-based RNGs. The first is shared with the helper to the "left", + /// the second is shared with the helper to the "right". + /// + /// # Panics + /// This method can only be called once. This is also mutually exclusive with `prss()`. + /// This will panic if you have previously invoked `prss()`. + #[must_use] + fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness); + + /// Get a set of communications channels to different peers. + fn mesh(&self) -> Mesh<'_, '_>; +} + +#[derive(Clone, Debug)] +pub struct SemiHonestProtocolContext<'a, F: Field> { + role: Role, + step: Step, + prss: &'a PrssEndpoint, + gateway: &'a Gateway, + record_id: Option, + _field_marker: PhantomData, +} + #[derive(Clone, Debug)] -pub struct ProtocolContext<'a, S, F: Field> { +pub struct MaliciousProtocolContext<'a, F: Field> { role: Role, step: Step, prss: &'a PrssEndpoint, gateway: &'a Gateway, - accumulator: Option>, - r_share: Option>, record_id: Option, - _marker: PhantomData, + accumulator: SecurityValidatorAccumulator, + r_share: Replicated, + // _marker: PhantomData, } -impl<'a, F: Field, SS: SecretSharing> ProtocolContext<'a, SS, F> { + +impl <'a, F: Field> SemiHonestProtocolContext<'a, F> { pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { Self { role, step: Step::default(), prss: participant, gateway, - accumulator: None, - r_share: None, record_id: None, - _marker: PhantomData::default(), + // _share_marker: PhantomData::default(), + _field_marker: PhantomData::default(), } } - /// The role of this context. #[must_use] - pub fn role(&self) -> Role { + pub fn upgrade_to_malicious( + self, + accumulator: SecurityValidatorAccumulator, + r_share: Replicated, + ) -> MaliciousProtocolContext<'a, F> { + let mut ctx = MaliciousProtocolContext::new(self.role, self.prss, self.gateway, accumulator, r_share); + ctx.step = self.step; + + if let Some(record_id) = self.record_id { + ctx.bind(record_id) + } else { + ctx + } + } +} + +impl <'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { + type Share = Replicated; + + fn role(&self) -> Role { self.role } - /// A unique identifier for this stage of the protocol execution. - #[must_use] - pub fn step(&self) -> &Step { + fn step(&self) -> &Step { &self.step } - /// Make a sub-context. - /// Note that each invocation of this should use a unique value of `step`. - #[must_use] - pub fn narrow(&self, step: &S) -> Self { - ProtocolContext { + fn narrow(&self, step: &S) -> Self { + Self { role: self.role, step: self.step.narrow(step), prss: self.prss, gateway: self.gateway, - accumulator: self.accumulator.clone(), - r_share: self.r_share.clone(), record_id: self.record_id, - _marker: PhantomData::default(), + _field_marker: PhantomData::default(), } } - #[must_use] - /// Make a sub-context which is bound to a record in case the same step is bound to a different `record_id` - /// # Panics - /// Panics in case the context is already bound to the same `record_id` - pub fn bind(&self, record_id: RecordId) -> Self { + fn bind(&self, record_id: RecordId) -> Self { if let Some(prev_record_id) = self.record_id { panic!( "Cannot bind to {record_id:?} because already bound to record: {prev_record_id:?}" ) } - ProtocolContext { + Self { role: self.role, // create a unique step that allows narrowing this context to the same step // if it is bound to a different record id step: Step::from_step_id(&self.step), prss: self.prss, gateway: self.gateway, - accumulator: self.accumulator.clone(), - r_share: self.r_share.clone(), record_id: Some(record_id), - _marker: PhantomData::default(), + _field_marker: PhantomData::default(), } } - /// Get the indexed PRSS instance for this step. It is safe to call this function - /// multiple times. - /// - /// # Panics - /// If `prss_rng()` is invoked for the same context, this will panic. Use of - /// these two functions are mutually exclusive. - #[must_use] - pub fn prss(&self) -> Arc { - self.prss.indexed(&self.step) + fn prss(&self) -> Arc { + self.prss.indexed(self.step()) } - /// Get a pair of PRSS-based RNGs. The first is shared with the helper to the "left", - /// the second is shared with the helper to the "right". - /// - /// # Panics - /// This method can only be called once. This is also mutually exclusive with `prss()`. - /// This will panic if you have previously invoked `prss()`. - #[must_use] - pub fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { - self.prss.sequential(&self.step) + fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { + self.prss.sequential(self.step()) } - /// Get a set of communications channels to different peers. - #[must_use] - pub fn mesh(&self) -> Mesh<'_, '_> { - self.gateway.mesh(&self.step) + fn mesh(&self) -> Mesh<'_, '_> { + self.gateway.mesh(self.step()) } } -/// Implementation to upgrade semi-honest context to malicious. Only works for replicated secret -/// sharing because it is not known yet how to do it for any other type of secret sharing. -impl<'a, F: Field> ProtocolContext<'a, Replicated, F> { - #[must_use] - pub fn upgrade_to_malicious( - self, - accumulator: SecurityValidatorAccumulator, - r_share: Replicated, - ) -> ProtocolContext<'a, MaliciousReplicated, F> { - ProtocolContext { - role: self.role, - step: self.step, - prss: self.prss, - gateway: self.gateway, - accumulator: Some(accumulator), - r_share: Some(r_share), - record_id: self.record_id, - _marker: PhantomData::default(), +impl <'a, F: Field> MaliciousProtocolContext<'a, F> { + pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway, acc: SecurityValidatorAccumulator, r_share: Replicated) -> Self { + Self { + role, + step: Step::default(), + prss: participant, + gateway, + record_id: None, + accumulator: acc, + r_share, + // _marker: PhantomData::default(), } } -} -/// Implementation that is specific to malicious contexts operating over replicated secret sharings. -impl<'a, F: Field> ProtocolContext<'a, MaliciousReplicated, F> { - /// Get the accumulator that collects messages MACs. - /// - /// ## Panics - /// Does not panic in normal circumstances, panic here will indicate a bug in protocol context - /// setup that left the accumulator field empty inside the malicious context. - #[must_use] - pub fn accumulator(&self) -> SecurityValidatorAccumulator { - self.accumulator - .as_ref() - .expect("Accumulator must be set in the context in order to perform maliciously secure multiplication") - .clone() + pub fn r_share(&self) -> &Replicated { + &self.r_share } - /// The `r_share` of this context. - #[must_use] - pub fn r_share(&self) -> Replicated { - self.r_share - .as_ref() - .expect("r_share must be set in the context in order to perform maliciously") - .clone() + pub fn accumulator(&self) -> SecurityValidatorAccumulator { + self.accumulator.clone() } - /// In some occasions it is required to reinterpret malicious context as semi-honest. Ideally + /// Sometimes it is required to reinterpret malicious context as semi-honest. Ideally /// protocols should be generic over `SecretShare` trait and not requiring this cast and taking /// `ProtocolContext<'a, S: SecretShare, F: Field>` as the context. If that is not possible, /// this implementation makes it easier to reinterpret the context as semi-honest. @@ -180,16 +204,245 @@ impl<'a, F: Field> ProtocolContext<'a, MaliciousReplicated, F> { /// The context received will be an exact copy of malicious, so it will be tied up to the same step /// and prss. #[must_use] - pub fn to_semi_honest(self) -> ProtocolContext<'a, Replicated, F> { - ProtocolContext { + pub fn to_semi_honest(self) -> SemiHonestProtocolContext<'a, F> { + let mut ctx = SemiHonestProtocolContext::new(self.role, self.prss, self.gateway); + ctx.step = self.step; + if let Some(record_id) = self.record_id { + ctx.bind(record_id) + } else { + ctx + } + + // ProtocolContext { + // role: self.role, + // step: self.step, + // prss: self.prss, + // gateway: self.gateway, + // accumulator: None, + // r_share: None, + // record_id: self.record_id, + // _marker: PhantomData::default(), + // } + } +} + + +impl <'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { + type Share = MaliciousReplicated; + + fn role(&self) -> Role { + self.role + } + + fn step(&self) -> &Step { + &self.step + } + + fn narrow(&self, step: &S) -> Self { + Self { role: self.role, - step: self.step, + step: self.step.narrow(step), prss: self.prss, gateway: self.gateway, - accumulator: None, - r_share: None, + accumulator: self.accumulator.clone(), + r_share: self.r_share.clone(), record_id: self.record_id, - _marker: PhantomData::default(), } } + + fn bind(&self, record_id: RecordId) -> Self { + if let Some(prev_record_id) = self.record_id { + panic!( + "Cannot bind to {record_id:?} because already bound to record: {prev_record_id:?}" + ) + } + + Self { + role: self.role, + // create a unique step that allows narrowing this context to the same step + // if it is bound to a different record id + step: Step::from_step_id(&self.step), + prss: self.prss, + gateway: self.gateway, + accumulator: self.accumulator.clone(), + r_share: self.r_share.clone(), + record_id: Some(record_id), + } + } + + fn prss(&self) -> Arc { + self.prss.indexed(self.step()) + } + + fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { + self.prss.sequential(self.step()) + } + + fn mesh(&self) -> Mesh<'_, '_> { + self.gateway.mesh(self.step()) + } } + +// impl<'a, F: Field, SS: SecretSharing> ProtocolContext<'a, SS, F> { +// pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { +// Self { +// role, +// step: Step::default(), +// prss: participant, +// gateway, +// accumulator: None, +// r_share: None, +// record_id: None, +// _marker: PhantomData::default(), +// } +// } +// +// /// The role of this context. +// #[must_use] +// pub fn role(&self) -> Role { +// self.role +// } +// +// /// A unique identifier for this stage of the protocol execution. +// #[must_use] +// pub fn step(&self) -> &Step { +// &self.step +// } +// +// /// Make a sub-context. +// /// Note that each invocation of this should use a unique value of `step`. +// #[must_use] +// pub fn narrow(&self, step: &S) -> Self { +// ProtocolContext { +// role: self.role, +// step: self.step.narrow(step), +// prss: self.prss, +// gateway: self.gateway, +// accumulator: self.accumulator.clone(), +// r_share: self.r_share.clone(), +// record_id: self.record_id, +// _marker: PhantomData::default(), +// } +// } +// +// #[must_use] +// /// Make a sub-context which is bound to a record in case the same step is bound to a different `record_id` +// /// # Panics +// /// Panics in case the context is already bound to the same `record_id` +// pub fn bind(&self, record_id: RecordId) -> Self { +// if let Some(prev_record_id) = self.record_id { +// panic!( +// "Cannot bind to {record_id:?} because already bound to record: {prev_record_id:?}" +// ) +// } +// +// ProtocolContext { +// role: self.role, +// // create a unique step that allows narrowing this context to the same step +// // if it is bound to a different record id +// step: Step::from_step_id(&self.step), +// prss: self.prss, +// gateway: self.gateway, +// accumulator: self.accumulator.clone(), +// r_share: self.r_share.clone(), +// record_id: Some(record_id), +// _marker: PhantomData::default(), +// } +// } +// +// /// Get the indexed PRSS instance for this step. It is safe to call this function +// /// multiple times. +// /// +// /// # Panics +// /// If `prss_rng()` is invoked for the same context, this will panic. Use of +// /// these two functions are mutually exclusive. +// #[must_use] +// pub fn prss(&self) -> Arc { +// self.prss.indexed(&self.step) +// } +// +// /// Get a pair of PRSS-based RNGs. The first is shared with the helper to the "left", +// /// the second is shared with the helper to the "right". +// /// +// /// # Panics +// /// This method can only be called once. This is also mutually exclusive with `prss()`. +// /// This will panic if you have previously invoked `prss()`. +// #[must_use] +// pub fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { +// self.prss.sequential(&self.step) +// } +// +// /// Get a set of communications channels to different peers. +// #[must_use] +// pub fn mesh(&self) -> Mesh<'_, '_> { +// self.gateway.mesh(&self.step) +// } +// } +// +// /// Implementation to upgrade semi-honest context to malicious. Only works for replicated secret +// /// sharing because it is not known yet how to do it for any other type of secret sharing. +// impl<'a, F: Field> ProtocolContext<'a, Replicated, F> { +// #[must_use] +// pub fn upgrade_to_malicious( +// self, +// accumulator: SecurityValidatorAccumulator, +// r_share: Replicated, +// ) -> ProtocolContext<'a, MaliciousReplicated, F> { +// ProtocolContext { +// role: self.role, +// step: self.step, +// prss: self.prss, +// gateway: self.gateway, +// accumulator: Some(accumulator), +// r_share: Some(r_share), +// record_id: self.record_id, +// _marker: PhantomData::default(), +// } +// } +// } +// +// /// Implementation that is specific to malicious contexts operating over replicated secret sharings. +// impl<'a, F: Field> ProtocolContext<'a, MaliciousReplicated, F> { +// /// Get the accumulator that collects messages MACs. +// /// +// /// ## Panics +// /// Does not panic in normal circumstances, panic here will indicate a bug in protocol context +// /// setup that left the accumulator field empty inside the malicious context. +// #[must_use] +// pub fn accumulator(&self) -> SecurityValidatorAccumulator { +// self.accumulator +// .as_ref() +// .expect("Accumulator must be set in the context in order to perform maliciously secure multiplication") +// .clone() +// } +// +// /// The `r_share` of this context. +// #[must_use] +// pub fn r_share(&self) -> Replicated { +// self.r_share +// .as_ref() +// .expect("r_share must be set in the context in order to perform maliciously") +// .clone() +// } +// +// /// In some occasions it is required to reinterpret malicious context as semi-honest. Ideally +// /// protocols should be generic over `SecretShare` trait and not requiring this cast and taking +// /// `ProtocolContext<'a, S: SecretShare, F: Field>` as the context. If that is not possible, +// /// this implementation makes it easier to reinterpret the context as semi-honest. +// /// +// /// The context received will be an exact copy of malicious, so it will be tied up to the same step +// /// and prss. +// #[must_use] +// pub fn to_semi_honest(self) -> ProtocolContext<'a, Replicated, F> { +// ProtocolContext { +// role: self.role, +// step: self.step, +// prss: self.prss, +// gateway: self.gateway, +// accumulator: None, +// r_share: None, +// record_id: self.record_id, +// _marker: PhantomData::default(), +// } +// } +// } diff --git a/src/protocol/context_traits.rs b/src/protocol/context_traits.rs index 5893d5c2b..d9eb7069a 100644 --- a/src/protocol/context_traits.rs +++ b/src/protocol/context_traits.rs @@ -2,6 +2,7 @@ use crate::{ ff::Field, secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}, }; +use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; use super::context::ProtocolContext; @@ -10,7 +11,7 @@ pub trait ShareOfOne { fn share_of_one(&self) -> Self::Share; } -impl ShareOfOne for ProtocolContext<'_, Replicated, F> { +impl ShareOfOne for SemiHonestProtocolContext<'_, F> { type Share = Replicated; fn share_of_one(&self) -> Self::Share { @@ -18,10 +19,10 @@ impl ShareOfOne for ProtocolContext<'_, Replicated, F> { } } -impl ShareOfOne for ProtocolContext<'_, MaliciousReplicated, F> { +impl ShareOfOne for MaliciousProtocolContext<'_, F> { type Share = MaliciousReplicated; fn share_of_one(&self) -> Self::Share { - MaliciousReplicated::one(self.role(), self.r_share()) + MaliciousReplicated::one(self.role(), self.r_share().clone()) } } diff --git a/src/protocol/malicious.rs b/src/protocol/malicious.rs index d2d0bd175..8def0015e 100644 --- a/src/protocol/malicious.rs +++ b/src/protocol/malicious.rs @@ -11,6 +11,7 @@ use crate::{ }; use futures::future::try_join; use std::sync::{Arc, Mutex, Weak}; +use crate::protocol::context::SemiHonestProtocolContext; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum Step { @@ -122,7 +123,7 @@ pub struct SecurityValidator { impl SecurityValidator { #[must_use] #[allow(clippy::needless_pass_by_value)] - pub fn new(ctx: ProtocolContext<'_, Replicated, F>) -> SecurityValidator { + pub fn new(ctx: SemiHonestProtocolContext<'_, F>) -> SecurityValidator { let prss = ctx.prss(); let r_share = prss.generate_replicated(RECORD_0); @@ -157,7 +158,7 @@ impl SecurityValidator { /// ## Panics /// Will panic if the mutex is poisoned #[allow(clippy::await_holding_lock)] - pub async fn validate(self, ctx: ProtocolContext<'_, Replicated, F>) -> Result<(), Error> { + pub async fn validate(self, ctx: SemiHonestProtocolContext<'_, F>) -> Result<(), Error> { // send our `u_i+1` value to the helper on the right let channel = ctx.mesh(); let helper_right = ctx.role().peer(Direction::Right); @@ -214,6 +215,7 @@ pub mod tests { }; use futures::future::{try_join, try_join_all}; use proptest::prelude::Rng; + use crate::protocol::context::ProtocolContext; /// This is the simplest arithmetic circuit that allows us to test all of the pieces of this validator /// A - diff --git a/src/protocol/modulus_conversion/convert_shares.rs b/src/protocol/modulus_conversion/convert_shares.rs index da84c1929..47bf141f8 100644 --- a/src/protocol/modulus_conversion/convert_shares.rs +++ b/src/protocol/modulus_conversion/convert_shares.rs @@ -9,6 +9,7 @@ use crate::{ use futures::future::try_join_all; use std::iter::{repeat, zip}; +use crate::protocol::context::SemiHonestProtocolContext; pub struct XorShares { num_bits: u8, @@ -107,7 +108,7 @@ impl ConvertShares { /// And helper 3 has shares: /// a: (0, x1) and b: (0, 0) async fn xor_specialized_1( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -133,7 +134,7 @@ impl ConvertShares { /// And helper 3 has shares: /// (x3, 0) async fn xor_specialized_2( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -145,7 +146,7 @@ impl ConvertShares { pub async fn execute_one_bit( &self, - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, bit_index: u8, ) -> Result, Error> { @@ -168,7 +169,7 @@ impl ConvertShares { /// For a given vector of input shares, this returns a vector of modulus converted replicated shares of /// `bit_index` of each input. pub async fn convert_shares_for_a_bit( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, input: &[(u64, u64)], num_bits: u8, bit_index: u8, @@ -204,6 +205,7 @@ mod tests { use futures::future::try_join_all; use proptest::prelude::Rng; use std::iter::{repeat, zip}; + use crate::protocol::context::ProtocolContext; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] struct ModulusConversionTestStep { diff --git a/src/protocol/modulus_conversion/specialized_mul.rs b/src/protocol/modulus_conversion/specialized_mul.rs index 3961ea990..70b516225 100644 --- a/src/protocol/modulus_conversion/specialized_mul.rs +++ b/src/protocol/modulus_conversion/specialized_mul.rs @@ -5,6 +5,7 @@ use crate::{ protocol::{context::ProtocolContext, RecordId}, secret_sharing::Replicated, }; +use crate::protocol::context::SemiHonestProtocolContext; /// A highly specialized variant of the IKHC multiplication protocol which is only valid /// in the case where 4 of the 6 shares are zero. @@ -30,7 +31,7 @@ use crate::{ /// back via the error response #[allow(dead_code)] pub async fn multiply_two_shares_mostly_zeroes( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -114,7 +115,7 @@ pub async fn multiply_two_shares_mostly_zeroes( /// back via the error response #[allow(dead_code)] pub async fn multiply_one_share_mostly_zeroes( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -200,6 +201,7 @@ pub mod tests { }; use futures::future::try_join_all; use proptest::prelude::Rng; + use crate::protocol::context::ProtocolContext; #[tokio::test] async fn specialized_1_sequence() -> Result<(), Error> { diff --git a/src/protocol/mul/malicious.rs b/src/protocol/mul/malicious.rs index 4469b50ba..cc8a87341 100644 --- a/src/protocol/mul/malicious.rs +++ b/src/protocol/mul/malicious.rs @@ -7,6 +7,7 @@ use crate::protocol::{ use crate::secret_sharing::MaliciousReplicated; use futures::future::try_join; use std::fmt::Debug; +use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum Step { @@ -47,7 +48,7 @@ impl AsRef for Step { /// `SecureMult` is an implementation of the IKHC multiplication protocol, which has this property. /// pub struct SecureMul<'a, F: Field> { - ctx: ProtocolContext<'a, MaliciousReplicated, F>, + ctx: MaliciousProtocolContext<'a, F>, record_id: RecordId, accumulator: SecurityValidatorAccumulator, } @@ -55,7 +56,7 @@ pub struct SecureMul<'a, F: Field> { impl<'a, F: Field> SecureMul<'a, F> { #[must_use] pub fn new( - ctx: ProtocolContext<'a, MaliciousReplicated, F>, + ctx: MaliciousProtocolContext<'a, F>, record_id: RecordId, accumulator: SecurityValidatorAccumulator, ) -> Self { diff --git a/src/protocol/mul/mod.rs b/src/protocol/mul/mod.rs index 638612a2e..fbb59bdde 100644 --- a/src/protocol/mul/mod.rs +++ b/src/protocol/mul/mod.rs @@ -1,6 +1,6 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::ProtocolContext; +use crate::protocol::context::{MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext}; use crate::protocol::RecordId; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; use async_trait::async_trait; @@ -27,7 +27,7 @@ pub use {malicious::SecureMul as MaliciouslySecureMul, semi_honest::SecureMul as /// Implement secure multiplication for semi-honest contexts with replicated secret sharing. #[async_trait] -impl SecureMul for ProtocolContext<'_, Replicated, F> { +impl SecureMul for SemiHonestProtocolContext<'_, F> { type Share = Replicated; async fn multiply( @@ -42,7 +42,7 @@ impl SecureMul for ProtocolContext<'_, Replicated, F> { /// Implement secure multiplication for malicious contexts with replicated secret sharing. #[async_trait] -impl SecureMul for ProtocolContext<'_, MaliciousReplicated, F> { +impl SecureMul for MaliciousProtocolContext<'_, F> { type Share = MaliciousReplicated; async fn multiply( diff --git a/src/protocol/mul/semi_honest.rs b/src/protocol/mul/semi_honest.rs index f3a3d3871..65ceda931 100644 --- a/src/protocol/mul/semi_honest.rs +++ b/src/protocol/mul/semi_honest.rs @@ -4,19 +4,20 @@ use crate::helpers::Direction; use crate::protocol::{context::ProtocolContext, RecordId}; use crate::secret_sharing::Replicated; use std::fmt::Debug; +use crate::protocol::context::SemiHonestProtocolContext; /// IKHC multiplication protocol /// for use with replicated secret sharing over some field F. /// K. Chida, K. Hamada, D. Ikarashi, R. Kikuchi, and B. Pinkas. High-throughput secure AES computation. In WAHC@CCS 2018, pp. 13–24, 2018 #[derive(Debug)] pub struct SecureMul<'a, F: Field> { - ctx: ProtocolContext<'a, Replicated, F>, + ctx: SemiHonestProtocolContext<'a, F>, record_id: RecordId, } impl<'a, F: Field> SecureMul<'a, F> { #[must_use] - pub fn new(ctx: ProtocolContext<'a, Replicated, F>, record_id: RecordId) -> Self { + pub fn new(ctx: SemiHonestProtocolContext<'a, F>, record_id: RecordId) -> Self { Self { ctx, record_id } } @@ -75,6 +76,7 @@ pub mod tests { use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, RngCore}; use std::iter::{repeat, zip}; use std::sync::atomic::{AtomicU32, Ordering}; + use crate::protocol::context::SemiHonestProtocolContext; #[tokio::test] async fn basic() -> Result<(), Error> { @@ -145,7 +147,7 @@ pub mod tests { } async fn multiply_sync( - context: [ProtocolContext<'_, Replicated, F>; 3], + context: [SemiHonestProtocolContext<'_, F>; 3], a: u8, b: u8, rng: &mut R, diff --git a/src/protocol/reveal/mod.rs b/src/protocol/reveal/mod.rs index 21d5ea53d..b35beed71 100644 --- a/src/protocol/reveal/mod.rs +++ b/src/protocol/reveal/mod.rs @@ -1,7 +1,7 @@ -use std::iter::{repeat, zip}; +use std::iter::{repeat, Rev, zip}; use crate::ff::Field; -use crate::protocol::context::ProtocolContext; +use crate::protocol::context::{MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext}; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; use crate::{ error::{BoxError, Error}, @@ -11,6 +11,7 @@ use crate::{ use async_trait::async_trait; use embed_doc_image::embed_doc_image; use futures::future::{try_join, try_join_all}; +use crate::protocol::malicious::SecurityValidator; /// Trait for reveal protocol to open a shared secret to all helpers inside the MPC ring. #[async_trait] @@ -25,6 +26,7 @@ pub trait Reveal { async fn reveal(self, record: RecordId, input: &Self::Share) -> Result; } + /// This implements a semi-honest reveal algorithm for replicated secret sharing. /// For simplicity, we consider a simple revealing in which each `P_i` sends `\[a\]_i` to `P_i+1` after which /// each helper has all three shares and can reconstruct `a` @@ -38,7 +40,7 @@ pub trait Reveal { /// i.e. their own shares and received share. #[async_trait] #[embed_doc_image("reveal", "images/reveal.png")] -impl Reveal for ProtocolContext<'_, Replicated, G> { +impl Reveal for SemiHonestProtocolContext<'_, G> { type Share = Replicated; async fn reveal( @@ -67,7 +69,7 @@ impl Reveal for ProtocolContext<'_, Replicated, G> { /// to both helpers (right and left) and upon receiving 2 shares from peers it validates that they /// indeed match. #[async_trait] -impl Reveal for ProtocolContext<'_, MaliciousReplicated, G> { +impl Reveal for MaliciousProtocolContext<'_, G> { type Share = MaliciousReplicated; async fn reveal( @@ -103,7 +105,7 @@ impl Reveal for ProtocolContext<'_, MaliciousReplicated, G> { /// This executes `reveal` protocol on each row of the vector and then constructs a `Permutation` object /// from the revealed rows. pub async fn reveal_permutation( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, permutation: &[Replicated], ) -> Result, BoxError> { let revealed_permutation = try_join_all(zip(repeat(ctx), permutation).enumerate().map( @@ -139,6 +141,7 @@ mod tests { make_contexts, make_world, share, share_malicious, validate_and_reconstruct, TestWorld, }, }; + use crate::protocol::context::MaliciousProtocolContext; #[tokio::test] pub async fn simple() -> Result<(), BoxError> { @@ -223,7 +226,7 @@ mod tests { } pub async fn reveal_with_additive_attack( - ctx: ProtocolContext<'_, MaliciousReplicated, F>, + ctx: MaliciousProtocolContext<'_, F>, record_id: RecordId, input: &MaliciousReplicated, additive_error: F, diff --git a/src/protocol/sort/bit_permutation.rs b/src/protocol/sort/bit_permutation.rs index 8e230864c..872b07d2c 100644 --- a/src/protocol/sort/bit_permutation.rs +++ b/src/protocol/sort/bit_permutation.rs @@ -33,13 +33,10 @@ use futures::future::try_join_all; /// /// ## Errors /// It will propagate errors from multiplication protocol. -pub async fn bit_permutation<'a, F: Field, S: SecretSharing>( - ctx: ProtocolContext<'a, S, F>, +pub async fn bit_permutation<'a, F: Field, S: SecretSharing, C: ProtocolContext>( + ctx: C, input: &[S], -) -> Result, BoxError> -where - ProtocolContext<'a, S, F>: SecureMul + ShareOfOne, -{ +) -> Result, BoxError> { let share_of_one = ctx.share_of_one(); let mult_input = zip(repeat(share_of_one.clone()), input) diff --git a/src/protocol/sort/compose.rs b/src/protocol/sort/compose.rs index efedbbf87..4121fb4f4 100644 --- a/src/protocol/sort/compose.rs +++ b/src/protocol/sort/compose.rs @@ -5,6 +5,7 @@ use crate::{ secret_sharing::Replicated, }; use embed_doc_image::embed_doc_image; +use crate::protocol::context::SemiHonestProtocolContext; use super::{ apply::apply, @@ -31,7 +32,7 @@ use super::{ /// 4. Revealed permutation is applied locally on another permutation shares (rho) /// 5. Unshuffle the permutation with the same random permutations used in step 2, to undo the effect of the shuffling pub async fn compose( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, sigma: Vec>, mut rho: Vec>, ) -> Result>, BoxError> { diff --git a/src/protocol/sort/generate_sort_permutation.rs b/src/protocol/sort/generate_sort_permutation.rs index 3ecad3794..9f63cf218 100644 --- a/src/protocol/sort/generate_sort_permutation.rs +++ b/src/protocol/sort/generate_sort_permutation.rs @@ -13,6 +13,7 @@ use crate::{ use super::{compose::compose, secureapplyinv::secureapplyinv}; use embed_doc_image::embed_doc_image; +use crate::protocol::context::SemiHonestProtocolContext; /// This is an implementation of `GenPerm` (Algorithm 6) described in: /// "An Efficient Secure Three-Party Sorting Protocol with an Honest Majority" @@ -33,9 +34,9 @@ use embed_doc_image::embed_doc_image; /// 3 Compute bit permutation that sorts ith bit /// 4. Compute ith composition by composing i-1th composition on ith permutation /// In the end, n-1th composition is returned. This is the permutation which sorts the inputs -pub async fn generate_sort_permutation<'a, F: Field>( - ctx: ProtocolContext<'_, Replicated, F>, - input: &'a [(u64, u64)], +pub async fn generate_sort_permutation( + ctx: SemiHonestProtocolContext<'_, F>, + input: &[(u64, u64)], num_bits: u8, ) -> Result>, BoxError> { let ctx_0 = ctx.narrow(&Sort(0)); diff --git a/src/protocol/sort/reshare.rs b/src/protocol/sort/reshare.rs index d6ba2011b..b257c0267 100644 --- a/src/protocol/sort/reshare.rs +++ b/src/protocol/sort/reshare.rs @@ -6,6 +6,7 @@ use crate::{ secret_sharing::Replicated, }; use embed_doc_image::embed_doc_image; +use crate::protocol::context::SemiHonestProtocolContext; /// Reshare(i, \[x\]) // This implements reshare algorithm of "Efficient Secure Three-Party Sorting Protocol with an Honest Majority" at communication cost of 2R. @@ -36,7 +37,7 @@ impl Reshare { /// `to_helper.right` = (`rand_right`, part1 + part2) = (r0, part1 + part2) pub async fn execute( self, - ctx: &ProtocolContext<'_, Replicated, F>, + ctx: &SemiHonestProtocolContext<'_, F>, record_id: RecordId, to_helper: Role, ) -> Result, BoxError> { diff --git a/src/protocol/sort/secureapplyinv.rs b/src/protocol/sort/secureapplyinv.rs index 0b75c805b..56efe6a09 100644 --- a/src/protocol/sort/secureapplyinv.rs +++ b/src/protocol/sort/secureapplyinv.rs @@ -15,6 +15,7 @@ use super::{ shuffle::{get_two_of_three_random_permutations, shuffle_shares}, }; use futures::future::try_join; +use crate::protocol::context::SemiHonestProtocolContext; /// This is an implementation of ApplyInv (Algorithm 4) found in the paper: /// "An Efficient Secure Three-Party Sorting Protocol with an Honest Majority" @@ -37,7 +38,7 @@ use futures::future::try_join; /// 4. The permutation is revealed /// 5. All helpers call `apply` to apply the permutation locally. pub async fn secureapplyinv( - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, input: Vec>, sort_permutation: Vec>, ) -> Result>, BoxError> { diff --git a/src/protocol/sort/shuffle.rs b/src/protocol/sort/shuffle.rs index 3ff43f008..56b01f0f2 100644 --- a/src/protocol/sort/shuffle.rs +++ b/src/protocol/sort/shuffle.rs @@ -11,6 +11,7 @@ use crate::{ protocol::{context::ProtocolContext, prss::IndexedSharedRandomness, RecordId, Substep}, secret_sharing::Replicated, }; +use crate::protocol::context::SemiHonestProtocolContext; use super::{ apply::{apply, apply_inv}, @@ -88,7 +89,7 @@ fn shuffle_for_helper(which_step: ShuffleStep) -> Role { #[allow(clippy::cast_possible_truncation)] async fn reshare_all_shares( input: Vec>, - ctx: &ProtocolContext<'_, Replicated, F>, + ctx: &SemiHonestProtocolContext<'_, F>, to_helper: Role, ) -> Result>, BoxError> { let reshares = input @@ -112,7 +113,7 @@ async fn shuffle_or_unshuffle_once( mut input: Vec>, random_permutations: (&[u32], &[u32]), shuffle_or_unshuffle: ShuffleOrUnshuffle, - ctx: &ProtocolContext<'_, Replicated, F>, + ctx: &SemiHonestProtocolContext<'_, F>, which_step: ShuffleStep, ) -> Result>, BoxError> { let to_helper = shuffle_for_helper(which_step); @@ -144,7 +145,7 @@ async fn shuffle_or_unshuffle_once( pub async fn shuffle_shares( input: Vec>, random_permutations: (&[u32], &[u32]), - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, ) -> Result>, BoxError> { let input = shuffle_or_unshuffle_once( input, @@ -179,7 +180,7 @@ pub async fn shuffle_shares( pub async fn unshuffle_shares( input: Vec>, random_permutations: (&[u32], &[u32]), - ctx: ProtocolContext<'_, Replicated, F>, + ctx: SemiHonestProtocolContext<'_, F>, ) -> Result>, BoxError> { let input = shuffle_or_unshuffle_once( input, @@ -228,6 +229,7 @@ mod tests { }, }; use futures::future::try_join_all; + use crate::protocol::context::ProtocolContext; #[test] fn random_sequence_generated() { diff --git a/src/test_fixture/circuit.rs b/src/test_fixture/circuit.rs index 8c419a400..d6f3519f8 100644 --- a/src/test_fixture/circuit.rs +++ b/src/test_fixture/circuit.rs @@ -7,6 +7,7 @@ use crate::test_fixture::{ }; use futures_util::future::join_all; use rand::thread_rng; +use crate::protocol::context::ProtocolContext; /// Creates an arithmetic circuit with the given width and depth. /// diff --git a/src/test_fixture/mod.rs b/src/test_fixture/mod.rs index 6a7f7dc36..2e5b20d34 100644 --- a/src/test_fixture/mod.rs +++ b/src/test_fixture/mod.rs @@ -5,9 +5,10 @@ pub mod circuit; pub mod logging; pub mod network; +use std::fmt::Debug; use crate::ff::{Field, Fp31}; use crate::helpers::Role; -use crate::protocol::context::ProtocolContext; +use crate::protocol::context::{MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext}; use crate::protocol::malicious::SecurityValidator; use crate::protocol::prss::Endpoint as PrssEndpoint; use crate::protocol::Substep; @@ -32,19 +33,19 @@ pub use world::{ #[must_use] pub fn make_contexts( test_world: &TestWorld, -) -> [ProtocolContext<'_, Replicated, F>; 3] { +) -> [SemiHonestProtocolContext<'_, F>; 3] { test_world .gateways .iter() .zip(&test_world.participants) .zip(Role::all()) - .map(|((gateway, participant), role)| ProtocolContext::new(*role, participant, gateway)) + .map(|((gateway, participant), role)| SemiHonestProtocolContext::new(*role, participant, gateway)) .collect::>() .try_into() .unwrap() } pub struct MaliciousContext<'a, F: Field> { - pub ctx: ProtocolContext<'a, MaliciousReplicated, F>, + pub ctx: MaliciousProtocolContext<'a, F>, pub validator: SecurityValidator, } @@ -67,10 +68,10 @@ pub fn make_malicious_contexts(test_world: &TestWorld) -> [MaliciousCo /// # Panics /// Never, but then Rust doesn't know that; this is only needed because we don't have `each_ref()`. #[must_use] -pub fn narrow_contexts<'a, F: Field, S: SecretSharing>( - contexts: &[ProtocolContext<'a, S, F>; 3], +pub fn narrow_contexts<'a, C: Debug + ProtocolContext, F: Field, S: SecretSharing>( + contexts: &[C; 3], step: &impl Substep, -) -> [ProtocolContext<'a, S, F>; 3] { +) -> [C; 3] { // This really wants <[_; N]>::each_ref() contexts .iter() From 423d80d6bb0c7cb9eb7643b14a8b4edf0792253b Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 21:02:48 -0800 Subject: [PATCH 02/13] Remove `bind` and checks from `narrow` What is left: * Introduce a small context struct that clone will refer to --- src/protocol/context.rs | 65 +------------------ src/protocol/mod.rs | 46 +------------ .../modulus_conversion/convert_shares.rs | 8 +-- .../modulus_conversion/specialized_mul.rs | 24 +++---- src/protocol/mul/semi_honest.rs | 6 +- src/protocol/sort/bit_permutation.rs | 2 +- 6 files changed, 23 insertions(+), 128 deletions(-) diff --git a/src/protocol/context.rs b/src/protocol/context.rs index e3587a787..2bf451407 100644 --- a/src/protocol/context.rs +++ b/src/protocol/context.rs @@ -40,11 +40,6 @@ pub trait ProtocolContext : Clone #[must_use] fn narrow(&self, step: &S) -> Self; - /// Make a sub-context which is bound to a record in case the same step is bound to a different `record_id` - /// # Panics - /// Panics in case the context is already bound to the same `record_id` - fn bind(&self, record_id: RecordId) -> Self; - /// Get the indexed PRSS instance for this step. It is safe to call this function /// multiple times. /// @@ -112,11 +107,7 @@ impl <'a, F: Field> SemiHonestProtocolContext<'a, F> { let mut ctx = MaliciousProtocolContext::new(self.role, self.prss, self.gateway, accumulator, r_share); ctx.step = self.step; - if let Some(record_id) = self.record_id { - ctx.bind(record_id) - } else { - ctx - } + ctx } } @@ -142,25 +133,6 @@ impl <'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { } } - fn bind(&self, record_id: RecordId) -> Self { - if let Some(prev_record_id) = self.record_id { - panic!( - "Cannot bind to {record_id:?} because already bound to record: {prev_record_id:?}" - ) - } - - Self { - role: self.role, - // create a unique step that allows narrowing this context to the same step - // if it is bound to a different record id - step: Step::from_step_id(&self.step), - prss: self.prss, - gateway: self.gateway, - record_id: Some(record_id), - _field_marker: PhantomData::default(), - } - } - fn prss(&self) -> Arc { self.prss.indexed(self.step()) } @@ -207,22 +179,8 @@ impl <'a, F: Field> MaliciousProtocolContext<'a, F> { pub fn to_semi_honest(self) -> SemiHonestProtocolContext<'a, F> { let mut ctx = SemiHonestProtocolContext::new(self.role, self.prss, self.gateway); ctx.step = self.step; - if let Some(record_id) = self.record_id { - ctx.bind(record_id) - } else { - ctx - } - // ProtocolContext { - // role: self.role, - // step: self.step, - // prss: self.prss, - // gateway: self.gateway, - // accumulator: None, - // r_share: None, - // record_id: self.record_id, - // _marker: PhantomData::default(), - // } + ctx } } @@ -250,25 +208,6 @@ impl <'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { } } - fn bind(&self, record_id: RecordId) -> Self { - if let Some(prev_record_id) = self.record_id { - panic!( - "Cannot bind to {record_id:?} because already bound to record: {prev_record_id:?}" - ) - } - - Self { - role: self.role, - // create a unique step that allows narrowing this context to the same step - // if it is bound to a different record id - step: Step::from_step_id(&self.step), - prss: self.prss, - gateway: self.gateway, - accumulator: self.accumulator.clone(), - r_share: self.r_share.clone(), - record_id: Some(record_id), - } - } fn prss(&self) -> Arc { self.prss.indexed(self.step()) diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 8db41fc48..8d08f43f5 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -68,7 +68,7 @@ impl Substep for str {} /// (possible more efficient) representation. It is probably not particularly efficient /// to be cloning this object all over the place. Of course, a string is pretty useful /// from a debugging perspective. -#[derive(Clone)] +#[derive(Clone, Hash, PartialEq, Eq)] #[cfg_attr( feature = "enable-serde", derive(serde::Deserialize), @@ -76,57 +76,17 @@ impl Substep for str {} )] pub struct Step { id: String, - /// This tracks the different values that have been provided to `narrow()`. - #[cfg(debug_assertions)] - used: Arc>>, } -impl Hash for Step { - fn hash(&self, state: &mut H) { - state.write(self.id.as_bytes()); - } -} - -impl PartialEq for Step { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} - -impl Eq for Step {} - impl Step { - #[must_use] - pub fn from_step_id(step: &Self) -> Self { - Self { - id: step.id.clone(), - #[cfg(debug_assertions)] - used: Arc::new(Mutex::new(HashSet::new())), - } - } - /// Narrow the scope of the step identifier. /// # Panics /// In a debug build, this checks that the same refine call isn't run twice and that the string /// value of the step doesn't include '/' (which would lead to a bad outcome). #[must_use] pub fn narrow(&self, step: &S) -> Self { - #[cfg(debug_assertions)] - { - let s = String::from(step.as_ref()); - assert!(!s.contains('/'), "The string for a step cannot contain '/'"); - assert!( - self.used.lock().unwrap().insert(s), - "Refined '{}' with step '{}' twice", - self.id, - step.as_ref(), - ); - } - Self { id: self.id.clone() + "/" + step.as_ref(), - #[cfg(debug_assertions)] - used: Arc::new(Mutex::new(HashSet::new())), } } } @@ -137,8 +97,6 @@ impl Default for Step { fn default() -> Self { Self { id: String::from("protocol"), - #[cfg(debug_assertions)] - used: Arc::new(Mutex::new(HashSet::new())), } } } @@ -154,8 +112,6 @@ impl From<&str> for Step { let id = id.strip_prefix('/').unwrap_or(id); Step { id: id.to_owned(), - #[cfg(debug_assertions)] - used: Arc::new(Mutex::new(HashSet::new())), } } } diff --git a/src/protocol/modulus_conversion/convert_shares.rs b/src/protocol/modulus_conversion/convert_shares.rs index 47bf141f8..c8aa32046 100644 --- a/src/protocol/modulus_conversion/convert_shares.rs +++ b/src/protocol/modulus_conversion/convert_shares.rs @@ -182,7 +182,7 @@ pub async fn convert_shares_for_a_bit( packed_bits_left: row.0, packed_bits_right: row.1, }) - .execute_one_bit(ctx.bind(record_id), record_id, bit_index) + .execute_one_bit(ctx, record_id, bit_index) .await }, )) @@ -248,19 +248,19 @@ mod tests { packed_bits_left: share_0, packed_bits_right: share_1, }) - .execute_one_bit(c0.bind(record_id), record_id, 4), + .execute_one_bit(c0, record_id, 4), ConvertShares::new(XorShares { num_bits: 40, packed_bits_left: share_1, packed_bits_right: share_2, }) - .execute_one_bit(c1.bind(record_id), record_id, 4), + .execute_one_bit(c1, record_id, 4), ConvertShares::new(XorShares { num_bits: 40, packed_bits_left: share_2, packed_bits_right: share_0, }) - .execute_one_bit(c2.bind(record_id), record_id, 4), + .execute_one_bit(c2, record_id, 4), ]) .await }), diff --git a/src/protocol/modulus_conversion/specialized_mul.rs b/src/protocol/modulus_conversion/specialized_mul.rs index 70b516225..739b6ac0e 100644 --- a/src/protocol/modulus_conversion/specialized_mul.rs +++ b/src/protocol/modulus_conversion/specialized_mul.rs @@ -217,19 +217,19 @@ pub mod tests { let result_shares = try_join_all([ multiply_two_shares_mostly_zeroes( - context[0].bind(record_id), + context[0].clone(), record_id, &Replicated::new(a, Fp31::ZERO), &Replicated::new(Fp31::ZERO, b), ), multiply_two_shares_mostly_zeroes( - context[1].bind(record_id), + context[1].clone(), record_id, &Replicated::new(Fp31::ZERO, Fp31::ZERO), &Replicated::new(b, Fp31::ZERO), ), multiply_two_shares_mostly_zeroes( - context[2].bind(record_id), + context[2].clone(), record_id, &Replicated::new(Fp31::ZERO, a), &Replicated::new(Fp31::ZERO, Fp31::ZERO), @@ -278,19 +278,19 @@ pub mod tests { let record_id = RecordId::from(i); futures.push(try_join_all([ multiply_two_shares_mostly_zeroes( - context[0].bind(record_id), + context[0].clone(), record_id, &a_shares[i][0], &b_shares[i][0], ), multiply_two_shares_mostly_zeroes( - context[1].bind(record_id), + context[1].clone(), record_id, &a_shares[i][1], &b_shares[i][1], ), multiply_two_shares_mostly_zeroes( - context[2].bind(record_id), + context[2].clone(), record_id, &a_shares[i][2], &b_shares[i][2], @@ -326,19 +326,19 @@ pub mod tests { let result_shares = try_join_all([ multiply_one_share_mostly_zeroes( - context[0].bind(record_id), + context[0].clone(), record_id, &a_shares[0], &Replicated::new(Fp31::ZERO, Fp31::ZERO), ), multiply_one_share_mostly_zeroes( - context[1].bind(record_id), + context[1].clone(), record_id, &a_shares[1], &Replicated::new(Fp31::ZERO, b), ), multiply_one_share_mostly_zeroes( - context[2].bind(record_id), + context[2].clone(), record_id, &a_shares[2], &Replicated::new(b, Fp31::ZERO), @@ -385,19 +385,19 @@ pub mod tests { let record_id = RecordId::from(i); futures.push(try_join_all([ multiply_one_share_mostly_zeroes( - context[0].bind(record_id), + context[0].clone(), record_id, &a_shares[i][0], &b_shares[i][0], ), multiply_one_share_mostly_zeroes( - context[1].bind(record_id), + context[1].clone(), record_id, &a_shares[i][1], &b_shares[i][1], ), multiply_one_share_mostly_zeroes( - context[2].bind(record_id), + context[2].clone(), record_id, &a_shares[i][2], &b_shares[i][2], diff --git a/src/protocol/mul/semi_honest.rs b/src/protocol/mul/semi_honest.rs index 65ceda931..f3c834ecc 100644 --- a/src/protocol/mul/semi_honest.rs +++ b/src/protocol/mul/semi_honest.rs @@ -122,13 +122,13 @@ pub mod tests { async move { try_join_all([ ctx[0] - .bind(record_id) + .clone() .multiply(record_id, &a_shares[0], &b_shares[0]), ctx[1] - .bind(record_id) + .clone() .multiply(record_id, &a_shares[1], &b_shares[1]), ctx[2] - .bind(record_id) + .clone() .multiply(record_id, &a_shares[2], &b_shares[2]), ]) .await diff --git a/src/protocol/sort/bit_permutation.rs b/src/protocol/sort/bit_permutation.rs index 872b07d2c..4a2345e1a 100644 --- a/src/protocol/sort/bit_permutation.rs +++ b/src/protocol/sort/bit_permutation.rs @@ -52,7 +52,7 @@ pub async fn bit_permutation<'a, F: Field, S: SecretSharing, C: ProtocolConte .enumerate() .map(|(i, (ctx, (x, sum)))| async move { let record_id = RecordId::from(i); - ctx.bind(record_id).multiply(record_id, &x, &sum).await + ctx.multiply(record_id, &x, &sum).await }); let mut mult_output = try_join_all(async_multiply).await?; From 593da70aa11523080a362268f2de1748ad1d5148 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 22:09:25 -0800 Subject: [PATCH 03/13] ContextInner --- src/protocol/context.rs | 128 ++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 52 deletions(-) diff --git a/src/protocol/context.rs b/src/protocol/context.rs index 2bf451407..9b3e29d76 100644 --- a/src/protocol/context.rs +++ b/src/protocol/context.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::marker::PhantomData; use std::sync::Arc; @@ -62,39 +63,66 @@ pub trait ProtocolContext : Clone fn mesh(&self) -> Mesh<'_, '_>; } -#[derive(Clone, Debug)] -pub struct SemiHonestProtocolContext<'a, F: Field> { +/// Contains things that are applicable to any implementation of protocol context as see it today +/// Every context requires access to current step, PRSS and communication and that is what this +/// struct carries. +#[derive(Debug, Clone)] +struct ContextInner<'a> { role: Role, step: Step, prss: &'a PrssEndpoint, gateway: &'a Gateway, - record_id: Option, - _field_marker: PhantomData, } +impl <'a> ContextInner<'a> { + fn new(role: Role, prss: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { + Self { + role, + step: Step::default(), + prss, + gateway, + } + } + + fn narrow(&self, step: &S) -> Self { + Self { + role: self.role, + step: self.step.narrow(step), + prss: self.prss, + gateway: self.gateway, + } + } +} + +/// Context for protocol executions suitable for semi-honest security model, i.e. secure against +/// honest-but-curious adversary parties. +#[derive(Clone, Debug)] +pub struct SemiHonestProtocolContext<'a, F: Field> { + inner: Cow<'a, ContextInner<'a>>, + _marker: PhantomData, +} + +/// Represents protocol context in malicious setting, i.e. secure against one active adversary +/// in 3 party MPC ring. #[derive(Clone, Debug)] pub struct MaliciousProtocolContext<'a, F: Field> { - role: Role, - step: Step, - prss: &'a PrssEndpoint, - gateway: &'a Gateway, - record_id: Option, + inner: Cow<'a, ContextInner<'a>>, accumulator: SecurityValidatorAccumulator, r_share: Replicated, - // _marker: PhantomData, } - impl <'a, F: Field> SemiHonestProtocolContext<'a, F> { pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { Self { - role, - step: Step::default(), - prss: participant, - gateway, - record_id: None, - // _share_marker: PhantomData::default(), - _field_marker: PhantomData::default(), + inner: Cow::Owned(ContextInner::new(role, participant, gateway)), + _marker: PhantomData::default(), + } + } + + fn from_inner(inner: Cow<'a, ContextInner<'a>>) -> Self { + Self { + inner, + _marker: PhantomData::default(), } } @@ -104,10 +132,7 @@ impl <'a, F: Field> SemiHonestProtocolContext<'a, F> { accumulator: SecurityValidatorAccumulator, r_share: Replicated, ) -> MaliciousProtocolContext<'a, F> { - let mut ctx = MaliciousProtocolContext::new(self.role, self.prss, self.gateway, accumulator, r_share); - ctx.step = self.step; - - ctx + MaliciousProtocolContext::from_inner(self.inner, accumulator, r_share) } } @@ -115,48 +140,51 @@ impl <'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { type Share = Replicated; fn role(&self) -> Role { - self.role + self.inner.role } fn step(&self) -> &Step { - &self.step + &self.inner.step } fn narrow(&self, step: &S) -> Self { Self { - role: self.role, - step: self.step.narrow(step), - prss: self.prss, - gateway: self.gateway, - record_id: self.record_id, - _field_marker: PhantomData::default(), + inner: Cow::Owned(self.inner.narrow(step)), + _marker: PhantomData::default(), } } fn prss(&self) -> Arc { - self.prss.indexed(self.step()) + self.inner.prss.indexed(self.step()) } fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { - self.prss.sequential(self.step()) + self.inner.prss.sequential(self.step()) } fn mesh(&self) -> Mesh<'_, '_> { - self.gateway.mesh(self.step()) + self.inner.gateway.mesh(self.step()) } } impl <'a, F: Field> MaliciousProtocolContext<'a, F> { - pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway, acc: SecurityValidatorAccumulator, r_share: Replicated) -> Self { + pub fn new(role: Role, + participant: &'a PrssEndpoint, + gateway: &'a Gateway, + acc: SecurityValidatorAccumulator, + r_share: Replicated) -> Self { Self { - role, - step: Step::default(), - prss: participant, - gateway, - record_id: None, + inner: Cow::Owned(ContextInner::new(role, participant, gateway)), accumulator: acc, r_share, - // _marker: PhantomData::default(), + } + } + + fn from_inner(inner: Cow<'a, ContextInner<'a>>, acc: SecurityValidatorAccumulator, r_share: Replicated) -> Self { + Self { + inner, + accumulator: acc, + r_share } } @@ -177,8 +205,7 @@ impl <'a, F: Field> MaliciousProtocolContext<'a, F> { /// and prss. #[must_use] pub fn to_semi_honest(self) -> SemiHonestProtocolContext<'a, F> { - let mut ctx = SemiHonestProtocolContext::new(self.role, self.prss, self.gateway); - ctx.step = self.step; + let mut ctx = SemiHonestProtocolContext::from_inner(self.inner); ctx } @@ -189,36 +216,33 @@ impl <'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { type Share = MaliciousReplicated; fn role(&self) -> Role { - self.role + self.inner.role } fn step(&self) -> &Step { - &self.step + &self.inner.step } fn narrow(&self, step: &S) -> Self { Self { - role: self.role, - step: self.step.narrow(step), - prss: self.prss, - gateway: self.gateway, + inner: Cow::Owned(self.inner.narrow(step)), accumulator: self.accumulator.clone(), + // TODO (alex, mt) - is cloning ok here or we need to Cow it? r_share: self.r_share.clone(), - record_id: self.record_id, } } fn prss(&self) -> Arc { - self.prss.indexed(self.step()) + self.inner.prss.indexed(self.step()) } fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { - self.prss.sequential(self.step()) + self.inner.prss.sequential(self.step()) } fn mesh(&self) -> Mesh<'_, '_> { - self.gateway.mesh(self.step()) + self.inner.gateway.mesh(self.step()) } } From fda058a853d34840c2206e015ae8c8a4004b9c55 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 22:16:41 -0800 Subject: [PATCH 04/13] Formatting and Clippy --- src/helpers/messaging.rs | 1 + src/protocol/attribution/accumulate_credit.rs | 2 +- src/protocol/boolean/bitwise_lt.rs | 4 +- src/protocol/boolean/bitwise_sum.rs | 4 +- src/protocol/boolean/carries.rs | 4 +- src/protocol/boolean/or.rs | 4 +- src/protocol/boolean/prefix_or.rs | 4 +- src/protocol/boolean/xor.rs | 4 +- src/protocol/check_zero.rs | 4 +- src/protocol/context.rs | 216 +++--------------- src/protocol/malicious.rs | 4 +- src/protocol/mod.rs | 11 +- .../modulus_conversion/convert_shares.rs | 3 +- .../modulus_conversion/specialized_mul.rs | 3 +- src/protocol/mul/malicious.rs | 2 +- src/protocol/mul/mod.rs | 2 +- src/protocol/mul/semi_honest.rs | 8 +- src/protocol/reveal/mod.rs | 10 +- .../{context_traits.rs => share_of_one.rs} | 6 +- src/protocol/sort/bit_permutation.rs | 10 +- src/protocol/sort/compose.rs | 2 +- .../sort/generate_sort_permutation.rs | 2 +- src/protocol/sort/reshare.rs | 2 +- src/protocol/sort/secureapplyinv.rs | 2 +- src/protocol/sort/shuffle.rs | 4 +- src/test_fixture/circuit.rs | 2 +- src/test_fixture/mod.rs | 16 +- 27 files changed, 88 insertions(+), 248 deletions(-) rename src/protocol/{context_traits.rs => share_of_one.rs} (82%) diff --git a/src/helpers/messaging.rs b/src/helpers/messaging.rs index 15ac916ea..78c95bc00 100644 --- a/src/helpers/messaging.rs +++ b/src/helpers/messaging.rs @@ -252,6 +252,7 @@ impl Debug for ReceiveRequest { mod tests { use crate::ff::Fp31; use crate::helpers::Role; + use crate::protocol::context::ProtocolContext; use crate::protocol::{QueryId, RecordId}; use crate::test_fixture::{make_contexts, make_world_with_config, TestWorldConfig}; diff --git a/src/protocol/attribution/accumulate_credit.rs b/src/protocol/attribution/accumulate_credit.rs index cccdfdb9c..da3e4d788 100644 --- a/src/protocol/attribution/accumulate_credit.rs +++ b/src/protocol/attribution/accumulate_credit.rs @@ -1,4 +1,5 @@ use super::{AccumulateCreditInputRow, AccumulateCreditOutputRow, AttributionInputRow, IterStep}; +use crate::protocol::context::SemiHonestProtocolContext; use crate::protocol::mul::SecureMul; use crate::{ error::Error, @@ -12,7 +13,6 @@ use crate::{ }; use futures::future::{try_join, try_join_all}; use std::iter::{repeat, zip}; -use crate::protocol::context::SemiHonestProtocolContext; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum Step { diff --git a/src/protocol/boolean/bitwise_lt.rs b/src/protocol/boolean/bitwise_lt.rs index 481d65656..a1233589b 100644 --- a/src/protocol/boolean/bitwise_lt.rs +++ b/src/protocol/boolean/bitwise_lt.rs @@ -3,11 +3,11 @@ use super::xor::xor; use super::BitOpStep; use crate::error::Error; use crate::ff::Field; +use crate::protocol::context::SemiHonestProtocolContext; use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; -use crate::protocol::context::SemiHonestProtocolContext; /// This is an implementation of Bitwise Less-Than on bitwise-shared numbers. /// @@ -168,6 +168,7 @@ impl AsRef for Step { #[cfg(test)] mod tests { use super::BitwiseLessThan; + use crate::protocol::context::ProtocolContext; use crate::{ error::Error, ff::{Field, Fp31, Fp32BitPrime, Int}, @@ -177,7 +178,6 @@ mod tests { }; use futures::future::try_join_all; use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, RngCore}; - use crate::protocol::context::ProtocolContext; /// From `Vec<[Replicated; 3]>`, create `Vec>` taking `i`'th share per row fn transpose(x: &[[Replicated; 3]], i: usize) -> Vec> { diff --git a/src/protocol/boolean/bitwise_sum.rs b/src/protocol/boolean/bitwise_sum.rs index 869926447..0745a07d5 100644 --- a/src/protocol/boolean/bitwise_sum.rs +++ b/src/protocol/boolean/bitwise_sum.rs @@ -1,8 +1,8 @@ use super::carries::Carries; use crate::error::BoxError; use crate::ff::Field; -use crate::protocol::{context::ProtocolContext, RecordId}; use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::{context::ProtocolContext, RecordId}; use crate::secret_sharing::Replicated; /// This is an implementation of Bitwise Sum on bitwise-shared numbers. @@ -83,6 +83,7 @@ impl AsRef for Step { #[cfg(test)] mod tests { use super::BitwiseSum; + use crate::protocol::context::ProtocolContext; use crate::{ error::BoxError, ff::{Field, Fp31, Fp32BitPrime, Int}, @@ -92,7 +93,6 @@ mod tests { }; use futures::future::try_join_all; use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, Rng, RngCore}; - use crate::protocol::context::ProtocolContext; /// From `Vec<[Replicated; 3]>`, create `Vec>` taking the `i`'th share per row fn transpose(x: &[[Replicated; 3]], i: usize) -> Vec> { diff --git a/src/protocol/boolean/carries.rs b/src/protocol/boolean/carries.rs index 2004f0d31..e64bec60f 100644 --- a/src/protocol/boolean/carries.rs +++ b/src/protocol/boolean/carries.rs @@ -1,11 +1,11 @@ use super::BitOpStep; use crate::error::Error; use crate::ff::Field; +use crate::protocol::context::SemiHonestProtocolContext; use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; -use crate::protocol::context::SemiHonestProtocolContext; #[derive(Clone, Debug)] /// This struct represents set/propagate/kill bits used to compute the carries. @@ -232,6 +232,7 @@ mod tests { use super::Carries; use crate::error::Error; use crate::ff::{Field, Fp31, Fp32BitPrime, Int}; + use crate::protocol::context::ProtocolContext; use crate::protocol::{QueryId, RecordId}; use crate::secret_sharing::Replicated; use crate::test_fixture::{ @@ -239,7 +240,6 @@ mod tests { }; use futures::future::try_join_all; use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, RngCore}; - use crate::protocol::context::ProtocolContext; /// From `Vec<[Replicated; 3]>`, create `Vec>` taking `i`'th share per row fn transpose(x: &[[Replicated; 3]], i: usize) -> Vec> { diff --git a/src/protocol/boolean/or.rs b/src/protocol/boolean/or.rs index 7078a375f..dec108d58 100644 --- a/src/protocol/boolean/or.rs +++ b/src/protocol/boolean/or.rs @@ -1,7 +1,7 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; /// Secure XOR protocol with two inputs, `a, b ∈ {0,1} ⊆ F_p`. @@ -20,6 +20,7 @@ pub async fn or( #[cfg(test)] mod tests { use super::or; + use crate::protocol::context::ProtocolContext; use crate::{ error::Error, ff::{Field, Fp31}, @@ -28,7 +29,6 @@ mod tests { }; use futures::future::try_join_all; use rand::rngs::mock::StepRng; - use crate::protocol::context::ProtocolContext; async fn or_fp31(a: Fp31, b: Fp31) -> Result { let world: TestWorld = make_world(QueryId); diff --git a/src/protocol/boolean/prefix_or.rs b/src/protocol/boolean/prefix_or.rs index d46b28237..36114aef8 100644 --- a/src/protocol/boolean/prefix_or.rs +++ b/src/protocol/boolean/prefix_or.rs @@ -1,11 +1,11 @@ use super::{or::or, BitOpStep}; use crate::error::Error; use crate::ff::Field; +use crate::protocol::context::SemiHonestProtocolContext; use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; -use crate::protocol::context::SemiHonestProtocolContext; /// This is an implementation of Prefix-Or on bitwise-shared numbers. /// @@ -304,6 +304,7 @@ impl AsRef for Step { #[cfg(test)] mod tests { use super::PrefixOr; + use crate::protocol::context::ProtocolContext; use crate::{ error::Error, ff::{Field, Fp2, Fp31}, @@ -315,7 +316,6 @@ mod tests { use rand::distributions::{Distribution, Standard}; use rand::{rngs::mock::StepRng, Rng}; use std::iter::zip; - use crate::protocol::context::ProtocolContext; const BITS: [usize; 2] = [16, 32]; const TEST_TRIES: usize = 16; diff --git a/src/protocol/boolean/xor.rs b/src/protocol/boolean/xor.rs index 09cf05895..bb8b64f59 100644 --- a/src/protocol/boolean/xor.rs +++ b/src/protocol/boolean/xor.rs @@ -1,7 +1,7 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::{mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; /// Secure XOR protocol with two inputs, `a, b ∈ {0,1} ⊆ F_p`. @@ -19,6 +19,7 @@ pub async fn xor( #[cfg(test)] mod tests { use super::xor; + use crate::protocol::context::ProtocolContext; use crate::{ error::Error, ff::{Field, Fp31}, @@ -27,7 +28,6 @@ mod tests { }; use futures::future::try_join_all; use rand::rngs::mock::StepRng; - use crate::protocol::context::ProtocolContext; async fn xor_fp31(a: Fp31, b: Fp31) -> Result { let world: TestWorld = make_world(QueryId); diff --git a/src/protocol/check_zero.rs b/src/protocol/check_zero.rs index 044017916..cad3cb018 100644 --- a/src/protocol/check_zero.rs +++ b/src/protocol/check_zero.rs @@ -1,3 +1,4 @@ +use crate::protocol::context::SemiHonestProtocolContext; use crate::protocol::mul::SecureMul; use crate::protocol::reveal::Reveal; use crate::{ @@ -7,7 +8,6 @@ use crate::{ secret_sharing::Replicated, }; use serde::{Deserialize, Serialize}; -use crate::protocol::context::SemiHonestProtocolContext; /// A message sent by each helper when they've multiplied their own shares #[derive(Debug, Serialize, Deserialize, Default)] @@ -86,9 +86,9 @@ pub async fn check_zero( pub mod tests { use crate::error::Error; use crate::ff::{Field, Fp31}; + use crate::protocol::context::ProtocolContext; use crate::protocol::{check_zero::check_zero, QueryId, RecordId}; use crate::test_fixture::{make_contexts, make_world, share, TestWorld}; - use crate::protocol::context::ProtocolContext; #[tokio::test] async fn basic() -> Result<(), Error> { diff --git a/src/protocol/context.rs b/src/protocol/context.rs index 9b3e29d76..1c7fc64e2 100644 --- a/src/protocol/context.rs +++ b/src/protocol/context.rs @@ -4,8 +4,9 @@ use std::sync::Arc; use super::{ prss::{IndexedSharedRandomness, SequentialSharedRandomness}, - RecordId, Step, Substep, + Step, Substep, }; +use crate::protocol::share_of_one::ShareOfOne; use crate::{ ff::Field, helpers::{ @@ -14,18 +15,19 @@ use crate::{ }, protocol::{malicious::SecurityValidatorAccumulator, prss::Endpoint as PrssEndpoint}, }; -use crate::protocol::context_traits::ShareOfOne; -use crate::protocol::malicious::SecurityValidator; + use crate::protocol::mul::SecureMul; +use crate::protocol::reveal::Reveal; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; - /// Context used by each helper to perform secure computation. Provides access to shared randomness /// generator and communication channel. -pub trait ProtocolContext : Clone +pub trait ProtocolContext: + Clone + SecureMul>::Share> + ShareOfOne>::Share> + + Reveal { /// Secret sharing type this context supports. type Share: SecretSharing; @@ -34,6 +36,7 @@ pub trait ProtocolContext : Clone fn role(&self) -> Role; /// A unique identifier for this stage of the protocol execution. + #[must_use] fn step(&self) -> &Step; /// Make a sub-context. @@ -60,13 +63,14 @@ pub trait ProtocolContext : Clone fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness); /// Get a set of communications channels to different peers. + #[must_use] fn mesh(&self) -> Mesh<'_, '_>; } /// Contains things that are applicable to any implementation of protocol context as see it today /// Every context requires access to current step, PRSS and communication and that is what this /// struct carries. -#[derive(Debug, Clone)] +#[derive(Clone, Debug)] struct ContextInner<'a> { role: Role, step: Step, @@ -74,7 +78,7 @@ struct ContextInner<'a> { gateway: &'a Gateway, } -impl <'a> ContextInner<'a> { +impl<'a> ContextInner<'a> { fn new(role: Role, prss: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { Self { role, @@ -111,7 +115,7 @@ pub struct MaliciousProtocolContext<'a, F: Field> { r_share: Replicated, } -impl <'a, F: Field> SemiHonestProtocolContext<'a, F> { +impl<'a, F: Field> SemiHonestProtocolContext<'a, F> { pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { Self { inner: Cow::Owned(ContextInner::new(role, participant, gateway)), @@ -136,7 +140,7 @@ impl <'a, F: Field> SemiHonestProtocolContext<'a, F> { } } -impl <'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { +impl<'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { type Share = Replicated; fn role(&self) -> Role { @@ -167,12 +171,14 @@ impl <'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { } } -impl <'a, F: Field> MaliciousProtocolContext<'a, F> { - pub fn new(role: Role, - participant: &'a PrssEndpoint, - gateway: &'a Gateway, - acc: SecurityValidatorAccumulator, - r_share: Replicated) -> Self { +impl<'a, F: Field> MaliciousProtocolContext<'a, F> { + pub fn new( + role: Role, + participant: &'a PrssEndpoint, + gateway: &'a Gateway, + acc: SecurityValidatorAccumulator, + r_share: Replicated, + ) -> Self { Self { inner: Cow::Owned(ContextInner::new(role, participant, gateway)), accumulator: acc, @@ -180,11 +186,15 @@ impl <'a, F: Field> MaliciousProtocolContext<'a, F> { } } - fn from_inner(inner: Cow<'a, ContextInner<'a>>, acc: SecurityValidatorAccumulator, r_share: Replicated) -> Self { + fn from_inner( + inner: Cow<'a, ContextInner<'a>>, + acc: SecurityValidatorAccumulator, + r_share: Replicated, + ) -> Self { Self { inner, accumulator: acc, - r_share + r_share, } } @@ -205,14 +215,11 @@ impl <'a, F: Field> MaliciousProtocolContext<'a, F> { /// and prss. #[must_use] pub fn to_semi_honest(self) -> SemiHonestProtocolContext<'a, F> { - let mut ctx = SemiHonestProtocolContext::from_inner(self.inner); - - ctx + SemiHonestProtocolContext::from_inner(self.inner) } } - -impl <'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { +impl<'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { type Share = MaliciousReplicated; fn role(&self) -> Role { @@ -232,7 +239,6 @@ impl <'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { } } - fn prss(&self) -> Arc { self.inner.prss.indexed(self.step()) } @@ -245,167 +251,3 @@ impl <'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { self.inner.gateway.mesh(self.step()) } } - -// impl<'a, F: Field, SS: SecretSharing> ProtocolContext<'a, SS, F> { -// pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { -// Self { -// role, -// step: Step::default(), -// prss: participant, -// gateway, -// accumulator: None, -// r_share: None, -// record_id: None, -// _marker: PhantomData::default(), -// } -// } -// -// /// The role of this context. -// #[must_use] -// pub fn role(&self) -> Role { -// self.role -// } -// -// /// A unique identifier for this stage of the protocol execution. -// #[must_use] -// pub fn step(&self) -> &Step { -// &self.step -// } -// -// /// Make a sub-context. -// /// Note that each invocation of this should use a unique value of `step`. -// #[must_use] -// pub fn narrow(&self, step: &S) -> Self { -// ProtocolContext { -// role: self.role, -// step: self.step.narrow(step), -// prss: self.prss, -// gateway: self.gateway, -// accumulator: self.accumulator.clone(), -// r_share: self.r_share.clone(), -// record_id: self.record_id, -// _marker: PhantomData::default(), -// } -// } -// -// #[must_use] -// /// Make a sub-context which is bound to a record in case the same step is bound to a different `record_id` -// /// # Panics -// /// Panics in case the context is already bound to the same `record_id` -// pub fn bind(&self, record_id: RecordId) -> Self { -// if let Some(prev_record_id) = self.record_id { -// panic!( -// "Cannot bind to {record_id:?} because already bound to record: {prev_record_id:?}" -// ) -// } -// -// ProtocolContext { -// role: self.role, -// // create a unique step that allows narrowing this context to the same step -// // if it is bound to a different record id -// step: Step::from_step_id(&self.step), -// prss: self.prss, -// gateway: self.gateway, -// accumulator: self.accumulator.clone(), -// r_share: self.r_share.clone(), -// record_id: Some(record_id), -// _marker: PhantomData::default(), -// } -// } -// -// /// Get the indexed PRSS instance for this step. It is safe to call this function -// /// multiple times. -// /// -// /// # Panics -// /// If `prss_rng()` is invoked for the same context, this will panic. Use of -// /// these two functions are mutually exclusive. -// #[must_use] -// pub fn prss(&self) -> Arc { -// self.prss.indexed(&self.step) -// } -// -// /// Get a pair of PRSS-based RNGs. The first is shared with the helper to the "left", -// /// the second is shared with the helper to the "right". -// /// -// /// # Panics -// /// This method can only be called once. This is also mutually exclusive with `prss()`. -// /// This will panic if you have previously invoked `prss()`. -// #[must_use] -// pub fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { -// self.prss.sequential(&self.step) -// } -// -// /// Get a set of communications channels to different peers. -// #[must_use] -// pub fn mesh(&self) -> Mesh<'_, '_> { -// self.gateway.mesh(&self.step) -// } -// } -// -// /// Implementation to upgrade semi-honest context to malicious. Only works for replicated secret -// /// sharing because it is not known yet how to do it for any other type of secret sharing. -// impl<'a, F: Field> ProtocolContext<'a, Replicated, F> { -// #[must_use] -// pub fn upgrade_to_malicious( -// self, -// accumulator: SecurityValidatorAccumulator, -// r_share: Replicated, -// ) -> ProtocolContext<'a, MaliciousReplicated, F> { -// ProtocolContext { -// role: self.role, -// step: self.step, -// prss: self.prss, -// gateway: self.gateway, -// accumulator: Some(accumulator), -// r_share: Some(r_share), -// record_id: self.record_id, -// _marker: PhantomData::default(), -// } -// } -// } -// -// /// Implementation that is specific to malicious contexts operating over replicated secret sharings. -// impl<'a, F: Field> ProtocolContext<'a, MaliciousReplicated, F> { -// /// Get the accumulator that collects messages MACs. -// /// -// /// ## Panics -// /// Does not panic in normal circumstances, panic here will indicate a bug in protocol context -// /// setup that left the accumulator field empty inside the malicious context. -// #[must_use] -// pub fn accumulator(&self) -> SecurityValidatorAccumulator { -// self.accumulator -// .as_ref() -// .expect("Accumulator must be set in the context in order to perform maliciously secure multiplication") -// .clone() -// } -// -// /// The `r_share` of this context. -// #[must_use] -// pub fn r_share(&self) -> Replicated { -// self.r_share -// .as_ref() -// .expect("r_share must be set in the context in order to perform maliciously") -// .clone() -// } -// -// /// In some occasions it is required to reinterpret malicious context as semi-honest. Ideally -// /// protocols should be generic over `SecretShare` trait and not requiring this cast and taking -// /// `ProtocolContext<'a, S: SecretShare, F: Field>` as the context. If that is not possible, -// /// this implementation makes it easier to reinterpret the context as semi-honest. -// /// -// /// The context received will be an exact copy of malicious, so it will be tied up to the same step -// /// and prss. -// #[must_use] -// pub fn to_semi_honest(self) -> ProtocolContext<'a, Replicated, F> { -// ProtocolContext { -// role: self.role, -// step: self.step, -// prss: self.prss, -// gateway: self.gateway, -// accumulator: None, -// r_share: None, -// record_id: self.record_id, -// _marker: PhantomData::default(), -// } -// } -// } diff --git a/src/protocol/malicious.rs b/src/protocol/malicious.rs index 8def0015e..3e6506f58 100644 --- a/src/protocol/malicious.rs +++ b/src/protocol/malicious.rs @@ -1,3 +1,4 @@ +use crate::protocol::context::SemiHonestProtocolContext; use crate::protocol::reveal::Reveal; use crate::{ error::Error, @@ -11,7 +12,6 @@ use crate::{ }; use futures::future::try_join; use std::sync::{Arc, Mutex, Weak}; -use crate::protocol::context::SemiHonestProtocolContext; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum Step { @@ -204,6 +204,7 @@ pub mod tests { use crate::error::Error; use crate::ff::Fp31; + use crate::protocol::context::ProtocolContext; use crate::protocol::mul::SecureMul; use crate::protocol::{ malicious::{SecurityValidator, Step}, @@ -215,7 +216,6 @@ pub mod tests { }; use futures::future::{try_join, try_join_all}; use proptest::prelude::Rng; - use crate::protocol::context::ProtocolContext; /// This is the simplest arithmetic circuit that allows us to test all of the pieces of this validator /// A - diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 8d08f43f5..59b8b06b5 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -3,12 +3,12 @@ mod batch; mod boolean; mod check_zero; pub mod context; -pub mod context_traits; pub mod malicious; mod modulus_conversion; pub mod mul; pub mod prss; mod reveal; +pub mod share_of_one; pub mod sort; use crate::error::Error; @@ -16,11 +16,6 @@ use std::fmt::Debug; use std::fmt::Formatter; use std::hash::Hash; use std::ops::AddAssign; -#[cfg(debug_assertions)] -use std::{ - collections::HashSet, - sync::{Arc, Mutex}, -}; /// Defines a unique step of the IPA protocol at a given level of implementation. /// @@ -110,9 +105,7 @@ impl AsRef for Step { impl From<&str> for Step { fn from(id: &str) -> Self { let id = id.strip_prefix('/').unwrap_or(id); - Step { - id: id.to_owned(), - } + Step { id: id.to_owned() } } } diff --git a/src/protocol/modulus_conversion/convert_shares.rs b/src/protocol/modulus_conversion/convert_shares.rs index c8aa32046..026b929ba 100644 --- a/src/protocol/modulus_conversion/convert_shares.rs +++ b/src/protocol/modulus_conversion/convert_shares.rs @@ -7,9 +7,9 @@ use crate::{ secret_sharing::Replicated, }; +use crate::protocol::context::SemiHonestProtocolContext; use futures::future::try_join_all; use std::iter::{repeat, zip}; -use crate::protocol::context::SemiHonestProtocolContext; pub struct XorShares { num_bits: u8, @@ -205,7 +205,6 @@ mod tests { use futures::future::try_join_all; use proptest::prelude::Rng; use std::iter::{repeat, zip}; - use crate::protocol::context::ProtocolContext; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] struct ModulusConversionTestStep { diff --git a/src/protocol/modulus_conversion/specialized_mul.rs b/src/protocol/modulus_conversion/specialized_mul.rs index 739b6ac0e..6290db20c 100644 --- a/src/protocol/modulus_conversion/specialized_mul.rs +++ b/src/protocol/modulus_conversion/specialized_mul.rs @@ -1,3 +1,4 @@ +use crate::protocol::context::SemiHonestProtocolContext; use crate::{ error::Error, ff::Field, @@ -5,7 +6,6 @@ use crate::{ protocol::{context::ProtocolContext, RecordId}, secret_sharing::Replicated, }; -use crate::protocol::context::SemiHonestProtocolContext; /// A highly specialized variant of the IKHC multiplication protocol which is only valid /// in the case where 4 of the 6 shares are zero. @@ -201,7 +201,6 @@ pub mod tests { }; use futures::future::try_join_all; use proptest::prelude::Rng; - use crate::protocol::context::ProtocolContext; #[tokio::test] async fn specialized_1_sequence() -> Result<(), Error> { diff --git a/src/protocol/mul/malicious.rs b/src/protocol/mul/malicious.rs index cc8a87341..48325d2dd 100644 --- a/src/protocol/mul/malicious.rs +++ b/src/protocol/mul/malicious.rs @@ -1,5 +1,6 @@ use crate::error::Error; use crate::ff::Field; +use crate::protocol::context::MaliciousProtocolContext; use crate::protocol::mul::SemiHonestMul; use crate::protocol::{ context::ProtocolContext, malicious::SecurityValidatorAccumulator, RecordId, @@ -7,7 +8,6 @@ use crate::protocol::{ use crate::secret_sharing::MaliciousReplicated; use futures::future::try_join; use std::fmt::Debug; -use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum Step { diff --git a/src/protocol/mul/mod.rs b/src/protocol/mul/mod.rs index fbb59bdde..f169bb02a 100644 --- a/src/protocol/mul/mod.rs +++ b/src/protocol/mul/mod.rs @@ -1,6 +1,6 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::{MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext}; +use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; use crate::protocol::RecordId; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; use async_trait::async_trait; diff --git a/src/protocol/mul/semi_honest.rs b/src/protocol/mul/semi_honest.rs index f3c834ecc..900774f65 100644 --- a/src/protocol/mul/semi_honest.rs +++ b/src/protocol/mul/semi_honest.rs @@ -1,10 +1,10 @@ use crate::error::Error; use crate::ff::Field; use crate::helpers::Direction; +use crate::protocol::context::SemiHonestProtocolContext; use crate::protocol::{context::ProtocolContext, RecordId}; use crate::secret_sharing::Replicated; use std::fmt::Debug; -use crate::protocol::context::SemiHonestProtocolContext; /// IKHC multiplication protocol /// for use with replicated secret sharing over some field F. @@ -66,8 +66,9 @@ pub mod tests { use crate::error::Error; use crate::ff::{Field, Fp31}; use crate::protocol::mul::SecureMul; - use crate::protocol::{context::ProtocolContext, QueryId, RecordId}; - use crate::secret_sharing::Replicated; + use crate::protocol::{QueryId, RecordId}; + + use crate::protocol::context::SemiHonestProtocolContext; use crate::test_fixture::{ make_contexts, make_world, share, validate_and_reconstruct, TestWorld, }; @@ -76,7 +77,6 @@ pub mod tests { use rand::{distributions::Standard, prelude::Distribution, rngs::mock::StepRng, RngCore}; use std::iter::{repeat, zip}; use std::sync::atomic::{AtomicU32, Ordering}; - use crate::protocol::context::SemiHonestProtocolContext; #[tokio::test] async fn basic() -> Result<(), Error> { diff --git a/src/protocol/reveal/mod.rs b/src/protocol/reveal/mod.rs index b35beed71..f5785df29 100644 --- a/src/protocol/reveal/mod.rs +++ b/src/protocol/reveal/mod.rs @@ -1,7 +1,9 @@ -use std::iter::{repeat, Rev, zip}; +use std::iter::{repeat, zip}; use crate::ff::Field; -use crate::protocol::context::{MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext}; +use crate::protocol::context::{ + MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext, +}; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; use crate::{ error::{BoxError, Error}, @@ -11,7 +13,6 @@ use crate::{ use async_trait::async_trait; use embed_doc_image::embed_doc_image; use futures::future::{try_join, try_join_all}; -use crate::protocol::malicious::SecurityValidator; /// Trait for reveal protocol to open a shared secret to all helpers inside the MPC ring. #[async_trait] @@ -26,7 +27,6 @@ pub trait Reveal { async fn reveal(self, record: RecordId, input: &Self::Share) -> Result; } - /// This implements a semi-honest reveal algorithm for replicated secret sharing. /// For simplicity, we consider a simple revealing in which each `P_i` sends `\[a\]_i` to `P_i+1` after which /// each helper has all three shares and can reconstruct `a` @@ -128,6 +128,7 @@ mod tests { use proptest::prelude::Rng; use tokio::try_join; + use crate::protocol::context::MaliciousProtocolContext; use crate::test_fixture::make_malicious_contexts; use crate::{ error::BoxError, @@ -141,7 +142,6 @@ mod tests { make_contexts, make_world, share, share_malicious, validate_and_reconstruct, TestWorld, }, }; - use crate::protocol::context::MaliciousProtocolContext; #[tokio::test] pub async fn simple() -> Result<(), BoxError> { diff --git a/src/protocol/context_traits.rs b/src/protocol/share_of_one.rs similarity index 82% rename from src/protocol/context_traits.rs rename to src/protocol/share_of_one.rs index d9eb7069a..38ff8de14 100644 --- a/src/protocol/context_traits.rs +++ b/src/protocol/share_of_one.rs @@ -1,8 +1,8 @@ +use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; use crate::{ ff::Field, secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}, }; -use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; use super::context::ProtocolContext; @@ -11,7 +11,7 @@ pub trait ShareOfOne { fn share_of_one(&self) -> Self::Share; } -impl ShareOfOne for SemiHonestProtocolContext<'_, F> { +impl ShareOfOne for SemiHonestProtocolContext<'_, F> { type Share = Replicated; fn share_of_one(&self) -> Self::Share { @@ -19,7 +19,7 @@ impl ShareOfOne for SemiHonestProtocolContext<'_, F> { } } -impl ShareOfOne for MaliciousProtocolContext<'_, F> { +impl ShareOfOne for MaliciousProtocolContext<'_, F> { type Share = MaliciousReplicated; fn share_of_one(&self) -> Self::Share { diff --git a/src/protocol/sort/bit_permutation.rs b/src/protocol/sort/bit_permutation.rs index 4a2345e1a..b10d6b304 100644 --- a/src/protocol/sort/bit_permutation.rs +++ b/src/protocol/sort/bit_permutation.rs @@ -3,11 +3,10 @@ use std::iter::{repeat, zip}; use crate::{ error::BoxError, ff::Field, - protocol::{context::ProtocolContext, context_traits::ShareOfOne, RecordId}, + protocol::{context::ProtocolContext, RecordId}, secret_sharing::SecretSharing, }; -use crate::protocol::mul::SecureMul; use embed_doc_image::embed_doc_image; use futures::future::try_join_all; @@ -33,7 +32,12 @@ use futures::future::try_join_all; /// /// ## Errors /// It will propagate errors from multiplication protocol. -pub async fn bit_permutation<'a, F: Field, S: SecretSharing, C: ProtocolContext>( +pub async fn bit_permutation< + 'a, + F: Field, + S: SecretSharing, + C: ProtocolContext, +>( ctx: C, input: &[S], ) -> Result, BoxError> { diff --git a/src/protocol/sort/compose.rs b/src/protocol/sort/compose.rs index 4121fb4f4..87fa7a63f 100644 --- a/src/protocol/sort/compose.rs +++ b/src/protocol/sort/compose.rs @@ -1,3 +1,4 @@ +use crate::protocol::context::SemiHonestProtocolContext; use crate::{ error::BoxError, ff::Field, @@ -5,7 +6,6 @@ use crate::{ secret_sharing::Replicated, }; use embed_doc_image::embed_doc_image; -use crate::protocol::context::SemiHonestProtocolContext; use super::{ apply::apply, diff --git a/src/protocol/sort/generate_sort_permutation.rs b/src/protocol/sort/generate_sort_permutation.rs index 9f63cf218..bdd658cba 100644 --- a/src/protocol/sort/generate_sort_permutation.rs +++ b/src/protocol/sort/generate_sort_permutation.rs @@ -12,8 +12,8 @@ use crate::{ }; use super::{compose::compose, secureapplyinv::secureapplyinv}; -use embed_doc_image::embed_doc_image; use crate::protocol::context::SemiHonestProtocolContext; +use embed_doc_image::embed_doc_image; /// This is an implementation of `GenPerm` (Algorithm 6) described in: /// "An Efficient Secure Three-Party Sorting Protocol with an Honest Majority" diff --git a/src/protocol/sort/reshare.rs b/src/protocol/sort/reshare.rs index b257c0267..accabeae9 100644 --- a/src/protocol/sort/reshare.rs +++ b/src/protocol/sort/reshare.rs @@ -1,4 +1,5 @@ use crate::ff::Field; +use crate::protocol::context::SemiHonestProtocolContext; use crate::{ error::BoxError, helpers::{Direction, Role}, @@ -6,7 +7,6 @@ use crate::{ secret_sharing::Replicated, }; use embed_doc_image::embed_doc_image; -use crate::protocol::context::SemiHonestProtocolContext; /// Reshare(i, \[x\]) // This implements reshare algorithm of "Efficient Secure Three-Party Sorting Protocol with an Honest Majority" at communication cost of 2R. diff --git a/src/protocol/sort/secureapplyinv.rs b/src/protocol/sort/secureapplyinv.rs index 56efe6a09..bbdf8f7d8 100644 --- a/src/protocol/sort/secureapplyinv.rs +++ b/src/protocol/sort/secureapplyinv.rs @@ -14,8 +14,8 @@ use super::{ apply::apply_inv, shuffle::{get_two_of_three_random_permutations, shuffle_shares}, }; -use futures::future::try_join; use crate::protocol::context::SemiHonestProtocolContext; +use futures::future::try_join; /// This is an implementation of ApplyInv (Algorithm 4) found in the paper: /// "An Efficient Secure Three-Party Sorting Protocol with an Honest Majority" diff --git a/src/protocol/sort/shuffle.rs b/src/protocol/sort/shuffle.rs index 56b01f0f2..b1976e6a5 100644 --- a/src/protocol/sort/shuffle.rs +++ b/src/protocol/sort/shuffle.rs @@ -4,6 +4,7 @@ use rand::seq::SliceRandom; use rand::SeedableRng; use rand_chacha::ChaCha8Rng; +use crate::protocol::context::SemiHonestProtocolContext; use crate::{ error::BoxError, ff::Field, @@ -11,7 +12,6 @@ use crate::{ protocol::{context::ProtocolContext, prss::IndexedSharedRandomness, RecordId, Substep}, secret_sharing::Replicated, }; -use crate::protocol::context::SemiHonestProtocolContext; use super::{ apply::{apply, apply_inv}, @@ -213,6 +213,7 @@ mod tests { use std::collections::HashSet; use std::iter::zip; + use crate::protocol::context::ProtocolContext; use crate::test_fixture::{logging, validate_list_of_shares}; use crate::{ ff::Fp31, @@ -229,7 +230,6 @@ mod tests { }, }; use futures::future::try_join_all; - use crate::protocol::context::ProtocolContext; #[test] fn random_sequence_generated() { diff --git a/src/test_fixture/circuit.rs b/src/test_fixture/circuit.rs index d6f3519f8..69d8de6ef 100644 --- a/src/test_fixture/circuit.rs +++ b/src/test_fixture/circuit.rs @@ -1,4 +1,5 @@ use crate::ff::Field; +use crate::protocol::context::ProtocolContext; use crate::protocol::mul::SecureMul; use crate::protocol::{QueryId, RecordId}; use crate::secret_sharing::Replicated; @@ -7,7 +8,6 @@ use crate::test_fixture::{ }; use futures_util::future::join_all; use rand::thread_rng; -use crate::protocol::context::ProtocolContext; /// Creates an arithmetic circuit with the given width and depth. /// diff --git a/src/test_fixture/mod.rs b/src/test_fixture/mod.rs index 2e5b20d34..6601e28ad 100644 --- a/src/test_fixture/mod.rs +++ b/src/test_fixture/mod.rs @@ -5,10 +5,11 @@ pub mod circuit; pub mod logging; pub mod network; -use std::fmt::Debug; use crate::ff::{Field, Fp31}; use crate::helpers::Role; -use crate::protocol::context::{MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext}; +use crate::protocol::context::{ + MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext, +}; use crate::protocol::malicious::SecurityValidator; use crate::protocol::prss::Endpoint as PrssEndpoint; use crate::protocol::Substep; @@ -17,6 +18,7 @@ use rand::distributions::Standard; use rand::prelude::Distribution; use rand::rngs::mock::StepRng; use rand::thread_rng; +use std::fmt::Debug; pub use sharing::{ share, share_malicious, validate_and_reconstruct, validate_list_of_shares, @@ -31,15 +33,15 @@ pub use world::{ /// # Panics /// Panics if world has more or less than 3 gateways/participants #[must_use] -pub fn make_contexts( - test_world: &TestWorld, -) -> [SemiHonestProtocolContext<'_, F>; 3] { +pub fn make_contexts(test_world: &TestWorld) -> [SemiHonestProtocolContext<'_, F>; 3] { test_world .gateways .iter() .zip(&test_world.participants) .zip(Role::all()) - .map(|((gateway, participant), role)| SemiHonestProtocolContext::new(*role, participant, gateway)) + .map(|((gateway, participant), role)| { + SemiHonestProtocolContext::new(*role, participant, gateway) + }) .collect::>() .try_into() .unwrap() @@ -68,7 +70,7 @@ pub fn make_malicious_contexts(test_world: &TestWorld) -> [MaliciousCo /// # Panics /// Never, but then Rust doesn't know that; this is only needed because we don't have `each_ref()`. #[must_use] -pub fn narrow_contexts<'a, C: Debug + ProtocolContext, F: Field, S: SecretSharing>( +pub fn narrow_contexts, F: Field, S: SecretSharing>( contexts: &[C; 3], step: &impl Substep, ) -> [C; 3] { From 0fdc2a7d62111366e9433f2dea7645bf45367c46 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 22:54:02 -0800 Subject: [PATCH 05/13] Create folder for protocol contexts --- src/protocol/context.rs | 253 ---------------------------- src/protocol/context/malicious.rs | 101 +++++++++++ src/protocol/context/mod.rs | 94 +++++++++++ src/protocol/context/semi_honest.rs | 75 +++++++++ 4 files changed, 270 insertions(+), 253 deletions(-) delete mode 100644 src/protocol/context.rs create mode 100644 src/protocol/context/malicious.rs create mode 100644 src/protocol/context/mod.rs create mode 100644 src/protocol/context/semi_honest.rs diff --git a/src/protocol/context.rs b/src/protocol/context.rs deleted file mode 100644 index 1c7fc64e2..000000000 --- a/src/protocol/context.rs +++ /dev/null @@ -1,253 +0,0 @@ -use std::borrow::Cow; -use std::marker::PhantomData; -use std::sync::Arc; - -use super::{ - prss::{IndexedSharedRandomness, SequentialSharedRandomness}, - Step, Substep, -}; -use crate::protocol::share_of_one::ShareOfOne; -use crate::{ - ff::Field, - helpers::{ - messaging::{Gateway, Mesh}, - Role, - }, - protocol::{malicious::SecurityValidatorAccumulator, prss::Endpoint as PrssEndpoint}, -}; - -use crate::protocol::mul::SecureMul; -use crate::protocol::reveal::Reveal; - -use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; - -/// Context used by each helper to perform secure computation. Provides access to shared randomness -/// generator and communication channel. -pub trait ProtocolContext: - Clone - + SecureMul>::Share> - + ShareOfOne>::Share> - + Reveal -{ - /// Secret sharing type this context supports. - type Share: SecretSharing; - - /// The role of this context. - fn role(&self) -> Role; - - /// A unique identifier for this stage of the protocol execution. - #[must_use] - fn step(&self) -> &Step; - - /// Make a sub-context. - /// Note that each invocation of this should use a unique value of `step`. - #[must_use] - fn narrow(&self, step: &S) -> Self; - - /// Get the indexed PRSS instance for this step. It is safe to call this function - /// multiple times. - /// - /// # Panics - /// If `prss_rng()` is invoked for the same context, this will panic. Use of - /// these two functions are mutually exclusive. - #[must_use] - fn prss(&self) -> Arc; - - /// Get a pair of PRSS-based RNGs. The first is shared with the helper to the "left", - /// the second is shared with the helper to the "right". - /// - /// # Panics - /// This method can only be called once. This is also mutually exclusive with `prss()`. - /// This will panic if you have previously invoked `prss()`. - #[must_use] - fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness); - - /// Get a set of communications channels to different peers. - #[must_use] - fn mesh(&self) -> Mesh<'_, '_>; -} - -/// Contains things that are applicable to any implementation of protocol context as see it today -/// Every context requires access to current step, PRSS and communication and that is what this -/// struct carries. -#[derive(Clone, Debug)] -struct ContextInner<'a> { - role: Role, - step: Step, - prss: &'a PrssEndpoint, - gateway: &'a Gateway, -} - -impl<'a> ContextInner<'a> { - fn new(role: Role, prss: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { - Self { - role, - step: Step::default(), - prss, - gateway, - } - } - - fn narrow(&self, step: &S) -> Self { - Self { - role: self.role, - step: self.step.narrow(step), - prss: self.prss, - gateway: self.gateway, - } - } -} - -/// Context for protocol executions suitable for semi-honest security model, i.e. secure against -/// honest-but-curious adversary parties. -#[derive(Clone, Debug)] -pub struct SemiHonestProtocolContext<'a, F: Field> { - inner: Cow<'a, ContextInner<'a>>, - _marker: PhantomData, -} - -/// Represents protocol context in malicious setting, i.e. secure against one active adversary -/// in 3 party MPC ring. -#[derive(Clone, Debug)] -pub struct MaliciousProtocolContext<'a, F: Field> { - inner: Cow<'a, ContextInner<'a>>, - accumulator: SecurityValidatorAccumulator, - r_share: Replicated, -} - -impl<'a, F: Field> SemiHonestProtocolContext<'a, F> { - pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { - Self { - inner: Cow::Owned(ContextInner::new(role, participant, gateway)), - _marker: PhantomData::default(), - } - } - - fn from_inner(inner: Cow<'a, ContextInner<'a>>) -> Self { - Self { - inner, - _marker: PhantomData::default(), - } - } - - #[must_use] - pub fn upgrade_to_malicious( - self, - accumulator: SecurityValidatorAccumulator, - r_share: Replicated, - ) -> MaliciousProtocolContext<'a, F> { - MaliciousProtocolContext::from_inner(self.inner, accumulator, r_share) - } -} - -impl<'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { - type Share = Replicated; - - fn role(&self) -> Role { - self.inner.role - } - - fn step(&self) -> &Step { - &self.inner.step - } - - fn narrow(&self, step: &S) -> Self { - Self { - inner: Cow::Owned(self.inner.narrow(step)), - _marker: PhantomData::default(), - } - } - - fn prss(&self) -> Arc { - self.inner.prss.indexed(self.step()) - } - - fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { - self.inner.prss.sequential(self.step()) - } - - fn mesh(&self) -> Mesh<'_, '_> { - self.inner.gateway.mesh(self.step()) - } -} - -impl<'a, F: Field> MaliciousProtocolContext<'a, F> { - pub fn new( - role: Role, - participant: &'a PrssEndpoint, - gateway: &'a Gateway, - acc: SecurityValidatorAccumulator, - r_share: Replicated, - ) -> Self { - Self { - inner: Cow::Owned(ContextInner::new(role, participant, gateway)), - accumulator: acc, - r_share, - } - } - - fn from_inner( - inner: Cow<'a, ContextInner<'a>>, - acc: SecurityValidatorAccumulator, - r_share: Replicated, - ) -> Self { - Self { - inner, - accumulator: acc, - r_share, - } - } - - pub fn r_share(&self) -> &Replicated { - &self.r_share - } - - pub fn accumulator(&self) -> SecurityValidatorAccumulator { - self.accumulator.clone() - } - - /// Sometimes it is required to reinterpret malicious context as semi-honest. Ideally - /// protocols should be generic over `SecretShare` trait and not requiring this cast and taking - /// `ProtocolContext<'a, S: SecretShare, F: Field>` as the context. If that is not possible, - /// this implementation makes it easier to reinterpret the context as semi-honest. - /// - /// The context received will be an exact copy of malicious, so it will be tied up to the same step - /// and prss. - #[must_use] - pub fn to_semi_honest(self) -> SemiHonestProtocolContext<'a, F> { - SemiHonestProtocolContext::from_inner(self.inner) - } -} - -impl<'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { - type Share = MaliciousReplicated; - - fn role(&self) -> Role { - self.inner.role - } - - fn step(&self) -> &Step { - &self.inner.step - } - - fn narrow(&self, step: &S) -> Self { - Self { - inner: Cow::Owned(self.inner.narrow(step)), - accumulator: self.accumulator.clone(), - // TODO (alex, mt) - is cloning ok here or we need to Cow it? - r_share: self.r_share.clone(), - } - } - - fn prss(&self) -> Arc { - self.inner.prss.indexed(self.step()) - } - - fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { - self.inner.prss.sequential(self.step()) - } - - fn mesh(&self) -> Mesh<'_, '_> { - self.inner.gateway.mesh(self.step()) - } -} diff --git a/src/protocol/context/malicious.rs b/src/protocol/context/malicious.rs new file mode 100644 index 000000000..f566184ba --- /dev/null +++ b/src/protocol/context/malicious.rs @@ -0,0 +1,101 @@ +use std::borrow::Cow; +use std::sync::Arc; +use crate::ff::Field; +use crate::helpers::messaging::{Gateway, Mesh}; +use crate::helpers::Role; +use crate::protocol::context::{ContextInner, ProtocolContext, SemiHonestProtocolContext}; +use crate::protocol::malicious::SecurityValidatorAccumulator; +use crate::protocol::{Step, Substep}; +use crate::protocol::prss::{Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness}; +use crate::secret_sharing::{MaliciousReplicated, Replicated}; + +/// Represents protocol context in malicious setting, i.e. secure against one active adversary +/// in 3 party MPC ring. +#[derive(Clone, Debug)] +pub struct MaliciousProtocolContext<'a, F: Field> { + inner: Cow<'a, ContextInner<'a>>, + accumulator: SecurityValidatorAccumulator, + r_share: Replicated, +} + + +impl<'a, F: Field> MaliciousProtocolContext<'a, F> { + pub fn new( + role: Role, + participant: &'a PrssEndpoint, + gateway: &'a Gateway, + acc: SecurityValidatorAccumulator, + r_share: Replicated, + ) -> Self { + Self { + inner: Cow::Owned(ContextInner::new(role, participant, gateway)), + accumulator: acc, + r_share, + } + } + + pub(super) fn from_inner( + inner: Cow<'a, ContextInner<'a>>, + acc: SecurityValidatorAccumulator, + r_share: Replicated, + ) -> Self { + Self { + inner, + accumulator: acc, + r_share, + } + } + + pub fn r_share(&self) -> &Replicated { + &self.r_share + } + + pub fn accumulator(&self) -> SecurityValidatorAccumulator { + self.accumulator.clone() + } + + /// Sometimes it is required to reinterpret malicious context as semi-honest. Ideally + /// protocols should be generic over `SecretShare` trait and not requiring this cast and taking + /// `ProtocolContext<'a, S: SecretShare, F: Field>` as the context. If that is not possible, + /// this implementation makes it easier to reinterpret the context as semi-honest. + /// + /// The context received will be an exact copy of malicious, so it will be tied up to the same step + /// and prss. + #[must_use] + pub fn to_semi_honest(self) -> SemiHonestProtocolContext<'a, F> { + SemiHonestProtocolContext::from_inner(self.inner) + } +} + +impl<'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { + type Share = MaliciousReplicated; + + fn role(&self) -> Role { + self.inner.role + } + + fn step(&self) -> &Step { + &self.inner.step + } + + fn narrow(&self, step: &S) -> Self { + Self { + inner: Cow::Owned(self.inner.narrow(step)), + accumulator: self.accumulator.clone(), + // TODO (alex, mt) - is cloning ok here or we need to Cow it? + r_share: self.r_share.clone(), + } + } + + fn prss(&self) -> Arc { + self.inner.prss.indexed(self.step()) + } + + fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { + self.inner.prss.sequential(self.step()) + } + + fn mesh(&self) -> Mesh<'_, '_> { + self.inner.gateway.mesh(self.step()) + } +} diff --git a/src/protocol/context/mod.rs b/src/protocol/context/mod.rs new file mode 100644 index 000000000..0cbdaa9dc --- /dev/null +++ b/src/protocol/context/mod.rs @@ -0,0 +1,94 @@ +use std::sync::Arc; +use crate::ff::Field; +use crate::helpers::messaging::{Gateway, Mesh}; +use crate::helpers::Role; +use crate::protocol::mul::SecureMul; +use crate::protocol::reveal::Reveal; +use crate::protocol::share_of_one::ShareOfOne; +use crate::protocol::{Step, Substep}; +use crate::protocol::prss::{Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness}; +use crate::secret_sharing::SecretSharing; + +mod malicious; +mod semi_honest; + +pub use malicious::MaliciousProtocolContext; +pub use semi_honest::SemiHonestProtocolContext; + +/// Context used by each helper to perform secure computation. Provides access to shared randomness +/// generator and communication channel. +pub trait ProtocolContext: + Clone + + SecureMul>::Share> + + ShareOfOne>::Share> + + Reveal +{ + /// Secret sharing type this context supports. + type Share: SecretSharing; + + /// The role of this context. + fn role(&self) -> Role; + + /// A unique identifier for this stage of the protocol execution. + #[must_use] + fn step(&self) -> &Step; + + /// Make a sub-context. + /// Note that each invocation of this should use a unique value of `step`. + #[must_use] + fn narrow(&self, step: &S) -> Self; + + /// Get the indexed PRSS instance for this step. It is safe to call this function + /// multiple times. + /// + /// # Panics + /// If `prss_rng()` is invoked for the same context, this will panic. Use of + /// these two functions are mutually exclusive. + #[must_use] + fn prss(&self) -> Arc; + + /// Get a pair of PRSS-based RNGs. The first is shared with the helper to the "left", + /// the second is shared with the helper to the "right". + /// + /// # Panics + /// This method can only be called once. This is also mutually exclusive with `prss()`. + /// This will panic if you have previously invoked `prss()`. + #[must_use] + fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness); + + /// Get a set of communications channels to different peers. + #[must_use] + fn mesh(&self) -> Mesh<'_, '_>; +} + +/// Contains things that are applicable to any implementation of protocol context as see it today +/// Every context requires access to current step, PRSS and communication and that is what this +/// struct carries. +#[derive(Clone, Debug)] +struct ContextInner<'a> { + role: Role, + step: Step, + prss: &'a PrssEndpoint, + gateway: &'a Gateway, +} + +impl<'a> ContextInner<'a> { + fn new(role: Role, prss: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { + Self { + role, + step: Step::default(), + prss, + gateway, + } + } + + fn narrow(&self, step: &S) -> Self { + Self { + role: self.role, + step: self.step.narrow(step), + prss: self.prss, + gateway: self.gateway, + } + } +} + diff --git a/src/protocol/context/semi_honest.rs b/src/protocol/context/semi_honest.rs new file mode 100644 index 000000000..467b747ec --- /dev/null +++ b/src/protocol/context/semi_honest.rs @@ -0,0 +1,75 @@ +use std::borrow::Cow; +use std::marker::PhantomData; +use std::sync::Arc; +use crate::ff::Field; +use crate::helpers::messaging::{Gateway, Mesh}; +use crate::helpers::Role; +use crate::protocol::context::{ContextInner, MaliciousProtocolContext, ProtocolContext}; +use crate::protocol::malicious::SecurityValidatorAccumulator; +use crate::protocol::{Step, Substep}; +use crate::protocol::prss::{Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness}; +use crate::secret_sharing::Replicated; + +/// Context for protocol executions suitable for semi-honest security model, i.e. secure against +/// honest-but-curious adversary parties. +#[derive(Clone, Debug)] +pub struct SemiHonestProtocolContext<'a, F: Field> { + inner: Cow<'a, ContextInner<'a>>, + _marker: PhantomData, +} + +impl<'a, F: Field> SemiHonestProtocolContext<'a, F> { + pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { + Self { + inner: Cow::Owned(ContextInner::new(role, participant, gateway)), + _marker: PhantomData::default(), + } + } + + pub(super) fn from_inner(inner: Cow<'a, ContextInner<'a>>) -> Self { + Self { + inner, + _marker: PhantomData::default(), + } + } + + #[must_use] + pub fn upgrade_to_malicious( + self, + accumulator: SecurityValidatorAccumulator, + r_share: Replicated, + ) -> MaliciousProtocolContext<'a, F> { + MaliciousProtocolContext::from_inner(self.inner, accumulator, r_share) + } +} + +impl<'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { + type Share = Replicated; + + fn role(&self) -> Role { + self.inner.role + } + + fn step(&self) -> &Step { + &self.inner.step + } + + fn narrow(&self, step: &S) -> Self { + Self { + inner: Cow::Owned(self.inner.narrow(step)), + _marker: PhantomData::default(), + } + } + + fn prss(&self) -> Arc { + self.inner.prss.indexed(self.step()) + } + + fn prss_rng(&self) -> (SequentialSharedRandomness, SequentialSharedRandomness) { + self.inner.prss.sequential(self.step()) + } + + fn mesh(&self) -> Mesh<'_, '_> { + self.inner.gateway.mesh(self.step()) + } +} From 7b7d3d46b3ad70841951cc7c0c3a0bb9d975ce1a Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 22:58:42 -0800 Subject: [PATCH 06/13] Bring back step string validation in debug mode --- src/protocol/context/malicious.rs | 9 +++++---- src/protocol/context/mod.rs | 7 ++++--- src/protocol/context/semi_honest.rs | 10 ++++++---- src/protocol/mod.rs | 6 ++++++ 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/protocol/context/malicious.rs b/src/protocol/context/malicious.rs index f566184ba..6e3c85187 100644 --- a/src/protocol/context/malicious.rs +++ b/src/protocol/context/malicious.rs @@ -1,13 +1,15 @@ -use std::borrow::Cow; -use std::sync::Arc; use crate::ff::Field; use crate::helpers::messaging::{Gateway, Mesh}; use crate::helpers::Role; use crate::protocol::context::{ContextInner, ProtocolContext, SemiHonestProtocolContext}; use crate::protocol::malicious::SecurityValidatorAccumulator; +use crate::protocol::prss::{ + Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, +}; use crate::protocol::{Step, Substep}; -use crate::protocol::prss::{Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness}; use crate::secret_sharing::{MaliciousReplicated, Replicated}; +use std::borrow::Cow; +use std::sync::Arc; /// Represents protocol context in malicious setting, i.e. secure against one active adversary /// in 3 party MPC ring. @@ -18,7 +20,6 @@ pub struct MaliciousProtocolContext<'a, F: Field> { r_share: Replicated, } - impl<'a, F: Field> MaliciousProtocolContext<'a, F> { pub fn new( role: Role, diff --git a/src/protocol/context/mod.rs b/src/protocol/context/mod.rs index 0cbdaa9dc..0f3b4ccdf 100644 --- a/src/protocol/context/mod.rs +++ b/src/protocol/context/mod.rs @@ -1,13 +1,15 @@ -use std::sync::Arc; use crate::ff::Field; use crate::helpers::messaging::{Gateway, Mesh}; use crate::helpers::Role; use crate::protocol::mul::SecureMul; +use crate::protocol::prss::{ + Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, +}; use crate::protocol::reveal::Reveal; use crate::protocol::share_of_one::ShareOfOne; use crate::protocol::{Step, Substep}; -use crate::protocol::prss::{Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness}; use crate::secret_sharing::SecretSharing; +use std::sync::Arc; mod malicious; mod semi_honest; @@ -91,4 +93,3 @@ impl<'a> ContextInner<'a> { } } } - diff --git a/src/protocol/context/semi_honest.rs b/src/protocol/context/semi_honest.rs index 467b747ec..da6b6a242 100644 --- a/src/protocol/context/semi_honest.rs +++ b/src/protocol/context/semi_honest.rs @@ -1,14 +1,16 @@ -use std::borrow::Cow; -use std::marker::PhantomData; -use std::sync::Arc; use crate::ff::Field; use crate::helpers::messaging::{Gateway, Mesh}; use crate::helpers::Role; use crate::protocol::context::{ContextInner, MaliciousProtocolContext, ProtocolContext}; use crate::protocol::malicious::SecurityValidatorAccumulator; +use crate::protocol::prss::{ + Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, +}; use crate::protocol::{Step, Substep}; -use crate::protocol::prss::{Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness}; use crate::secret_sharing::Replicated; +use std::borrow::Cow; +use std::marker::PhantomData; +use std::sync::Arc; /// Context for protocol executions suitable for semi-honest security model, i.e. secure against /// honest-but-curious adversary parties. diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 59b8b06b5..4cf5ff194 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -80,6 +80,12 @@ impl Step { /// value of the step doesn't include '/' (which would lead to a bad outcome). #[must_use] pub fn narrow(&self, step: &S) -> Self { + #[cfg(debug_assertions)] + { + let s = String::from(step.as_ref()); + assert!(!s.contains('/'), "The string for a step cannot contain '/'"); + } + Self { id: self.id.clone() + "/" + step.as_ref(), } From d97a5800baea8dbfea707fe3322b1f3d2ff19cda Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 23:18:11 -0800 Subject: [PATCH 07/13] Get rid of Cow inside protocol contexts --- src/protocol/context/malicious.rs | 9 ++++----- src/protocol/context/semi_honest.rs | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/protocol/context/malicious.rs b/src/protocol/context/malicious.rs index 6e3c85187..c09ebcd73 100644 --- a/src/protocol/context/malicious.rs +++ b/src/protocol/context/malicious.rs @@ -8,14 +8,13 @@ use crate::protocol::prss::{ }; use crate::protocol::{Step, Substep}; use crate::secret_sharing::{MaliciousReplicated, Replicated}; -use std::borrow::Cow; use std::sync::Arc; /// Represents protocol context in malicious setting, i.e. secure against one active adversary /// in 3 party MPC ring. #[derive(Clone, Debug)] pub struct MaliciousProtocolContext<'a, F: Field> { - inner: Cow<'a, ContextInner<'a>>, + inner: ContextInner<'a>, accumulator: SecurityValidatorAccumulator, r_share: Replicated, } @@ -29,14 +28,14 @@ impl<'a, F: Field> MaliciousProtocolContext<'a, F> { r_share: Replicated, ) -> Self { Self { - inner: Cow::Owned(ContextInner::new(role, participant, gateway)), + inner: ContextInner::new(role, participant, gateway), accumulator: acc, r_share, } } pub(super) fn from_inner( - inner: Cow<'a, ContextInner<'a>>, + inner: ContextInner<'a>, acc: SecurityValidatorAccumulator, r_share: Replicated, ) -> Self { @@ -81,7 +80,7 @@ impl<'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { fn narrow(&self, step: &S) -> Self { Self { - inner: Cow::Owned(self.inner.narrow(step)), + inner: self.inner.narrow(step), accumulator: self.accumulator.clone(), // TODO (alex, mt) - is cloning ok here or we need to Cow it? r_share: self.r_share.clone(), diff --git a/src/protocol/context/semi_honest.rs b/src/protocol/context/semi_honest.rs index da6b6a242..9fad5f897 100644 --- a/src/protocol/context/semi_honest.rs +++ b/src/protocol/context/semi_honest.rs @@ -8,7 +8,6 @@ use crate::protocol::prss::{ }; use crate::protocol::{Step, Substep}; use crate::secret_sharing::Replicated; -use std::borrow::Cow; use std::marker::PhantomData; use std::sync::Arc; @@ -16,19 +15,19 @@ use std::sync::Arc; /// honest-but-curious adversary parties. #[derive(Clone, Debug)] pub struct SemiHonestProtocolContext<'a, F: Field> { - inner: Cow<'a, ContextInner<'a>>, + inner: ContextInner<'a>, _marker: PhantomData, } impl<'a, F: Field> SemiHonestProtocolContext<'a, F> { pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { Self { - inner: Cow::Owned(ContextInner::new(role, participant, gateway)), + inner: ContextInner::new(role, participant, gateway), _marker: PhantomData::default(), } } - pub(super) fn from_inner(inner: Cow<'a, ContextInner<'a>>) -> Self { + pub(super) fn from_inner(inner: ContextInner<'a>) -> Self { Self { inner, _marker: PhantomData::default(), @@ -58,7 +57,7 @@ impl<'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { fn narrow(&self, step: &S) -> Self { Self { - inner: Cow::Owned(self.inner.narrow(step)), + inner: self.inner.narrow(step), _marker: PhantomData::default(), } } From e086292721d3b91f8647f0c94a5afec17d5733c8 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 23:28:05 -0800 Subject: [PATCH 08/13] Delete share_of_one module --- src/protocol/context/malicious.rs | 8 ++++---- src/protocol/context/mod.rs | 6 ++++-- src/protocol/context/semi_honest.rs | 4 ++++ src/protocol/mod.rs | 1 - src/protocol/share_of_one.rs | 28 ---------------------------- 5 files changed, 12 insertions(+), 35 deletions(-) delete mode 100644 src/protocol/share_of_one.rs diff --git a/src/protocol/context/malicious.rs b/src/protocol/context/malicious.rs index c09ebcd73..ade6fb725 100644 --- a/src/protocol/context/malicious.rs +++ b/src/protocol/context/malicious.rs @@ -46,10 +46,6 @@ impl<'a, F: Field> MaliciousProtocolContext<'a, F> { } } - pub fn r_share(&self) -> &Replicated { - &self.r_share - } - pub fn accumulator(&self) -> SecurityValidatorAccumulator { self.accumulator.clone() } @@ -98,4 +94,8 @@ impl<'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { fn mesh(&self) -> Mesh<'_, '_> { self.inner.gateway.mesh(self.step()) } + + fn share_of_one(&self) -> >::Share { + MaliciousReplicated::one(self.role(), self.r_share.clone()) + } } diff --git a/src/protocol/context/mod.rs b/src/protocol/context/mod.rs index 0f3b4ccdf..f349c9c5c 100644 --- a/src/protocol/context/mod.rs +++ b/src/protocol/context/mod.rs @@ -6,7 +6,6 @@ use crate::protocol::prss::{ Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, }; use crate::protocol::reveal::Reveal; -use crate::protocol::share_of_one::ShareOfOne; use crate::protocol::{Step, Substep}; use crate::secret_sharing::SecretSharing; use std::sync::Arc; @@ -22,7 +21,7 @@ pub use semi_honest::SemiHonestProtocolContext; pub trait ProtocolContext: Clone + SecureMul>::Share> - + ShareOfOne>::Share> + // + ShareOfOne>::Share> + Reveal { /// Secret sharing type this context supports. @@ -61,6 +60,9 @@ pub trait ProtocolContext: /// Get a set of communications channels to different peers. #[must_use] fn mesh(&self) -> Mesh<'_, '_>; + + /// Generates a new share of one + fn share_of_one(&self) -> >::Share; } /// Contains things that are applicable to any implementation of protocol context as see it today diff --git a/src/protocol/context/semi_honest.rs b/src/protocol/context/semi_honest.rs index 9fad5f897..95aa975a0 100644 --- a/src/protocol/context/semi_honest.rs +++ b/src/protocol/context/semi_honest.rs @@ -73,4 +73,8 @@ impl<'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { fn mesh(&self) -> Mesh<'_, '_> { self.inner.gateway.mesh(self.step()) } + + fn share_of_one(&self) -> >::Share { + Replicated::one(self.role()) + } } diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 4cf5ff194..b2f3537f2 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -8,7 +8,6 @@ mod modulus_conversion; pub mod mul; pub mod prss; mod reveal; -pub mod share_of_one; pub mod sort; use crate::error::Error; diff --git a/src/protocol/share_of_one.rs b/src/protocol/share_of_one.rs deleted file mode 100644 index 38ff8de14..000000000 --- a/src/protocol/share_of_one.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; -use crate::{ - ff::Field, - secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}, -}; - -use super::context::ProtocolContext; - -pub trait ShareOfOne { - type Share: SecretSharing; - fn share_of_one(&self) -> Self::Share; -} - -impl ShareOfOne for SemiHonestProtocolContext<'_, F> { - type Share = Replicated; - - fn share_of_one(&self) -> Self::Share { - Replicated::one(self.role()) - } -} - -impl ShareOfOne for MaliciousProtocolContext<'_, F> { - type Share = MaliciousReplicated; - - fn share_of_one(&self) -> Self::Share { - MaliciousReplicated::one(self.role(), self.r_share().clone()) - } -} From 5ed71ed3296780e29b803ea426fde9f2fa1b6d70 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Thu, 17 Nov 2022 23:38:42 -0800 Subject: [PATCH 09/13] Remove commented lines (can someone create a clippy rule for that?) --- src/protocol/context/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/protocol/context/mod.rs b/src/protocol/context/mod.rs index f349c9c5c..a12bdba4b 100644 --- a/src/protocol/context/mod.rs +++ b/src/protocol/context/mod.rs @@ -19,10 +19,7 @@ pub use semi_honest::SemiHonestProtocolContext; /// Context used by each helper to perform secure computation. Provides access to shared randomness /// generator and communication channel. pub trait ProtocolContext: - Clone - + SecureMul>::Share> - // + ShareOfOne>::Share> - + Reveal + Clone + SecureMul>::Share> + Reveal { /// Secret sharing type this context supports. type Share: SecretSharing; From 15cb5f154be4f1d511394a0b202d6a93976fcd6e Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Mon, 21 Nov 2022 11:30:25 -0800 Subject: [PATCH 10/13] Remove GAT from Reveal and make it look the same as SecureMul. We don't need this advanced feature anymore --- src/protocol/context/mod.rs | 4 +++- src/protocol/reveal/mod.rs | 26 +++++++++----------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/protocol/context/mod.rs b/src/protocol/context/mod.rs index a12bdba4b..9d0bb2d12 100644 --- a/src/protocol/context/mod.rs +++ b/src/protocol/context/mod.rs @@ -19,7 +19,9 @@ pub use semi_honest::SemiHonestProtocolContext; /// Context used by each helper to perform secure computation. Provides access to shared randomness /// generator and communication channel. pub trait ProtocolContext: - Clone + SecureMul>::Share> + Reveal + Clone + + SecureMul>::Share> + + Reveal>::Share> { /// Secret sharing type this context supports. type Share: SecretSharing; diff --git a/src/protocol/reveal/mod.rs b/src/protocol/reveal/mod.rs index f5785df29..77a77a6e5 100644 --- a/src/protocol/reveal/mod.rs +++ b/src/protocol/reveal/mod.rs @@ -16,15 +16,15 @@ use futures::future::{try_join, try_join_all}; /// Trait for reveal protocol to open a shared secret to all helpers inside the MPC ring. #[async_trait] -pub trait Reveal { +pub trait Reveal { /// Secret sharing type that reveal implementation works with. Note that field type does not /// matter - implementations must be able to reveal secret value from any field. - type Share: SecretSharing; + type Share: SecretSharing; /// reveal the secret to all helpers in MPC circuit. Note that after method is called, /// it must be assumed that the secret value has been revealed to at least one of the helpers. /// Even in case when method never terminates, returns an error, etc. - async fn reveal(self, record: RecordId, input: &Self::Share) -> Result; + async fn reveal(self, record: RecordId, input: &Self::Share) -> Result; } /// This implements a semi-honest reveal algorithm for replicated secret sharing. @@ -40,14 +40,10 @@ pub trait Reveal { /// i.e. their own shares and received share. #[async_trait] #[embed_doc_image("reveal", "images/reveal.png")] -impl Reveal for SemiHonestProtocolContext<'_, G> { - type Share = Replicated; +impl Reveal for SemiHonestProtocolContext<'_, F> { + type Share = Replicated; - async fn reveal( - self, - record_id: RecordId, - input: &Self::Share, - ) -> Result { + async fn reveal(self, record_id: RecordId, input: &Self::Share) -> Result { let (role, channel) = (self.role(), self.mesh()); let (left, right) = input.as_tuple(); @@ -69,14 +65,10 @@ impl Reveal for SemiHonestProtocolContext<'_, G> { /// to both helpers (right and left) and upon receiving 2 shares from peers it validates that they /// indeed match. #[async_trait] -impl Reveal for MaliciousProtocolContext<'_, G> { - type Share = MaliciousReplicated; +impl Reveal for MaliciousProtocolContext<'_, F> { + type Share = MaliciousReplicated; - async fn reveal( - self, - record_id: RecordId, - input: &Self::Share, - ) -> Result { + async fn reveal(self, record_id: RecordId, input: &Self::Share) -> Result { let (role, channel) = (self.role(), self.mesh()); let (left, right) = input.x().as_tuple(); From 8e573093f01553851faaea8f1bb8e5a0b24048d2 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Mon, 21 Nov 2022 17:51:01 -0800 Subject: [PATCH 11/13] s/ProtocolContext/Context --- src/helpers/messaging.rs | 2 +- src/protocol/attribution/accumulate_credit.rs | 8 ++++---- src/protocol/boolean/bitwise_lt.rs | 14 ++++++------- src/protocol/boolean/bitwise_sum.rs | 8 ++++---- src/protocol/boolean/carries.rs | 14 ++++++------- src/protocol/boolean/or.rs | 8 ++++---- src/protocol/boolean/prefix_or.rs | 20 +++++++++---------- src/protocol/boolean/xor.rs | 6 +++--- src/protocol/check_zero.rs | 8 ++++---- src/protocol/context/malicious.rs | 14 ++++++------- src/protocol/context/mod.rs | 12 +++++------ src/protocol/context/semi_honest.rs | 14 ++++++------- src/protocol/malicious.rs | 10 +++++----- .../modulus_conversion/convert_shares.rs | 12 +++++------ .../modulus_conversion/specialized_mul.rs | 8 ++++---- src/protocol/mul/malicious.rs | 10 ++++------ src/protocol/mul/mod.rs | 6 +++--- src/protocol/mul/semi_honest.rs | 12 +++++------ src/protocol/reveal/mod.rs | 16 +++++++-------- src/protocol/sort/bit_permutation.rs | 9 ++------- src/protocol/sort/compose.rs | 6 +++--- .../sort/generate_sort_permutation.rs | 6 +++--- src/protocol/sort/reshare.rs | 6 +++--- src/protocol/sort/secureapplyinv.rs | 6 +++--- src/protocol/sort/shuffle.rs | 14 ++++++------- src/test_fixture/circuit.rs | 2 +- src/test_fixture/mod.rs | 20 ++++++++----------- 27 files changed, 129 insertions(+), 142 deletions(-) diff --git a/src/helpers/messaging.rs b/src/helpers/messaging.rs index 78c95bc00..9abb741d9 100644 --- a/src/helpers/messaging.rs +++ b/src/helpers/messaging.rs @@ -252,7 +252,7 @@ impl Debug for ReceiveRequest { mod tests { use crate::ff::Fp31; use crate::helpers::Role; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::protocol::{QueryId, RecordId}; use crate::test_fixture::{make_contexts, make_world_with_config, TestWorldConfig}; diff --git a/src/protocol/attribution/accumulate_credit.rs b/src/protocol/attribution/accumulate_credit.rs index da3e4d788..cc2b930f0 100644 --- a/src/protocol/attribution/accumulate_credit.rs +++ b/src/protocol/attribution/accumulate_credit.rs @@ -1,12 +1,12 @@ use super::{AccumulateCreditInputRow, AccumulateCreditOutputRow, AttributionInputRow, IterStep}; -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::protocol::mul::SecureMul; use crate::{ error::Error, ff::Field, protocol::{ batch::{Batch, RecordIndex}, - context::ProtocolContext, + context::Context, RecordId, }, secret_sharing::Replicated, @@ -55,7 +55,7 @@ impl<'a, F: Field> AccumulateCredit<'a, F> { #[allow(dead_code)] pub async fn execute( &self, - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, ) -> Result>, Error> { #[allow(clippy::cast_possible_truncation)] let num_rows = self.input.len() as RecordIndex; @@ -161,7 +161,7 @@ impl<'a, F: Field> AccumulateCredit<'a, F> { } async fn get_accumulated_credit( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, current: AccumulateCreditInputRow, successor: AccumulateCreditInputRow, diff --git a/src/protocol/boolean/bitwise_lt.rs b/src/protocol/boolean/bitwise_lt.rs index a1233589b..f76f724d5 100644 --- a/src/protocol/boolean/bitwise_lt.rs +++ b/src/protocol/boolean/bitwise_lt.rs @@ -3,8 +3,8 @@ use super::xor::xor; use super::BitOpStep; use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::SemiHonestProtocolContext; -use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; +use crate::protocol::context::SemiHonestContext; +use crate::protocol::{context::Context, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; @@ -40,7 +40,7 @@ impl BitwiseLessThan { async fn step1( a: &[Replicated], b: &[Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let xor = zip(a, b).enumerate().map(|(i, (a_bit, b_bit))| { @@ -68,7 +68,7 @@ impl BitwiseLessThan { /// ``` async fn step2( e: &mut [Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { e.reverse(); @@ -108,7 +108,7 @@ impl BitwiseLessThan { async fn step5( g: &[Replicated], b: &[Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let mul = zip(repeat(ctx), zip(g, b)) @@ -131,7 +131,7 @@ impl BitwiseLessThan { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &[Replicated], b: &[Replicated], @@ -168,7 +168,7 @@ impl AsRef for Step { #[cfg(test)] mod tests { use super::BitwiseLessThan; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::{ error::Error, ff::{Field, Fp31, Fp32BitPrime, Int}, diff --git a/src/protocol/boolean/bitwise_sum.rs b/src/protocol/boolean/bitwise_sum.rs index 0745a07d5..e411d5a82 100644 --- a/src/protocol/boolean/bitwise_sum.rs +++ b/src/protocol/boolean/bitwise_sum.rs @@ -1,8 +1,8 @@ use super::carries::Carries; use crate::error::BoxError; use crate::ff::Field; -use crate::protocol::context::SemiHonestProtocolContext; -use crate::protocol::{context::ProtocolContext, RecordId}; +use crate::protocol::context::SemiHonestContext; +use crate::protocol::{context::Context, RecordId}; use crate::secret_sharing::Replicated; /// This is an implementation of Bitwise Sum on bitwise-shared numbers. @@ -32,7 +32,7 @@ impl BitwiseSum { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &[Replicated], b: &[Replicated], @@ -83,7 +83,7 @@ impl AsRef for Step { #[cfg(test)] mod tests { use super::BitwiseSum; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::{ error::BoxError, ff::{Field, Fp31, Fp32BitPrime, Int}, diff --git a/src/protocol/boolean/carries.rs b/src/protocol/boolean/carries.rs index e64bec60f..e35621880 100644 --- a/src/protocol/boolean/carries.rs +++ b/src/protocol/boolean/carries.rs @@ -1,8 +1,8 @@ use super::BitOpStep; use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::SemiHonestProtocolContext; -use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; +use crate::protocol::context::SemiHonestContext; +use crate::protocol::{context::Context, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; @@ -39,7 +39,7 @@ impl Carries { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &[Replicated], b: &[Replicated], @@ -67,7 +67,7 @@ impl Carries { async fn step1( a: &[Replicated], b: &[Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let mul = zip(repeat(ctx), zip(a, b)) @@ -124,7 +124,7 @@ impl Carries { /// computes `([f_0],...,[f_l]) ← PRE○([e_0],...,[e_l])`. async fn step3( e: &[CarryPropagationShares], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let l = e.len(); @@ -150,7 +150,7 @@ impl Carries { #[allow(clippy::many_single_char_names)] async fn fan_in_carry_propagation( e: &[CarryPropagationShares], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result, Error> { let l = e.len(); @@ -232,7 +232,7 @@ mod tests { use super::Carries; use crate::error::Error; use crate::ff::{Field, Fp31, Fp32BitPrime, Int}; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::protocol::{QueryId, RecordId}; use crate::secret_sharing::Replicated; use crate::test_fixture::{ diff --git a/src/protocol/boolean/or.rs b/src/protocol/boolean/or.rs index dec108d58..d421ac2e7 100644 --- a/src/protocol/boolean/or.rs +++ b/src/protocol/boolean/or.rs @@ -1,13 +1,13 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::SemiHonestProtocolContext; -use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; +use crate::protocol::context::SemiHonestContext; +use crate::protocol::{context::Context, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; /// Secure XOR protocol with two inputs, `a, b ∈ {0,1} ⊆ F_p`. /// It computes `[a] + [b] - 2[ab]` pub async fn or( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -20,7 +20,7 @@ pub async fn or( #[cfg(test)] mod tests { use super::or; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::{ error::Error, ff::{Field, Fp31}, diff --git a/src/protocol/boolean/prefix_or.rs b/src/protocol/boolean/prefix_or.rs index 36114aef8..13c9655de 100644 --- a/src/protocol/boolean/prefix_or.rs +++ b/src/protocol/boolean/prefix_or.rs @@ -1,8 +1,8 @@ use super::{or::or, BitOpStep}; use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::SemiHonestProtocolContext; -use crate::protocol::{context::ProtocolContext, mul::SecureMul, RecordId}; +use crate::protocol::context::SemiHonestContext; +use crate::protocol::{context::Context, mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; use futures::future::try_join_all; use std::iter::{repeat, zip}; @@ -28,7 +28,7 @@ impl PrefixOr { async fn block_or( a: &[Replicated], k: usize, - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result, Error> { #[allow(clippy::cast_possible_truncation)] @@ -54,7 +54,7 @@ impl PrefixOr { async fn step1( a: &[Replicated], lambda: usize, - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let mut futures = Vec::with_capacity(lambda); @@ -75,7 +75,7 @@ impl PrefixOr { /// ``` async fn step2( x: &[Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = x.len(); @@ -117,7 +117,7 @@ impl PrefixOr { async fn step5( f: &[Replicated], a: &[Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = f.len(); @@ -161,7 +161,7 @@ impl PrefixOr { /// ``` async fn step7( c: &[Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = c.len(); @@ -187,7 +187,7 @@ impl PrefixOr { async fn step8( f: &[Replicated], b: &[Replicated], - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, ) -> Result>, Error> { let lambda = f.len(); @@ -228,7 +228,7 @@ impl PrefixOr { #[allow(dead_code)] #[allow(clippy::many_single_char_names)] pub async fn execute( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, input: &[Replicated], ) -> Result>, Error> { @@ -304,7 +304,7 @@ impl AsRef for Step { #[cfg(test)] mod tests { use super::PrefixOr; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::{ error::Error, ff::{Field, Fp2, Fp31}, diff --git a/src/protocol/boolean/xor.rs b/src/protocol/boolean/xor.rs index bb8b64f59..534175360 100644 --- a/src/protocol/boolean/xor.rs +++ b/src/protocol/boolean/xor.rs @@ -1,13 +1,13 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::protocol::{mul::SecureMul, RecordId}; use crate::secret_sharing::Replicated; /// Secure XOR protocol with two inputs, `a, b ∈ {0,1} ⊆ F_p`. /// It computes `[a] + [b] - 2[ab]` pub async fn xor( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -19,7 +19,7 @@ pub async fn xor( #[cfg(test)] mod tests { use super::xor; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::{ error::Error, ff::{Field, Fp31}, diff --git a/src/protocol/check_zero.rs b/src/protocol/check_zero.rs index cad3cb018..b0f9710d2 100644 --- a/src/protocol/check_zero.rs +++ b/src/protocol/check_zero.rs @@ -1,10 +1,10 @@ -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::protocol::mul::SecureMul; use crate::protocol::reveal::Reveal; use crate::{ error::Error, ff::Field, - protocol::{context::ProtocolContext, RecordId}, + protocol::{context::Context, RecordId}, secret_sharing::Replicated, }; use serde::{Deserialize, Serialize}; @@ -63,7 +63,7 @@ impl AsRef for Step { /// back via the error response #[allow(dead_code)] pub async fn check_zero( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, v: &Replicated, ) -> Result { @@ -86,7 +86,7 @@ pub async fn check_zero( pub mod tests { use crate::error::Error; use crate::ff::{Field, Fp31}; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::protocol::{check_zero::check_zero, QueryId, RecordId}; use crate::test_fixture::{make_contexts, make_world, share, TestWorld}; diff --git a/src/protocol/context/malicious.rs b/src/protocol/context/malicious.rs index ade6fb725..d7e381679 100644 --- a/src/protocol/context/malicious.rs +++ b/src/protocol/context/malicious.rs @@ -1,7 +1,7 @@ use crate::ff::Field; use crate::helpers::messaging::{Gateway, Mesh}; use crate::helpers::Role; -use crate::protocol::context::{ContextInner, ProtocolContext, SemiHonestProtocolContext}; +use crate::protocol::context::{Context, ContextInner, SemiHonestContext}; use crate::protocol::malicious::SecurityValidatorAccumulator; use crate::protocol::prss::{ Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, @@ -13,13 +13,13 @@ use std::sync::Arc; /// Represents protocol context in malicious setting, i.e. secure against one active adversary /// in 3 party MPC ring. #[derive(Clone, Debug)] -pub struct MaliciousProtocolContext<'a, F: Field> { +pub struct MaliciousContext<'a, F: Field> { inner: ContextInner<'a>, accumulator: SecurityValidatorAccumulator, r_share: Replicated, } -impl<'a, F: Field> MaliciousProtocolContext<'a, F> { +impl<'a, F: Field> MaliciousContext<'a, F> { pub fn new( role: Role, participant: &'a PrssEndpoint, @@ -58,12 +58,12 @@ impl<'a, F: Field> MaliciousProtocolContext<'a, F> { /// The context received will be an exact copy of malicious, so it will be tied up to the same step /// and prss. #[must_use] - pub fn to_semi_honest(self) -> SemiHonestProtocolContext<'a, F> { - SemiHonestProtocolContext::from_inner(self.inner) + pub fn to_semi_honest(self) -> SemiHonestContext<'a, F> { + SemiHonestContext::from_inner(self.inner) } } -impl<'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { +impl<'a, F: Field> Context for MaliciousContext<'a, F> { type Share = MaliciousReplicated; fn role(&self) -> Role { @@ -95,7 +95,7 @@ impl<'a, F: Field> ProtocolContext for MaliciousProtocolContext<'a, F> { self.inner.gateway.mesh(self.step()) } - fn share_of_one(&self) -> >::Share { + fn share_of_one(&self) -> >::Share { MaliciousReplicated::one(self.role(), self.r_share.clone()) } } diff --git a/src/protocol/context/mod.rs b/src/protocol/context/mod.rs index 9d0bb2d12..577ef546e 100644 --- a/src/protocol/context/mod.rs +++ b/src/protocol/context/mod.rs @@ -13,15 +13,15 @@ use std::sync::Arc; mod malicious; mod semi_honest; -pub use malicious::MaliciousProtocolContext; -pub use semi_honest::SemiHonestProtocolContext; +pub use malicious::MaliciousContext; +pub use semi_honest::SemiHonestContext; /// Context used by each helper to perform secure computation. Provides access to shared randomness /// generator and communication channel. -pub trait ProtocolContext: +pub trait Context: Clone - + SecureMul>::Share> - + Reveal>::Share> + + SecureMul>::Share> + + Reveal>::Share> { /// Secret sharing type this context supports. type Share: SecretSharing; @@ -61,7 +61,7 @@ pub trait ProtocolContext: fn mesh(&self) -> Mesh<'_, '_>; /// Generates a new share of one - fn share_of_one(&self) -> >::Share; + fn share_of_one(&self) -> >::Share; } /// Contains things that are applicable to any implementation of protocol context as see it today diff --git a/src/protocol/context/semi_honest.rs b/src/protocol/context/semi_honest.rs index 95aa975a0..563734a49 100644 --- a/src/protocol/context/semi_honest.rs +++ b/src/protocol/context/semi_honest.rs @@ -1,7 +1,7 @@ use crate::ff::Field; use crate::helpers::messaging::{Gateway, Mesh}; use crate::helpers::Role; -use crate::protocol::context::{ContextInner, MaliciousProtocolContext, ProtocolContext}; +use crate::protocol::context::{Context, ContextInner, MaliciousContext}; use crate::protocol::malicious::SecurityValidatorAccumulator; use crate::protocol::prss::{ Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, @@ -14,12 +14,12 @@ use std::sync::Arc; /// Context for protocol executions suitable for semi-honest security model, i.e. secure against /// honest-but-curious adversary parties. #[derive(Clone, Debug)] -pub struct SemiHonestProtocolContext<'a, F: Field> { +pub struct SemiHonestContext<'a, F: Field> { inner: ContextInner<'a>, _marker: PhantomData, } -impl<'a, F: Field> SemiHonestProtocolContext<'a, F> { +impl<'a, F: Field> SemiHonestContext<'a, F> { pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { Self { inner: ContextInner::new(role, participant, gateway), @@ -39,12 +39,12 @@ impl<'a, F: Field> SemiHonestProtocolContext<'a, F> { self, accumulator: SecurityValidatorAccumulator, r_share: Replicated, - ) -> MaliciousProtocolContext<'a, F> { - MaliciousProtocolContext::from_inner(self.inner, accumulator, r_share) + ) -> MaliciousContext<'a, F> { + MaliciousContext::from_inner(self.inner, accumulator, r_share) } } -impl<'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { +impl<'a, F: Field> Context for SemiHonestContext<'a, F> { type Share = Replicated; fn role(&self) -> Role { @@ -74,7 +74,7 @@ impl<'a, F: Field> ProtocolContext for SemiHonestProtocolContext<'a, F> { self.inner.gateway.mesh(self.step()) } - fn share_of_one(&self) -> >::Share { + fn share_of_one(&self) -> >::Share { Replicated::one(self.role()) } } diff --git a/src/protocol/malicious.rs b/src/protocol/malicious.rs index 3e6506f58..be2ca662d 100644 --- a/src/protocol/malicious.rs +++ b/src/protocol/malicious.rs @@ -1,11 +1,11 @@ -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::protocol::reveal::Reveal; use crate::{ error::Error, ff::Field, helpers::Direction, protocol::{ - check_zero::check_zero, context::ProtocolContext, prss::IndexedSharedRandomness, RecordId, + check_zero::check_zero, context::Context, prss::IndexedSharedRandomness, RecordId, RECORD_0, RECORD_1, RECORD_2, }, secret_sharing::{MaliciousReplicated, Replicated}, @@ -123,7 +123,7 @@ pub struct SecurityValidator { impl SecurityValidator { #[must_use] #[allow(clippy::needless_pass_by_value)] - pub fn new(ctx: SemiHonestProtocolContext<'_, F>) -> SecurityValidator { + pub fn new(ctx: SemiHonestContext<'_, F>) -> SecurityValidator { let prss = ctx.prss(); let r_share = prss.generate_replicated(RECORD_0); @@ -158,7 +158,7 @@ impl SecurityValidator { /// ## Panics /// Will panic if the mutex is poisoned #[allow(clippy::await_holding_lock)] - pub async fn validate(self, ctx: SemiHonestProtocolContext<'_, F>) -> Result<(), Error> { + pub async fn validate(self, ctx: SemiHonestContext<'_, F>) -> Result<(), Error> { // send our `u_i+1` value to the helper on the right let channel = ctx.mesh(); let helper_right = ctx.role().peer(Direction::Right); @@ -204,7 +204,7 @@ pub mod tests { use crate::error::Error; use crate::ff::Fp31; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::protocol::mul::SecureMul; use crate::protocol::{ malicious::{SecurityValidator, Step}, diff --git a/src/protocol/modulus_conversion/convert_shares.rs b/src/protocol/modulus_conversion/convert_shares.rs index 026b929ba..ff6695560 100644 --- a/src/protocol/modulus_conversion/convert_shares.rs +++ b/src/protocol/modulus_conversion/convert_shares.rs @@ -3,11 +3,11 @@ use crate::{ error::Error, ff::{BinaryField, Field, Fp2}, helpers::Role, - protocol::{context::ProtocolContext, RecordId}, + protocol::{context::Context, RecordId}, secret_sharing::Replicated, }; -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use futures::future::try_join_all; use std::iter::{repeat, zip}; @@ -108,7 +108,7 @@ impl ConvertShares { /// And helper 3 has shares: /// a: (0, x1) and b: (0, 0) async fn xor_specialized_1( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -134,7 +134,7 @@ impl ConvertShares { /// And helper 3 has shares: /// (x3, 0) async fn xor_specialized_2( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -146,7 +146,7 @@ impl ConvertShares { pub async fn execute_one_bit( &self, - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, bit_index: u8, ) -> Result, Error> { @@ -169,7 +169,7 @@ impl ConvertShares { /// For a given vector of input shares, this returns a vector of modulus converted replicated shares of /// `bit_index` of each input. pub async fn convert_shares_for_a_bit( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, input: &[(u64, u64)], num_bits: u8, bit_index: u8, diff --git a/src/protocol/modulus_conversion/specialized_mul.rs b/src/protocol/modulus_conversion/specialized_mul.rs index 6290db20c..53d0e25fc 100644 --- a/src/protocol/modulus_conversion/specialized_mul.rs +++ b/src/protocol/modulus_conversion/specialized_mul.rs @@ -1,9 +1,9 @@ -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::{ error::Error, ff::Field, helpers::{Direction, Role}, - protocol::{context::ProtocolContext, RecordId}, + protocol::{context::Context, RecordId}, secret_sharing::Replicated, }; @@ -31,7 +31,7 @@ use crate::{ /// back via the error response #[allow(dead_code)] pub async fn multiply_two_shares_mostly_zeroes( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, @@ -115,7 +115,7 @@ pub async fn multiply_two_shares_mostly_zeroes( /// back via the error response #[allow(dead_code)] pub async fn multiply_one_share_mostly_zeroes( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, record_id: RecordId, a: &Replicated, b: &Replicated, diff --git a/src/protocol/mul/malicious.rs b/src/protocol/mul/malicious.rs index 48325d2dd..2c5d2f3a6 100644 --- a/src/protocol/mul/malicious.rs +++ b/src/protocol/mul/malicious.rs @@ -1,10 +1,8 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::MaliciousProtocolContext; +use crate::protocol::context::MaliciousContext; use crate::protocol::mul::SemiHonestMul; -use crate::protocol::{ - context::ProtocolContext, malicious::SecurityValidatorAccumulator, RecordId, -}; +use crate::protocol::{context::Context, malicious::SecurityValidatorAccumulator, RecordId}; use crate::secret_sharing::MaliciousReplicated; use futures::future::try_join; use std::fmt::Debug; @@ -48,7 +46,7 @@ impl AsRef for Step { /// `SecureMult` is an implementation of the IKHC multiplication protocol, which has this property. /// pub struct SecureMul<'a, F: Field> { - ctx: MaliciousProtocolContext<'a, F>, + ctx: MaliciousContext<'a, F>, record_id: RecordId, accumulator: SecurityValidatorAccumulator, } @@ -56,7 +54,7 @@ pub struct SecureMul<'a, F: Field> { impl<'a, F: Field> SecureMul<'a, F> { #[must_use] pub fn new( - ctx: MaliciousProtocolContext<'a, F>, + ctx: MaliciousContext<'a, F>, record_id: RecordId, accumulator: SecurityValidatorAccumulator, ) -> Self { diff --git a/src/protocol/mul/mod.rs b/src/protocol/mul/mod.rs index f169bb02a..6c59a2b75 100644 --- a/src/protocol/mul/mod.rs +++ b/src/protocol/mul/mod.rs @@ -1,6 +1,6 @@ use crate::error::Error; use crate::ff::Field; -use crate::protocol::context::{MaliciousProtocolContext, SemiHonestProtocolContext}; +use crate::protocol::context::{MaliciousContext, SemiHonestContext}; use crate::protocol::RecordId; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; use async_trait::async_trait; @@ -27,7 +27,7 @@ pub use {malicious::SecureMul as MaliciouslySecureMul, semi_honest::SecureMul as /// Implement secure multiplication for semi-honest contexts with replicated secret sharing. #[async_trait] -impl SecureMul for SemiHonestProtocolContext<'_, F> { +impl SecureMul for SemiHonestContext<'_, F> { type Share = Replicated; async fn multiply( @@ -42,7 +42,7 @@ impl SecureMul for SemiHonestProtocolContext<'_, F> { /// Implement secure multiplication for malicious contexts with replicated secret sharing. #[async_trait] -impl SecureMul for MaliciousProtocolContext<'_, F> { +impl SecureMul for MaliciousContext<'_, F> { type Share = MaliciousReplicated; async fn multiply( diff --git a/src/protocol/mul/semi_honest.rs b/src/protocol/mul/semi_honest.rs index 900774f65..c983f97eb 100644 --- a/src/protocol/mul/semi_honest.rs +++ b/src/protocol/mul/semi_honest.rs @@ -1,8 +1,8 @@ use crate::error::Error; use crate::ff::Field; use crate::helpers::Direction; -use crate::protocol::context::SemiHonestProtocolContext; -use crate::protocol::{context::ProtocolContext, RecordId}; +use crate::protocol::context::SemiHonestContext; +use crate::protocol::{context::Context, RecordId}; use crate::secret_sharing::Replicated; use std::fmt::Debug; @@ -11,13 +11,13 @@ use std::fmt::Debug; /// K. Chida, K. Hamada, D. Ikarashi, R. Kikuchi, and B. Pinkas. High-throughput secure AES computation. In WAHC@CCS 2018, pp. 13–24, 2018 #[derive(Debug)] pub struct SecureMul<'a, F: Field> { - ctx: SemiHonestProtocolContext<'a, F>, + ctx: SemiHonestContext<'a, F>, record_id: RecordId, } impl<'a, F: Field> SecureMul<'a, F> { #[must_use] - pub fn new(ctx: SemiHonestProtocolContext<'a, F>, record_id: RecordId) -> Self { + pub fn new(ctx: SemiHonestContext<'a, F>, record_id: RecordId) -> Self { Self { ctx, record_id } } @@ -68,7 +68,7 @@ pub mod tests { use crate::protocol::mul::SecureMul; use crate::protocol::{QueryId, RecordId}; - use crate::protocol::context::SemiHonestProtocolContext; + use crate::protocol::context::SemiHonestContext; use crate::test_fixture::{ make_contexts, make_world, share, validate_and_reconstruct, TestWorld, }; @@ -147,7 +147,7 @@ pub mod tests { } async fn multiply_sync( - context: [SemiHonestProtocolContext<'_, F>; 3], + context: [SemiHonestContext<'_, F>; 3], a: u8, b: u8, rng: &mut R, diff --git a/src/protocol/reveal/mod.rs b/src/protocol/reveal/mod.rs index 77a77a6e5..0889794b8 100644 --- a/src/protocol/reveal/mod.rs +++ b/src/protocol/reveal/mod.rs @@ -1,9 +1,7 @@ use std::iter::{repeat, zip}; use crate::ff::Field; -use crate::protocol::context::{ - MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext, -}; +use crate::protocol::context::{Context, MaliciousContext, SemiHonestContext}; use crate::secret_sharing::{MaliciousReplicated, Replicated, SecretSharing}; use crate::{ error::{BoxError, Error}, @@ -40,7 +38,7 @@ pub trait Reveal { /// i.e. their own shares and received share. #[async_trait] #[embed_doc_image("reveal", "images/reveal.png")] -impl Reveal for SemiHonestProtocolContext<'_, F> { +impl Reveal for SemiHonestContext<'_, F> { type Share = Replicated; async fn reveal(self, record_id: RecordId, input: &Self::Share) -> Result { @@ -65,7 +63,7 @@ impl Reveal for SemiHonestProtocolContext<'_, F> { /// to both helpers (right and left) and upon receiving 2 shares from peers it validates that they /// indeed match. #[async_trait] -impl Reveal for MaliciousProtocolContext<'_, F> { +impl Reveal for MaliciousContext<'_, F> { type Share = MaliciousReplicated; async fn reveal(self, record_id: RecordId, input: &Self::Share) -> Result { @@ -97,7 +95,7 @@ impl Reveal for MaliciousProtocolContext<'_, F> { /// This executes `reveal` protocol on each row of the vector and then constructs a `Permutation` object /// from the revealed rows. pub async fn reveal_permutation( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, permutation: &[Replicated], ) -> Result, BoxError> { let revealed_permutation = try_join_all(zip(repeat(ctx), permutation).enumerate().map( @@ -120,7 +118,7 @@ mod tests { use proptest::prelude::Rng; use tokio::try_join; - use crate::protocol::context::MaliciousProtocolContext; + use crate::protocol::context::MaliciousContext; use crate::test_fixture::make_malicious_contexts; use crate::{ error::BoxError, @@ -128,7 +126,7 @@ mod tests { ff::{Field, Fp31}, helpers::Direction, protocol::reveal::Reveal, - protocol::{context::ProtocolContext, QueryId, RecordId}, + protocol::{context::Context, QueryId, RecordId}, secret_sharing::MaliciousReplicated, test_fixture::{ make_contexts, make_world, share, share_malicious, validate_and_reconstruct, TestWorld, @@ -218,7 +216,7 @@ mod tests { } pub async fn reveal_with_additive_attack( - ctx: MaliciousProtocolContext<'_, F>, + ctx: MaliciousContext<'_, F>, record_id: RecordId, input: &MaliciousReplicated, additive_error: F, diff --git a/src/protocol/sort/bit_permutation.rs b/src/protocol/sort/bit_permutation.rs index b10d6b304..5c2f4348d 100644 --- a/src/protocol/sort/bit_permutation.rs +++ b/src/protocol/sort/bit_permutation.rs @@ -3,7 +3,7 @@ use std::iter::{repeat, zip}; use crate::{ error::BoxError, ff::Field, - protocol::{context::ProtocolContext, RecordId}, + protocol::{context::Context, RecordId}, secret_sharing::SecretSharing, }; @@ -32,12 +32,7 @@ use futures::future::try_join_all; /// /// ## Errors /// It will propagate errors from multiplication protocol. -pub async fn bit_permutation< - 'a, - F: Field, - S: SecretSharing, - C: ProtocolContext, ->( +pub async fn bit_permutation<'a, F: Field, S: SecretSharing, C: Context>( ctx: C, input: &[S], ) -> Result, BoxError> { diff --git a/src/protocol/sort/compose.rs b/src/protocol/sort/compose.rs index 87fa7a63f..754401b8e 100644 --- a/src/protocol/sort/compose.rs +++ b/src/protocol/sort/compose.rs @@ -1,8 +1,8 @@ -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::{ error::BoxError, ff::Field, - protocol::{context::ProtocolContext, reveal::reveal_permutation}, + protocol::{context::Context, reveal::reveal_permutation}, secret_sharing::Replicated, }; use embed_doc_image::embed_doc_image; @@ -32,7 +32,7 @@ use super::{ /// 4. Revealed permutation is applied locally on another permutation shares (rho) /// 5. Unshuffle the permutation with the same random permutations used in step 2, to undo the effect of the shuffling pub async fn compose( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, sigma: Vec>, mut rho: Vec>, ) -> Result>, BoxError> { diff --git a/src/protocol/sort/generate_sort_permutation.rs b/src/protocol/sort/generate_sort_permutation.rs index bdd658cba..b0449059a 100644 --- a/src/protocol/sort/generate_sort_permutation.rs +++ b/src/protocol/sort/generate_sort_permutation.rs @@ -2,7 +2,7 @@ use crate::{ error::BoxError, ff::Field, protocol::{ - context::ProtocolContext, + context::Context, modulus_conversion::convert_shares::convert_shares_for_a_bit, sort::bit_permutation::bit_permutation, sort::SortStep::{ApplyInv, BitPermutationStep, ComposeStep, ModulusConversion}, @@ -12,7 +12,7 @@ use crate::{ }; use super::{compose::compose, secureapplyinv::secureapplyinv}; -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use embed_doc_image::embed_doc_image; /// This is an implementation of `GenPerm` (Algorithm 6) described in: @@ -35,7 +35,7 @@ use embed_doc_image::embed_doc_image; /// 4. Compute ith composition by composing i-1th composition on ith permutation /// In the end, n-1th composition is returned. This is the permutation which sorts the inputs pub async fn generate_sort_permutation( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, input: &[(u64, u64)], num_bits: u8, ) -> Result>, BoxError> { diff --git a/src/protocol/sort/reshare.rs b/src/protocol/sort/reshare.rs index accabeae9..d40491ecf 100644 --- a/src/protocol/sort/reshare.rs +++ b/src/protocol/sort/reshare.rs @@ -1,9 +1,9 @@ use crate::ff::Field; -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::{ error::BoxError, helpers::{Direction, Role}, - protocol::{context::ProtocolContext, RecordId}, + protocol::{context::Context, RecordId}, secret_sharing::Replicated, }; use embed_doc_image::embed_doc_image; @@ -37,7 +37,7 @@ impl Reshare { /// `to_helper.right` = (`rand_right`, part1 + part2) = (r0, part1 + part2) pub async fn execute( self, - ctx: &SemiHonestProtocolContext<'_, F>, + ctx: &SemiHonestContext<'_, F>, record_id: RecordId, to_helper: Role, ) -> Result, BoxError> { diff --git a/src/protocol/sort/secureapplyinv.rs b/src/protocol/sort/secureapplyinv.rs index bbdf8f7d8..d3103f012 100644 --- a/src/protocol/sort/secureapplyinv.rs +++ b/src/protocol/sort/secureapplyinv.rs @@ -2,7 +2,7 @@ use crate::{ error::BoxError, ff::Field, protocol::{ - context::ProtocolContext, + context::Context, reveal::reveal_permutation, sort::ApplyInvStep::{RevealPermutation, ShuffleInputs, ShufflePermutation}, }, @@ -14,7 +14,7 @@ use super::{ apply::apply_inv, shuffle::{get_two_of_three_random_permutations, shuffle_shares}, }; -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use futures::future::try_join; /// This is an implementation of ApplyInv (Algorithm 4) found in the paper: @@ -38,7 +38,7 @@ use futures::future::try_join; /// 4. The permutation is revealed /// 5. All helpers call `apply` to apply the permutation locally. pub async fn secureapplyinv( - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, input: Vec>, sort_permutation: Vec>, ) -> Result>, BoxError> { diff --git a/src/protocol/sort/shuffle.rs b/src/protocol/sort/shuffle.rs index b1976e6a5..5be99f487 100644 --- a/src/protocol/sort/shuffle.rs +++ b/src/protocol/sort/shuffle.rs @@ -4,12 +4,12 @@ use rand::seq::SliceRandom; use rand::SeedableRng; use rand_chacha::ChaCha8Rng; -use crate::protocol::context::SemiHonestProtocolContext; +use crate::protocol::context::SemiHonestContext; use crate::{ error::BoxError, ff::Field, helpers::{Direction, Role}, - protocol::{context::ProtocolContext, prss::IndexedSharedRandomness, RecordId, Substep}, + protocol::{context::Context, prss::IndexedSharedRandomness, RecordId, Substep}, secret_sharing::Replicated, }; @@ -89,7 +89,7 @@ fn shuffle_for_helper(which_step: ShuffleStep) -> Role { #[allow(clippy::cast_possible_truncation)] async fn reshare_all_shares( input: Vec>, - ctx: &SemiHonestProtocolContext<'_, F>, + ctx: &SemiHonestContext<'_, F>, to_helper: Role, ) -> Result>, BoxError> { let reshares = input @@ -113,7 +113,7 @@ async fn shuffle_or_unshuffle_once( mut input: Vec>, random_permutations: (&[u32], &[u32]), shuffle_or_unshuffle: ShuffleOrUnshuffle, - ctx: &SemiHonestProtocolContext<'_, F>, + ctx: &SemiHonestContext<'_, F>, which_step: ShuffleStep, ) -> Result>, BoxError> { let to_helper = shuffle_for_helper(which_step); @@ -145,7 +145,7 @@ async fn shuffle_or_unshuffle_once( pub async fn shuffle_shares( input: Vec>, random_permutations: (&[u32], &[u32]), - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, ) -> Result>, BoxError> { let input = shuffle_or_unshuffle_once( input, @@ -180,7 +180,7 @@ pub async fn shuffle_shares( pub async fn unshuffle_shares( input: Vec>, random_permutations: (&[u32], &[u32]), - ctx: SemiHonestProtocolContext<'_, F>, + ctx: SemiHonestContext<'_, F>, ) -> Result>, BoxError> { let input = shuffle_or_unshuffle_once( input, @@ -213,7 +213,7 @@ mod tests { use std::collections::HashSet; use std::iter::zip; - use crate::protocol::context::ProtocolContext; + use crate::protocol::context::Context; use crate::test_fixture::{logging, validate_list_of_shares}; use crate::{ ff::Fp31, diff --git a/src/test_fixture/circuit.rs b/src/test_fixture/circuit.rs index 69d8de6ef..b81e69688 100644 --- a/src/test_fixture/circuit.rs +++ b/src/test_fixture/circuit.rs @@ -1,5 +1,5 @@ use crate::ff::Field; -use crate::protocol::context::ProtocolContext; +use crate::protocol::context::Context; use crate::protocol::mul::SecureMul; use crate::protocol::{QueryId, RecordId}; use crate::secret_sharing::Replicated; diff --git a/src/test_fixture/mod.rs b/src/test_fixture/mod.rs index 6601e28ad..4039030e9 100644 --- a/src/test_fixture/mod.rs +++ b/src/test_fixture/mod.rs @@ -7,9 +7,7 @@ pub mod network; use crate::ff::{Field, Fp31}; use crate::helpers::Role; -use crate::protocol::context::{ - MaliciousProtocolContext, ProtocolContext, SemiHonestProtocolContext, -}; +use crate::protocol::context::{Context, MaliciousContext, SemiHonestContext}; use crate::protocol::malicious::SecurityValidator; use crate::protocol::prss::Endpoint as PrssEndpoint; use crate::protocol::Substep; @@ -33,31 +31,29 @@ pub use world::{ /// # Panics /// Panics if world has more or less than 3 gateways/participants #[must_use] -pub fn make_contexts(test_world: &TestWorld) -> [SemiHonestProtocolContext<'_, F>; 3] { +pub fn make_contexts(test_world: &TestWorld) -> [SemiHonestContext<'_, F>; 3] { test_world .gateways .iter() .zip(&test_world.participants) .zip(Role::all()) - .map(|((gateway, participant), role)| { - SemiHonestProtocolContext::new(*role, participant, gateway) - }) + .map(|((gateway, participant), role)| SemiHonestContext::new(*role, participant, gateway)) .collect::>() .try_into() .unwrap() } -pub struct MaliciousContext<'a, F: Field> { - pub ctx: MaliciousProtocolContext<'a, F>, +pub struct MaliciousContextWrapper<'a, F: Field> { + pub ctx: MaliciousContext<'a, F>, pub validator: SecurityValidator, } /// Creates malicious protocol contexts for 3 helpers. -pub fn make_malicious_contexts(test_world: &TestWorld) -> [MaliciousContext<'_, F>; 3] { +pub fn make_malicious_contexts(test_world: &TestWorld) -> [MaliciousContextWrapper<'_, F>; 3] { make_contexts(test_world).map(|ctx| { let v = SecurityValidator::new(ctx.narrow("MaliciousValidate")); let acc = v.accumulator(); - MaliciousContext { + MaliciousContextWrapper { ctx: ctx.upgrade_to_malicious(acc, v.r_share().clone()), validator: v, } @@ -70,7 +66,7 @@ pub fn make_malicious_contexts(test_world: &TestWorld) -> [MaliciousCo /// # Panics /// Never, but then Rust doesn't know that; this is only needed because we don't have `each_ref()`. #[must_use] -pub fn narrow_contexts, F: Field, S: SecretSharing>( +pub fn narrow_contexts, F: Field, S: SecretSharing>( contexts: &[C; 3], step: &impl Substep, ) -> [C; 3] { From e07835c95182a6c585d5df8487ea7f82ea31e7ec Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Mon, 21 Nov 2022 17:54:58 -0800 Subject: [PATCH 12/13] Fix formatting --- src/test_fixture/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test_fixture/mod.rs b/src/test_fixture/mod.rs index 4039030e9..cba159647 100644 --- a/src/test_fixture/mod.rs +++ b/src/test_fixture/mod.rs @@ -48,7 +48,9 @@ pub struct MaliciousContextWrapper<'a, F: Field> { } /// Creates malicious protocol contexts for 3 helpers. -pub fn make_malicious_contexts(test_world: &TestWorld) -> [MaliciousContextWrapper<'_, F>; 3] { +pub fn make_malicious_contexts( + test_world: &TestWorld, +) -> [MaliciousContextWrapper<'_, F>; 3] { make_contexts(test_world).map(|ctx| { let v = SecurityValidator::new(ctx.narrow("MaliciousValidate")); let acc = v.accumulator(); From f5a73d8c4957b7462f920416f01807d42c2105a5 Mon Sep 17 00:00:00 2001 From: Alex Koshelev Date: Mon, 21 Nov 2022 23:31:58 -0800 Subject: [PATCH 13/13] Specialize ContextInner for SemiHonest/Malicious impls --- src/protocol/context/malicious.rs | 84 ++++++++++++++++++----------- src/protocol/context/mod.rs | 37 +------------ src/protocol/context/semi_honest.rs | 39 +++++++++----- 3 files changed, 82 insertions(+), 78 deletions(-) diff --git a/src/protocol/context/malicious.rs b/src/protocol/context/malicious.rs index d7e381679..50d308278 100644 --- a/src/protocol/context/malicious.rs +++ b/src/protocol/context/malicious.rs @@ -1,53 +1,41 @@ use crate::ff::Field; use crate::helpers::messaging::{Gateway, Mesh}; use crate::helpers::Role; -use crate::protocol::context::{Context, ContextInner, SemiHonestContext}; +use crate::protocol::context::{semi_honest, Context, SemiHonestContext}; use crate::protocol::malicious::SecurityValidatorAccumulator; use crate::protocol::prss::{ Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, }; use crate::protocol::{Step, Substep}; use crate::secret_sharing::{MaliciousReplicated, Replicated}; +use std::borrow::Borrow; use std::sync::Arc; /// Represents protocol context in malicious setting, i.e. secure against one active adversary /// in 3 party MPC ring. #[derive(Clone, Debug)] pub struct MaliciousContext<'a, F: Field> { - inner: ContextInner<'a>, - accumulator: SecurityValidatorAccumulator, - r_share: Replicated, + /// TODO (alex): Arc is required here because of the `TestWorld` structure. Real world + /// may operate with raw references and be more efficient + inner: Arc>, + step: Step, } impl<'a, F: Field> MaliciousContext<'a, F> { - pub fn new( - role: Role, - participant: &'a PrssEndpoint, - gateway: &'a Gateway, + pub(super) fn new( + source: &SemiHonestContext<'a, F>, acc: SecurityValidatorAccumulator, r_share: Replicated, ) -> Self { Self { - inner: ContextInner::new(role, participant, gateway), - accumulator: acc, - r_share, - } - } - - pub(super) fn from_inner( - inner: ContextInner<'a>, - acc: SecurityValidatorAccumulator, - r_share: Replicated, - ) -> Self { - Self { - inner, - accumulator: acc, - r_share, + inner: ContextInner::new(&source.inner, acc, r_share), + step: source.step().clone(), } } + #[must_use] pub fn accumulator(&self) -> SecurityValidatorAccumulator { - self.accumulator.clone() + self.inner.accumulator.clone() } /// Sometimes it is required to reinterpret malicious context as semi-honest. Ideally @@ -59,7 +47,17 @@ impl<'a, F: Field> MaliciousContext<'a, F> { /// and prss. #[must_use] pub fn to_semi_honest(self) -> SemiHonestContext<'a, F> { - SemiHonestContext::from_inner(self.inner) + // TODO: it can be made more efficient by impersonating malicious context as semi-honest + // it does not work as of today because of https://github.com/rust-lang/rust/issues/20400 + // while it is possible to define a struct that wraps a reference to malicious context + // and implement `Context` trait for it, implementing SecureMul and Reveal for Context + // is not + // For the same reason, it is not possible to implement Context> + // for `MaliciousContext`. Deep clone is the only option + let mut ctx = SemiHonestContext::new(self.inner.role, self.inner.prss, self.inner.gateway); + ctx.step = self.step; + + ctx } } @@ -71,15 +69,13 @@ impl<'a, F: Field> Context for MaliciousContext<'a, F> { } fn step(&self) -> &Step { - &self.inner.step + &self.step } fn narrow(&self, step: &S) -> Self { Self { - inner: self.inner.narrow(step), - accumulator: self.accumulator.clone(), - // TODO (alex, mt) - is cloning ok here or we need to Cow it? - r_share: self.r_share.clone(), + inner: Arc::clone(&self.inner), + step: self.step.narrow(step), } } @@ -96,6 +92,32 @@ impl<'a, F: Field> Context for MaliciousContext<'a, F> { } fn share_of_one(&self) -> >::Share { - MaliciousReplicated::one(self.role(), self.r_share.clone()) + MaliciousReplicated::one(self.role(), self.inner.r_share.clone()) + } +} + +#[derive(Debug)] +struct ContextInner<'a, F: Field> { + role: Role, + prss: &'a PrssEndpoint, + gateway: &'a Gateway, + accumulator: SecurityValidatorAccumulator, + r_share: Replicated, +} + +impl<'a, F: Field> ContextInner<'a, F> { + fn new>>( + source: &B, + accumulator: SecurityValidatorAccumulator, + r_share: Replicated, + ) -> Arc { + let source = source.borrow(); + Arc::new(ContextInner { + role: source.role, + prss: source.prss, + gateway: source.gateway, + accumulator, + r_share, + }) } } diff --git a/src/protocol/context/mod.rs b/src/protocol/context/mod.rs index 577ef546e..5671eea06 100644 --- a/src/protocol/context/mod.rs +++ b/src/protocol/context/mod.rs @@ -1,10 +1,8 @@ use crate::ff::Field; -use crate::helpers::messaging::{Gateway, Mesh}; +use crate::helpers::messaging::Mesh; use crate::helpers::Role; use crate::protocol::mul::SecureMul; -use crate::protocol::prss::{ - Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, -}; +use crate::protocol::prss::{IndexedSharedRandomness, SequentialSharedRandomness}; use crate::protocol::reveal::Reveal; use crate::protocol::{Step, Substep}; use crate::secret_sharing::SecretSharing; @@ -63,34 +61,3 @@ pub trait Context: /// Generates a new share of one fn share_of_one(&self) -> >::Share; } - -/// Contains things that are applicable to any implementation of protocol context as see it today -/// Every context requires access to current step, PRSS and communication and that is what this -/// struct carries. -#[derive(Clone, Debug)] -struct ContextInner<'a> { - role: Role, - step: Step, - prss: &'a PrssEndpoint, - gateway: &'a Gateway, -} - -impl<'a> ContextInner<'a> { - fn new(role: Role, prss: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { - Self { - role, - step: Step::default(), - prss, - gateway, - } - } - - fn narrow(&self, step: &S) -> Self { - Self { - role: self.role, - step: self.step.narrow(step), - prss: self.prss, - gateway: self.gateway, - } - } -} diff --git a/src/protocol/context/semi_honest.rs b/src/protocol/context/semi_honest.rs index 563734a49..ebe13bcf1 100644 --- a/src/protocol/context/semi_honest.rs +++ b/src/protocol/context/semi_honest.rs @@ -1,7 +1,7 @@ use crate::ff::Field; use crate::helpers::messaging::{Gateway, Mesh}; use crate::helpers::Role; -use crate::protocol::context::{Context, ContextInner, MaliciousContext}; +use crate::protocol::context::{Context, MaliciousContext}; use crate::protocol::malicious::SecurityValidatorAccumulator; use crate::protocol::prss::{ Endpoint as PrssEndpoint, IndexedSharedRandomness, SequentialSharedRandomness, @@ -15,7 +15,10 @@ use std::sync::Arc; /// honest-but-curious adversary parties. #[derive(Clone, Debug)] pub struct SemiHonestContext<'a, F: Field> { - inner: ContextInner<'a>, + /// TODO (alex): Arc is required here because of the `TestWorld` structure. Real world + /// may operate with raw references and be more efficient + pub(super) inner: Arc>, + pub(super) step: Step, _marker: PhantomData, } @@ -23,13 +26,7 @@ impl<'a, F: Field> SemiHonestContext<'a, F> { pub fn new(role: Role, participant: &'a PrssEndpoint, gateway: &'a Gateway) -> Self { Self { inner: ContextInner::new(role, participant, gateway), - _marker: PhantomData::default(), - } - } - - pub(super) fn from_inner(inner: ContextInner<'a>) -> Self { - Self { - inner, + step: Step::default(), _marker: PhantomData::default(), } } @@ -40,7 +37,7 @@ impl<'a, F: Field> SemiHonestContext<'a, F> { accumulator: SecurityValidatorAccumulator, r_share: Replicated, ) -> MaliciousContext<'a, F> { - MaliciousContext::from_inner(self.inner, accumulator, r_share) + MaliciousContext::new(&self, accumulator, r_share) } } @@ -52,12 +49,13 @@ impl<'a, F: Field> Context for SemiHonestContext<'a, F> { } fn step(&self) -> &Step { - &self.inner.step + &self.step } fn narrow(&self, step: &S) -> Self { Self { - inner: self.inner.narrow(step), + inner: Arc::clone(&self.inner), + step: self.step.narrow(step), _marker: PhantomData::default(), } } @@ -78,3 +76,20 @@ impl<'a, F: Field> Context for SemiHonestContext<'a, F> { Replicated::one(self.role()) } } + +#[derive(Debug)] +pub(super) struct ContextInner<'a> { + pub role: Role, + pub prss: &'a PrssEndpoint, + pub gateway: &'a Gateway, +} + +impl<'a> ContextInner<'a> { + fn new(role: Role, prss: &'a PrssEndpoint, gateway: &'a Gateway) -> Arc { + Arc::new(Self { + role, + prss, + gateway, + }) + } +}