Skip to content

Commit

Permalink
offline-phase: structs: Implement OfflinePhase for LowGearPrep
Browse files Browse the repository at this point in the history
This implements the interface needed to be used in the online phase.
  • Loading branch information
joeykraut committed Apr 17, 2024
1 parent 520dec3 commit 9c4622e
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 1 deletion.
2 changes: 2 additions & 0 deletions mp-spdz-rs/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ mod ffi_inner {
}
pub use ffi_inner::*;
unsafe impl Send for FHE_Params {}
unsafe impl Sync for FHE_Params {}
unsafe impl Send for FHE_KeyPair {}
unsafe impl Sync for FHE_KeyPair {}
unsafe impl Send for FHE_PK {}
unsafe impl Sync for FHE_PK {}
unsafe impl Send for Ciphertext {}
Expand Down
2 changes: 1 addition & 1 deletion offline-phase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub(crate) mod test_helpers {
let mut rng = thread_rng();
let a = (0..n).map(|_| Scalar::<TestCurve>::random(&mut rng)).collect_vec();
let b = (0..n).map(|_| Scalar::<TestCurve>::random(&mut rng)).collect_vec();
let c = (0..n).map(|_| Scalar::<TestCurve>::random(&mut rng)).collect_vec();
let c = a.iter().zip(b.iter()).map(|(a, b)| a * b).collect_vec();

(a, b, c)
}
Expand Down
95 changes: 95 additions & 0 deletions offline-phase/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::ops::{Add, Mul, Sub};

use ark_ec::CurveGroup;
use ark_mpc::algebra::{Scalar, ScalarShare};
use ark_mpc::offline_prep::OfflinePhase;
use mp_spdz_rs::fhe::ciphertext::Ciphertext;
use mp_spdz_rs::fhe::keys::{BGVKeypair, BGVPublicKey};
use mp_spdz_rs::fhe::params::BGVParams;
Expand Down Expand Up @@ -92,6 +93,58 @@ impl<C: CurveGroup> LowGearPrep<C> {
}
}

impl<C: CurveGroup> OfflinePhase<C> for LowGearPrep<C> {
fn next_shared_bit(&mut self) -> ScalarShare<C> {
self.bits.split_off(1).into_inner()[0]
}

fn next_shared_bit_batch(&mut self, num_values: usize) -> Vec<ScalarShare<C>> {
assert!(self.bits.len() >= num_values, "shared bits exhausted");
self.bits.split_off(num_values).into_inner()
}

fn next_shared_value(&mut self) -> ScalarShare<C> {
self.shared_randomness.split_off(1).into_inner()[0]
}

fn next_shared_value_batch(&mut self, num_values: usize) -> Vec<ScalarShare<C>> {
assert!(self.shared_randomness.len() >= num_values, "shared random values exhausted");
self.shared_randomness.split_off(num_values).into_inner()
}

fn next_shared_inverse_pair(&mut self) -> (ScalarShare<C>, ScalarShare<C>) {
let (lhs, rhs) = self.next_shared_inverse_pair_batch(1);
(lhs[0], rhs[0])
}

fn next_shared_inverse_pair_batch(
&mut self,
num_pairs: usize,
) -> (Vec<ScalarShare<C>>, Vec<ScalarShare<C>>) {
assert!(self.inverse_pairs.0.len() >= num_pairs, "shared inverse pairs exhausted");
let lhs = self.inverse_pairs.0.split_off(num_pairs);
let rhs = self.inverse_pairs.1.split_off(num_pairs);
(lhs.into_inner(), rhs.into_inner())
}

fn next_triplet(&mut self) -> (ScalarShare<C>, ScalarShare<C>, ScalarShare<C>) {
let (a, b, c) = self.next_triplet_batch(1);
(a[0], b[0], c[0])
}

fn next_triplet_batch(
&mut self,
num_triplets: usize,
) -> (Vec<ScalarShare<C>>, Vec<ScalarShare<C>>, Vec<ScalarShare<C>>) {
assert!(self.triplets.0.len() >= num_triplets, "shared triplets exhausted");
let a = self.triplets.0.split_off(num_triplets);
let b = self.triplets.1.split_off(num_triplets);
let c = self.triplets.2.split_off(num_triplets);

(a.into_inner(), b.into_inner(), c.into_inner())
}
}

// ------------------------
// | Authenticated Shares |
// ------------------------
Expand Down Expand Up @@ -242,3 +295,45 @@ impl<C: CurveGroup> Mul<&[Scalar<C>]> for &ValueMacBatch<C> {
ValueMacBatch::new(self.inner.iter().zip(other.iter()).map(|(a, b)| a * *b).collect())
}
}

#[cfg(test)]
mod test {
use ark_mpc::{
algebra::Scalar, test_helpers::execute_mock_mpc_with_beaver_source, PARTY0, PARTY1,
};
use rand::thread_rng;

use crate::test_helpers::mock_lowgear_with_triples;

/// Tests the use of the `LowGear` type as an `OfflinePhase` implementation
#[tokio::test]
async fn test_lowgear_offline_phase() {
// Setup the mock offline phase
let (prep1, prep2) = mock_lowgear_with_triples(
100, // num_triples
|mut lowgear| async move { lowgear.get_offline_result().unwrap() },
)
.await;

// Run a mock mpc using the lowgear offline phase
let mut rng = thread_rng();
let a = Scalar::random(&mut rng);
let b = Scalar::random(&mut rng);
let expected = a * b;

let (res, _) = execute_mock_mpc_with_beaver_source(
|fabric| async move {
let a_shared = fabric.share_scalar(a, PARTY0);
let b_shared = fabric.share_scalar(b, PARTY1);

let c = a_shared * b_shared;
c.open().await
},
prep1,
prep2,
)
.await;

assert_eq!(res, expected);
}
}
1 change: 1 addition & 0 deletions online-phase/src/offline_prep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub trait OfflinePhase<C: CurveGroup>: Send + Sync {
(a_vals, b_vals, c_vals)
}
}

/// An implementation of a beaver value source that returns
/// beaver triples (0, 0, 0) for party 0 and (1, 1, 1) for party 1
#[cfg(any(feature = "test_helpers", test))]
Expand Down

0 comments on commit 9c4622e

Please sign in to comment.