Browse Source

add bool frontend

par-agg-key-shares
Janmajaya Mall 9 months ago
parent
commit
72d8cafa95
10 changed files with 257 additions and 97 deletions
  1. +3
    -54
      src/bool/evaluator.rs
  2. +2
    -2
      src/bool/keys.rs
  3. +179
    -1
      src/bool/mod.rs
  4. +60
    -5
      src/bool/mp_api.rs
  5. +1
    -1
      src/bool/ni_mp_api.rs
  6. +8
    -4
      src/bool/print_noise.rs
  7. +1
    -1
      src/lib.rs
  8. +1
    -26
      src/shortint/enc_dec.rs
  9. +1
    -2
      src/shortint/mod.rs
  10. +1
    -1
      src/shortint/ops.rs

+ 3
- 54
src/bool/evaluator.rs

@ -33,7 +33,7 @@ use crate::{
encode_x_pow_si_with_emebedding_factor, mod_exponent, puncture_p_rng, TryConvertFrom1,
WithLocal,
},
Encoder, Matrix, MatrixEntity, MatrixMut, RowEntity, RowMut,
BooleanGates, Encoder, Matrix, MatrixEntity, MatrixMut, RowEntity, RowMut,
};
use super::{
@ -171,57 +171,6 @@ impl NonInteractiveMultiPartyCrs {
}
}
pub(crate) trait BooleanGates {
type Ciphertext: RowEntity;
type Key;
fn and_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn nand_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn or_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn nor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn xor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn xnor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn not_inplace(&mut self, c: &mut Self::Ciphertext);
fn and(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn nand(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn or(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn nor(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn xor(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn xnor(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn not(&mut self, c: &Self::Ciphertext) -> Self::Ciphertext;
}
struct ScratchMemory<M>
where
M: Matrix,
@ -2324,7 +2273,7 @@ where
);
}
fn not_inplace(&mut self, c0: &mut M::R) {
fn not_inplace(&self, c0: &mut M::R) {
let modop = &self.pbs_info.rlwe_modop;
c0.as_mut().iter_mut().for_each(|v| *v = modop.neg(v));
}
@ -2395,7 +2344,7 @@ where
out
}
fn not(&mut self, c: &Self::Ciphertext) -> Self::Ciphertext {
fn not(&self, c: &Self::Ciphertext) -> Self::Ciphertext {
let mut out = c.clone();
self.not_inplace(&mut out);
out

+ 2
- 2
src/bool/keys.rs

@ -497,7 +497,7 @@ pub(super) mod impl_server_key_eval_domain {
use itertools::{izip, Itertools};
use crate::{
evaluator::InteractiveMultiPartyCrs,
bool::evaluator::InteractiveMultiPartyCrs,
ntt::{Ntt, NttInit},
pbs::PbsKey,
random::RandomFill,
@ -1268,7 +1268,7 @@ pub struct CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare
}
mod impl_common_ref_non_interactive_multi_party_server_share {
use crate::evaluator::multi_party_user_id_lwe_segment;
use crate::bool::evaluator::multi_party_user_id_lwe_segment;
use super::*;

+ 179
- 1
src/bool/mod.rs

@ -1,4 +1,4 @@
pub(crate) mod evaluator;
mod evaluator;
mod keys;
pub(crate) mod parameters;
@ -13,7 +13,185 @@ pub use ni_mp_api::*;
#[cfg(feature = "interactive_mp")]
pub use mp_api::*;
use crate::RowEntity;
pub type ClientKey = keys::ClientKey<[u8; 32], u64>;
pub type FheBool = impl_bool_frontend::FheBool<Vec<u64>>;
pub(crate) trait BooleanGates {
type Ciphertext: RowEntity;
type Key;
fn and_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn nand_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn or_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn nor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn xor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn xnor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
fn not_inplace(&self, c: &mut Self::Ciphertext);
fn and(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn nand(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn or(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn nor(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn xor(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn xnor(
&mut self,
c0: &Self::Ciphertext,
c1: &Self::Ciphertext,
key: &Self::Key,
) -> Self::Ciphertext;
fn not(&self, c: &Self::Ciphertext) -> Self::Ciphertext;
}
mod impl_bool_frontend {
use crate::MultiPartyDecryptor;
/// Fhe Bool ciphertext
#[derive(Clone)]
pub struct FheBool<C> {
pub(crate) data: C,
}
impl<C> FheBool<C> {
pub(crate) fn data(&self) -> &C {
&self.data
}
pub(crate) fn data_mut(&mut self) -> &mut C {
&mut self.data
}
}
impl<C, K> MultiPartyDecryptor<bool, FheBool<C>> for K
where
K: MultiPartyDecryptor<bool, C>,
{
type DecryptionShare = <K as MultiPartyDecryptor<bool, C>>::DecryptionShare;
fn aggregate_decryption_shares(
&self,
c: &FheBool<C>,
shares: &[Self::DecryptionShare],
) -> bool {
self.aggregate_decryption_shares(&c.data, shares)
}
fn gen_decryption_share(&self, c: &FheBool<C>) -> Self::DecryptionShare {
self.gen_decryption_share(&c.data)
}
}
mod ops {
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
use crate::{
utils::{Global, WithLocal},
BooleanGates,
};
use super::super::{BoolEvaluator, RuntimeServerKey};
type FheBool = super::super::FheBool;
impl BitAnd for &FheBool {
type Output = FheBool;
fn bitand(self, rhs: Self) -> Self::Output {
BoolEvaluator::with_local_mut(|e| {
let key = RuntimeServerKey::global();
FheBool {
data: e.and(self.data(), rhs.data(), key),
}
})
}
}
impl BitAndAssign for FheBool {
fn bitand_assign(&mut self, rhs: Self) {
BoolEvaluator::with_local_mut_mut(&mut |e| {
let key = RuntimeServerKey::global();
e.and_inplace(&mut self.data_mut(), rhs.data(), key);
});
}
}
impl BitOr for &FheBool {
type Output = FheBool;
fn bitor(self, rhs: Self) -> Self::Output {
BoolEvaluator::with_local_mut(|e| {
let key = RuntimeServerKey::global();
FheBool {
data: e.or(self.data(), rhs.data(), key),
}
})
}
}
impl BitOrAssign for FheBool {
fn bitor_assign(&mut self, rhs: Self) {
BoolEvaluator::with_local_mut_mut(&mut |e| {
let key = RuntimeServerKey::global();
e.or_inplace(&mut self.data_mut(), rhs.data(), key);
});
}
}
impl BitXor for &FheBool {
type Output = FheBool;
fn bitxor(self, rhs: Self) -> Self::Output {
BoolEvaluator::with_local_mut(|e| {
let key = RuntimeServerKey::global();
FheBool {
data: e.xor(self.data(), rhs.data(), key),
}
})
}
}
impl BitXorAssign for FheBool {
fn bitxor_assign(&mut self, rhs: Self) {
BoolEvaluator::with_local_mut_mut(&mut |e| {
let key = RuntimeServerKey::global();
e.xor_inplace(&mut self.data_mut(), rhs.data(), key);
});
}
}
impl Not for &FheBool {
type Output = FheBool;
fn not(self) -> Self::Output {
BoolEvaluator::with_local(|e| FheBool {
data: e.not(self.data()),
})
}
}
}
}
mod common_mp_enc_dec {
use super::BoolEvaluator;

+ 60
- 5
src/bool/mp_api.rs

@ -265,10 +265,10 @@ mod tests {
use crate::{
bool::{
evaluator::BooleanGates,
evaluator::BoolEncoding,
keys::tests::{ideal_sk_rlwe, measure_noise_lwe},
BooleanGates,
},
evaluator::{BoolEncoding, BoolEvaluator},
Encryptor, MultiPartyDecryptor,
};
@ -368,9 +368,8 @@ mod tests {
use rand::Rng;
use crate::{
backend::ModulusPowerOf2, evaluator::BoolEncoding, pbs::PbsInfo,
rgsw::seeded_secret_key_encrypt_rlwe, utils::WithLocal, Decryptor, ModularOpsU64,
NttBackendU64, SampleExtractor,
bool::impl_bool_frontend::FheBool, pbs::PbsInfo, rgsw::seeded_secret_key_encrypt_rlwe,
Decryptor, SampleExtractor,
};
use super::*;
@ -423,6 +422,27 @@ mod tests {
BoolEvaluator::with_local(|e| e.sk_decrypt(c, self))
}
}
impl<K: SinglePartyClientKey<Element = i32>, C> Encryptor<bool, FheBool<C>> for K
where
K: Encryptor<bool, C>,
{
fn encrypt(&self, m: &bool) -> FheBool<C> {
FheBool {
data: self.encrypt(m),
}
}
}
impl<K: SinglePartyClientKey<Element = i32>, C> Decryptor<bool, FheBool<C>> for K
where
K: Decryptor<bool, C>,
{
fn decrypt(&self, c: &FheBool<C>) -> bool {
self.decrypt(c.data())
}
}
impl<K> Encryptor<[bool], (Vec<Vec<u64>>, [u8; 32])> for K
where
K: SinglePartyClientKey<Element = i32>,
@ -658,5 +678,40 @@ mod tests {
}
}
}
#[test]
#[cfg(feature = "interactive_mp")]
fn all_bool_apis() {
use crate::FheBool;
set_single_party_parameter_sets(SP_TEST_BOOL_PARAMS);
let (ck, sk) = gen_keys();
sk.set_server_key();
for _ in 0..100 {
let a = thread_rng().gen_bool(0.5);
let b = thread_rng().gen_bool(0.5);
let c_a: FheBool = ck.encrypt(&a);
let c_b: FheBool = ck.encrypt(&b);
let c_out = &c_a & &c_b;
let out = ck.decrypt(&c_out);
assert_eq!(out, a & b, "Expected {} but got {out}", a & b);
let c_out = &c_a | &c_b;
let out = ck.decrypt(&c_out);
assert_eq!(out, a | b, "Expected {} but got {out}", a | b);
let c_out = &c_a ^ &c_b;
let out = ck.decrypt(&c_out);
assert_eq!(out, a ^ b, "Expected {} but got {out}", a ^ b);
let c_out = !(&c_a);
let out = ck.decrypt(&c_out);
assert_eq!(out, !a, "Expected {} but got {out}", !a);
}
}
}
}

+ 1
- 1
src/bool/ni_mp_api.rs

@ -406,8 +406,8 @@ mod tests {
use crate::{
bool::{
evaluator::BooleanGates,
keys::tests::{ideal_sk_rlwe, measure_noise_lwe},
BooleanGates,
},
Encoder, Encryptor, KeySwitchWithId, MultiPartyDecryptor,
};

+ 8
- 4
src/bool/print_noise.rs

@ -370,8 +370,10 @@ mod tests {
fn qwerty() {
use crate::{
aggregate_public_key_shares, aggregate_server_key_shares,
bool::keys::{key_size::KeySize, ServerKeyEvaluationDomain},
evaluator::InteractiveMultiPartyCrs,
bool::{
evaluator::InteractiveMultiPartyCrs,
keys::{key_size::KeySize, ServerKeyEvaluationDomain},
},
gen_client_key, gen_mp_keys_phase1, gen_mp_keys_phase2,
parameters::CiphertextModulus,
random::DefaultSecureRng,
@ -432,9 +434,11 @@ mod tests {
fn querty2() {
use crate::{
aggregate_server_key_shares,
bool::keys::{key_size::KeySize, NonInteractiveServerKeyEvaluationDomain},
bool::{
evaluator::NonInteractiveMultiPartyCrs,
keys::{key_size::KeySize, NonInteractiveServerKeyEvaluationDomain},
},
decomposer::DefaultDecomposer,
evaluator::NonInteractiveMultiPartyCrs,
gen_client_key, gen_server_key_share,
parameters::CiphertextModulus,
random::DefaultSecureRng,

+ 1
- 1
src/lib.rs

@ -22,7 +22,7 @@ pub use backend::{
// ParameterSelector, };
pub use bool::*;
pub use ntt::{Ntt, NttBackendU64, NttInit};
pub use shortint::{div_zero_error_flag, FheBool, FheUint8};
pub use shortint::{div_zero_error_flag, FheUint8};
pub use decomposer::{Decomposer, DecomposerIter, DefaultDecomposer};

+ 1
- 26
src/shortint/enc_dec.rs

@ -1,19 +1,13 @@
use itertools::Itertools;
use crate::{
bool::BoolEvaluator,
bool::{BoolEvaluator, FheBool},
random::{DefaultSecureRng, RandomFillUniformInModulus},
utils::WithLocal,
Decryptor, Encryptor, KeySwitchWithId, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor,
RowMut, SampleExtractor,
};
/// Fhe Bool ciphertext
#[derive(Clone)]
pub struct FheBool<C> {
pub(super) data: C,
}
/// Fhe UInt8 type
///
/// - Stores encryptions of bits in little endian (i.e least signficant bit
@ -210,25 +204,6 @@ where
}
}
impl<C, K> MultiPartyDecryptor<bool, FheBool<C>> for K
where
K: MultiPartyDecryptor<bool, C>,
{
type DecryptionShare = <K as MultiPartyDecryptor<bool, C>>::DecryptionShare;
fn aggregate_decryption_shares(
&self,
c: &FheBool<C>,
shares: &[Self::DecryptionShare],
) -> bool {
self.aggregate_decryption_shares(&c.data, shares)
}
fn gen_decryption_share(&self, c: &FheBool<C>) -> Self::DecryptionShare {
self.gen_decryption_share(&c.data)
}
}
impl<C, K> Encryptor<u8, FheUint8<C>> for K
where
K: Encryptor<bool, C>,

+ 1
- 2
src/shortint/mod.rs

@ -2,11 +2,10 @@ mod enc_dec;
mod ops;
pub type FheUint8 = enc_dec::FheUint8<Vec<u64>>;
pub type FheBool = enc_dec::FheBool<Vec<u64>>;
use std::cell::RefCell;
use crate::bool::{evaluator::BooleanGates, BoolEvaluator, RuntimeServerKey};
use crate::bool::{BoolEvaluator, BooleanGates, FheBool, RuntimeServerKey};
thread_local! {
static DIV_ZERO_ERROR: RefCell<Option<FheBool>> = RefCell::new(None);

+ 1
- 1
src/shortint/ops.rs

@ -1,6 +1,6 @@
use itertools::{izip, Itertools};
use crate::bool::evaluator::BooleanGates;
use crate::bool::BooleanGates;
pub(super) fn half_adder<E: BooleanGates>(
evaluator: &mut E,

Loading…
Cancel
Save