mirror of
https://github.com/arnaucube/phantom-zone.git
synced 2026-01-09 15:41:30 +01:00
move fhe uint8 api tests
This commit is contained in:
@@ -14,10 +14,15 @@ num-bigint-dig = { version = "0.8.4", features = ["prime"] }
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.5.1"
|
criterion = "0.5.1"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["interactive_mp"]
|
||||||
|
interactive_mp = []
|
||||||
|
non_interactive_mp = []
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "ntt"
|
name = "ntt"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "modulus"
|
name = "modulus"
|
||||||
harness = false
|
harness = false
|
||||||
|
|||||||
@@ -2180,7 +2180,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
parameters::{
|
parameters::{
|
||||||
MP_BOOL_PARAMS, NON_INTERACTIVE_SMALL_MP_BOOL_PARAMS, SMALL_MP_BOOL_PARAMS,
|
MP_BOOL_PARAMS, NON_INTERACTIVE_SMALL_MP_BOOL_PARAMS, SMALL_MP_BOOL_PARAMS,
|
||||||
SP_BOOL_PARAMS,
|
SP_TEST_BOOL_PARAMS,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ntt::NttBackendU64,
|
ntt::NttBackendU64,
|
||||||
@@ -2204,7 +2204,7 @@ mod tests {
|
|||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
ModularOpsU64<CiphertextModulus<u64>>,
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
ModularOpsU64<CiphertextModulus<u64>>,
|
||||||
ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
|
ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
|
||||||
>::new(SP_BOOL_PARAMS);
|
>::new(SP_TEST_BOOL_PARAMS);
|
||||||
let client_key = bool_evaluator.client_key();
|
let client_key = bool_evaluator.client_key();
|
||||||
|
|
||||||
let mut m = true;
|
let mut m = true;
|
||||||
@@ -2216,243 +2216,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bool_nand() {
|
|
||||||
let mut bool_evaluator = BoolEvaluator::<
|
|
||||||
Vec<Vec<u64>>,
|
|
||||||
NttBackendU64,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ShoupServerKeyEvaluationDomain<_>,
|
|
||||||
>::new(SP_BOOL_PARAMS);
|
|
||||||
|
|
||||||
// println!("{:?}", bool_evaluator.nand_test_vec);
|
|
||||||
let client_key = bool_evaluator.client_key();
|
|
||||||
let seeded_server_key = bool_evaluator.single_party_server_key(&client_key);
|
|
||||||
let runtime_server_key =
|
|
||||||
ShoupServerKeyEvaluationDomain::from(ServerKeyEvaluationDomain::<
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
DefaultSecureRng,
|
|
||||||
NttBackendU64,
|
|
||||||
>::from(&seeded_server_key));
|
|
||||||
|
|
||||||
let mut m0 = false;
|
|
||||||
let mut m1 = true;
|
|
||||||
|
|
||||||
let mut ct0 = bool_evaluator.sk_encrypt(m0, &client_key);
|
|
||||||
let mut ct1 = bool_evaluator.sk_encrypt(m1, &client_key);
|
|
||||||
|
|
||||||
for _ in 0..500 {
|
|
||||||
let ct_back = bool_evaluator.nand(&ct0, &ct1, &runtime_server_key);
|
|
||||||
|
|
||||||
let m_out = !(m0 && m1);
|
|
||||||
|
|
||||||
let m_back = bool_evaluator.sk_decrypt(&ct_back, &client_key);
|
|
||||||
assert!(m_out == m_back, "Expected {m_out}, got {m_back}");
|
|
||||||
|
|
||||||
m1 = m0;
|
|
||||||
m0 = m_out;
|
|
||||||
|
|
||||||
ct1 = ct0;
|
|
||||||
ct0 = ct_back;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bool_xor() {
|
|
||||||
let mut bool_evaluator = BoolEvaluator::<
|
|
||||||
Vec<Vec<u64>>,
|
|
||||||
NttBackendU64,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ShoupServerKeyEvaluationDomain<_>,
|
|
||||||
>::new(SP_BOOL_PARAMS);
|
|
||||||
|
|
||||||
// println!("{:?}", bool_evaluator.nand_test_vec);
|
|
||||||
let client_key = bool_evaluator.client_key();
|
|
||||||
let seeded_server_key = bool_evaluator.single_party_server_key(&client_key);
|
|
||||||
let runtime_server_key =
|
|
||||||
ShoupServerKeyEvaluationDomain::from(ServerKeyEvaluationDomain::<
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
DefaultSecureRng,
|
|
||||||
NttBackendU64,
|
|
||||||
>::from(&seeded_server_key));
|
|
||||||
|
|
||||||
let mut m0 = false;
|
|
||||||
let mut m1 = true;
|
|
||||||
|
|
||||||
let mut ct0 = bool_evaluator.sk_encrypt(m0, &client_key);
|
|
||||||
let mut ct1 = bool_evaluator.sk_encrypt(m1, &client_key);
|
|
||||||
|
|
||||||
for _ in 0..1000 {
|
|
||||||
let ct_back = bool_evaluator.xor(&ct0, &ct1, &runtime_server_key);
|
|
||||||
let m_out = (m0 ^ m1);
|
|
||||||
|
|
||||||
let m_back = bool_evaluator.sk_decrypt(&ct_back, &client_key);
|
|
||||||
assert!(m_out == m_back, "Expected {m_out}, got {m_back}");
|
|
||||||
|
|
||||||
m1 = m0;
|
|
||||||
m0 = m_out;
|
|
||||||
|
|
||||||
ct1 = ct0;
|
|
||||||
ct0 = ct_back;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multi_party_encryption_decryption() {
|
|
||||||
let bool_evaluator = BoolEvaluator::<
|
|
||||||
Vec<Vec<u64>>,
|
|
||||||
NttBackendU64,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
|
|
||||||
>::new(MP_BOOL_PARAMS);
|
|
||||||
|
|
||||||
let no_of_parties = 500;
|
|
||||||
let parties = (0..no_of_parties)
|
|
||||||
.map(|_| bool_evaluator.client_key())
|
|
||||||
.collect_vec();
|
|
||||||
|
|
||||||
let mut ideal_rlwe_sk = vec![0i32; bool_evaluator.pbs_info.rlwe_n()];
|
|
||||||
parties.iter().for_each(|k| {
|
|
||||||
izip!(
|
|
||||||
ideal_rlwe_sk.iter_mut(),
|
|
||||||
InteractiveMultiPartyClientKey::sk_rlwe(k).iter()
|
|
||||||
)
|
|
||||||
.for_each(|(ideal_i, s_i)| {
|
|
||||||
*ideal_i = *ideal_i + s_i;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut m = true;
|
|
||||||
for i in 0..100 {
|
|
||||||
let pk_cr_seed = [0u8; 32];
|
|
||||||
|
|
||||||
let public_key_share = parties
|
|
||||||
.iter()
|
|
||||||
.map(|k| bool_evaluator.multi_party_public_key_share(pk_cr_seed, k))
|
|
||||||
.collect_vec();
|
|
||||||
|
|
||||||
let collective_pk = PublicKey::<
|
|
||||||
Vec<Vec<u64>>,
|
|
||||||
DefaultSecureRng,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
>::from(public_key_share.as_slice());
|
|
||||||
let lwe_ct = bool_evaluator.pk_encrypt(collective_pk.key(), m);
|
|
||||||
|
|
||||||
let decryption_shares = parties
|
|
||||||
.iter()
|
|
||||||
.map(|k| bool_evaluator.multi_party_decryption_share(&lwe_ct, k))
|
|
||||||
.collect_vec();
|
|
||||||
|
|
||||||
let m_back = bool_evaluator.multi_party_decrypt(&decryption_shares, &lwe_ct);
|
|
||||||
|
|
||||||
{
|
|
||||||
let ideal_m = if m {
|
|
||||||
bool_evaluator.pbs_info.parameters.rlwe_q().true_el()
|
|
||||||
} else {
|
|
||||||
bool_evaluator.pbs_info.parameters.rlwe_q().false_el()
|
|
||||||
};
|
|
||||||
let noise = measure_noise_lwe(
|
|
||||||
&lwe_ct,
|
|
||||||
&ideal_rlwe_sk,
|
|
||||||
&bool_evaluator.pbs_info.rlwe_modop,
|
|
||||||
&ideal_m,
|
|
||||||
);
|
|
||||||
println!("Noise: {noise}");
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(m_back, m);
|
|
||||||
m = !m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn interactive_multi_party_nand() {
|
|
||||||
let mut bool_evaluator = BoolEvaluator::<
|
|
||||||
Vec<Vec<u64>>,
|
|
||||||
NttBackendU64,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ModularOpsU64<CiphertextModulus<u64>>,
|
|
||||||
ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
|
|
||||||
>::new(MP_BOOL_PARAMS);
|
|
||||||
|
|
||||||
let multi_party_crs = MultiPartyCrs::random();
|
|
||||||
|
|
||||||
// let (parties, collective_pk, _, _, server_key_eval, ideal_client_key) =
|
|
||||||
// _multi_party_all_keygen(&bool_evaluator, 2);
|
|
||||||
|
|
||||||
let no_of_parties = 2;
|
|
||||||
let parties = (0..no_of_parties)
|
|
||||||
.map(|_| bool_evaluator.client_key())
|
|
||||||
.collect_vec();
|
|
||||||
|
|
||||||
// generate public key
|
|
||||||
let pk_shares = parties
|
|
||||||
.iter()
|
|
||||||
.map(|k| {
|
|
||||||
bool_evaluator.multi_party_public_key_share(
|
|
||||||
multi_party_crs.public_key_share_seed::<DefaultSecureRng>(),
|
|
||||||
k,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect_vec();
|
|
||||||
let collective_pk =
|
|
||||||
PublicKey::<_, DefaultSecureRng, ModularOpsU64<CiphertextModulus<u64>>>::from(
|
|
||||||
pk_shares.as_slice(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// generate server key
|
|
||||||
let server_key_shares = parties
|
|
||||||
.iter()
|
|
||||||
.map(|k| {
|
|
||||||
bool_evaluator.multi_party_server_key_share(
|
|
||||||
multi_party_crs.server_key_share_seed::<DefaultSecureRng>(),
|
|
||||||
collective_pk.key(),
|
|
||||||
k,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect_vec();
|
|
||||||
let seeded_server_key =
|
|
||||||
bool_evaluator.aggregate_multi_party_server_key_shares(&server_key_shares);
|
|
||||||
let server_key_eval =
|
|
||||||
ShoupServerKeyEvaluationDomain::from(ServerKeyEvaluationDomain::<
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
DefaultSecureRng,
|
|
||||||
NttBackendU64,
|
|
||||||
>::from(&seeded_server_key));
|
|
||||||
|
|
||||||
let mut m0 = true;
|
|
||||||
let mut m1 = false;
|
|
||||||
|
|
||||||
let mut lwe0 = bool_evaluator.pk_encrypt(collective_pk.key(), m0);
|
|
||||||
let mut lwe1 = bool_evaluator.pk_encrypt(collective_pk.key(), m1);
|
|
||||||
|
|
||||||
for _ in 0..2000 {
|
|
||||||
let lwe_out = bool_evaluator.nand(&lwe0, &lwe1, &server_key_eval);
|
|
||||||
|
|
||||||
let m_expected = !(m0 & m1);
|
|
||||||
|
|
||||||
// multi-party decrypt
|
|
||||||
let decryption_shares = parties
|
|
||||||
.iter()
|
|
||||||
.map(|k| bool_evaluator.multi_party_decryption_share(&lwe_out, k))
|
|
||||||
.collect_vec();
|
|
||||||
let m_back = bool_evaluator.multi_party_decrypt(&decryption_shares, &lwe_out);
|
|
||||||
|
|
||||||
assert!(m_expected == m_back, "Expected {m_expected}, got {m_back}");
|
|
||||||
m1 = m0;
|
|
||||||
m0 = m_expected;
|
|
||||||
|
|
||||||
lwe1 = lwe0;
|
|
||||||
lwe0 = lwe_out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn noise_tester() {
|
fn noise_tester() {
|
||||||
let bool_evaluator = BoolEvaluator::<
|
let bool_evaluator = BoolEvaluator::<
|
||||||
|
|||||||
@@ -4,14 +4,41 @@ mod mp_api;
|
|||||||
mod ni_mp_api;
|
mod ni_mp_api;
|
||||||
mod noise;
|
mod noise;
|
||||||
pub(crate) mod parameters;
|
pub(crate) mod parameters;
|
||||||
mod sp_api;
|
|
||||||
|
|
||||||
pub(crate) use keys::PublicKey;
|
pub(crate) use keys::PublicKey;
|
||||||
|
|
||||||
|
#[cfg(feature = "non_interactive_mp")]
|
||||||
pub use ni_mp_api::*;
|
pub use ni_mp_api::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "interactive_mp")]
|
||||||
|
pub use mp_api::*;
|
||||||
|
|
||||||
pub type ClientKey = keys::ClientKey<[u8; 32], u64>;
|
pub type ClientKey = keys::ClientKey<[u8; 32], u64>;
|
||||||
|
|
||||||
pub enum ParameterSelector {
|
pub enum ParameterSelector {
|
||||||
MultiPartyLessThanOrEqualTo16,
|
MultiPartyLessThanOrEqualTo16,
|
||||||
NonInteractiveMultiPartyLessThanOrEqualTo16,
|
NonInteractiveMultiPartyLessThanOrEqualTo16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod common_mp_enc_dec {
|
||||||
|
use super::BoolEvaluator;
|
||||||
|
use crate::{utils::WithLocal, Matrix, MultiPartyDecryptor};
|
||||||
|
|
||||||
|
type Mat = Vec<Vec<u64>>;
|
||||||
|
|
||||||
|
impl<E> MultiPartyDecryptor<bool, <Mat as Matrix>::R> for super::keys::ClientKey<[u8; 32], E> {
|
||||||
|
type DecryptionShare = <Mat as Matrix>::MatElement;
|
||||||
|
|
||||||
|
fn gen_decryption_share(&self, c: &<Mat as Matrix>::R) -> Self::DecryptionShare {
|
||||||
|
BoolEvaluator::with_local(|e| e.multi_party_decryption_share(c, self))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn aggregate_decryption_shares(
|
||||||
|
&self,
|
||||||
|
c: &<Mat as Matrix>::R,
|
||||||
|
shares: &[Self::DecryptionShare],
|
||||||
|
) -> bool {
|
||||||
|
BoolEvaluator::with_local(|e| e.multi_party_decrypt(shares, c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,25 +43,6 @@ pub fn set_mp_seed(seed: [u8; 32]) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_server_key(key: ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>) {
|
|
||||||
assert!(
|
|
||||||
BOOL_SERVER_KEY.set(key).is_ok(),
|
|
||||||
"Attempted to set server key twice."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn gen_keys() -> (
|
|
||||||
ClientKey,
|
|
||||||
SeededSinglePartyServerKey<Vec<Vec<u64>>, BoolParameters<u64>, [u8; 32]>,
|
|
||||||
) {
|
|
||||||
BoolEvaluator::with_local_mut(|e| {
|
|
||||||
let ck = e.client_key();
|
|
||||||
let sk = e.single_party_server_key(&ck);
|
|
||||||
|
|
||||||
(ck, sk)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gen_client_key() -> ClientKey {
|
pub fn gen_client_key() -> ClientKey {
|
||||||
BoolEvaluator::with_local(|e| e.client_key())
|
BoolEvaluator::with_local(|e| e.client_key())
|
||||||
}
|
}
|
||||||
@@ -107,14 +88,6 @@ pub fn aggregate_server_key_shares(
|
|||||||
BoolEvaluator::with_local(|e| e.aggregate_multi_party_server_key_shares(shares))
|
BoolEvaluator::with_local(|e| e.aggregate_multi_party_server_key_shares(shares))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SERVER KEY EVAL (/SHOUP) DOMAIN //
|
|
||||||
impl SeededSinglePartyServerKey<Vec<Vec<u64>>, BoolParameters<u64>, [u8; 32]> {
|
|
||||||
pub fn set_server_key(&self) {
|
|
||||||
let eval = ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(self);
|
|
||||||
set_server_key(ShoupServerKeyEvaluationDomain::from(eval));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl
|
impl
|
||||||
SeededMultiPartyServerKey<
|
SeededMultiPartyServerKey<
|
||||||
Vec<Vec<u64>>,
|
Vec<Vec<u64>>,
|
||||||
@@ -123,9 +96,14 @@ impl
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
pub fn set_server_key(&self) {
|
pub fn set_server_key(&self) {
|
||||||
set_server_key(ShoupServerKeyEvaluationDomain::from(
|
assert!(
|
||||||
ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(self),
|
BOOL_SERVER_KEY
|
||||||
))
|
.set(ShoupServerKeyEvaluationDomain::from(
|
||||||
|
ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(self),
|
||||||
|
))
|
||||||
|
.is_ok(),
|
||||||
|
"Attempted to set server key twice."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,3 +221,290 @@ mod impl_enc_dec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use itertools::Itertools;
|
||||||
|
use rand::{thread_rng, RngCore};
|
||||||
|
|
||||||
|
use crate::{bool::evaluator::BooleanGates, Encryptor, MultiPartyDecryptor};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_party_bool_gates() {
|
||||||
|
set_parameter_set(ParameterSelector::MultiPartyLessThanOrEqualTo16);
|
||||||
|
let mut seed = [0u8; 32];
|
||||||
|
thread_rng().fill_bytes(&mut seed);
|
||||||
|
set_mp_seed(seed);
|
||||||
|
|
||||||
|
let parties = 2;
|
||||||
|
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
|
||||||
|
|
||||||
|
// round 1
|
||||||
|
let pk_shares = cks.iter().map(|k| gen_mp_keys_phase1(k)).collect_vec();
|
||||||
|
|
||||||
|
// collective pk
|
||||||
|
let pk = aggregate_public_key_shares(&pk_shares);
|
||||||
|
|
||||||
|
// round 2
|
||||||
|
let server_key_shares = cks.iter().map(|k| gen_mp_keys_phase2(k, &pk)).collect_vec();
|
||||||
|
|
||||||
|
// server key
|
||||||
|
let server_key = aggregate_server_key_shares(&server_key_shares);
|
||||||
|
server_key.set_server_key();
|
||||||
|
|
||||||
|
let mut m0 = false;
|
||||||
|
let mut m1 = true;
|
||||||
|
|
||||||
|
let mut ct0 = pk.encrypt(&m0);
|
||||||
|
let mut ct1 = pk.encrypt(&m1);
|
||||||
|
|
||||||
|
for _ in 0..500 {
|
||||||
|
let ct_out =
|
||||||
|
BoolEvaluator::with_local_mut(|e| e.nand(&ct0, &ct1, RuntimeServerKey::global()));
|
||||||
|
|
||||||
|
let m_expected = !(m0 && m1);
|
||||||
|
|
||||||
|
let decryption_shares = cks
|
||||||
|
.iter()
|
||||||
|
.map(|k| k.gen_decryption_share(&ct_out))
|
||||||
|
.collect_vec();
|
||||||
|
let m_out = cks[0].aggregate_decryption_shares(&ct_out, &decryption_shares);
|
||||||
|
|
||||||
|
assert!(m_out == m_expected, "Expected {m_expected}, got {m_out}");
|
||||||
|
|
||||||
|
m1 = m0;
|
||||||
|
m0 = m_expected;
|
||||||
|
|
||||||
|
ct1 = ct0;
|
||||||
|
ct0 = ct_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..500 {
|
||||||
|
let ct_out =
|
||||||
|
BoolEvaluator::with_local_mut(|e| e.xnor(&ct0, &ct1, RuntimeServerKey::global()));
|
||||||
|
|
||||||
|
let m_expected = !(m0 ^ m1);
|
||||||
|
|
||||||
|
let decryption_shares = cks
|
||||||
|
.iter()
|
||||||
|
.map(|k| k.gen_decryption_share(&ct_out))
|
||||||
|
.collect_vec();
|
||||||
|
let m_out = cks[0].aggregate_decryption_shares(&ct_out, &decryption_shares);
|
||||||
|
|
||||||
|
assert!(m_out == m_expected, "Expected {m_expected}, got {m_out}");
|
||||||
|
|
||||||
|
m1 = m0;
|
||||||
|
m0 = m_expected;
|
||||||
|
|
||||||
|
ct1 = ct0;
|
||||||
|
ct0 = ct_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod sp_api {
|
||||||
|
use crate::{
|
||||||
|
backend::ModulusPowerOf2, utils::WithLocal, Decryptor, ModularOpsU64, NttBackendU64,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(crate) fn set_single_party_parameter_sets(parameter: BoolParameters<u64>) {
|
||||||
|
BOOL_EVALUATOR.with_borrow_mut(|e| *e = Some(BoolEvaluator::new(parameter)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SERVER KEY EVAL (/SHOUP) DOMAIN //
|
||||||
|
impl SeededSinglePartyServerKey<Vec<Vec<u64>>, BoolParameters<u64>, [u8; 32]> {
|
||||||
|
pub fn set_server_key(&self) {
|
||||||
|
assert!(
|
||||||
|
BOOL_SERVER_KEY
|
||||||
|
.set(
|
||||||
|
ShoupServerKeyEvaluationDomain::from(ServerKeyEvaluationDomain::<
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
DefaultSecureRng,
|
||||||
|
NttBackendU64,
|
||||||
|
>::from(
|
||||||
|
self
|
||||||
|
),)
|
||||||
|
)
|
||||||
|
.is_ok(),
|
||||||
|
"Attempted to set server key twice."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn gen_keys() -> (
|
||||||
|
ClientKey,
|
||||||
|
SeededSinglePartyServerKey<Vec<Vec<u64>>, BoolParameters<u64>, [u8; 32]>,
|
||||||
|
) {
|
||||||
|
super::BoolEvaluator::with_local_mut(|e| {
|
||||||
|
let ck = e.client_key();
|
||||||
|
let sk = e.single_party_server_key(&ck);
|
||||||
|
|
||||||
|
(ck, sk)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K: SinglePartyClientKey<Element = i32>> Encryptor<bool, Vec<u64>> for K {
|
||||||
|
fn encrypt(&self, m: &bool) -> Vec<u64> {
|
||||||
|
BoolEvaluator::with_local(|e| e.sk_encrypt(*m, self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K: SinglePartyClientKey<Element = i32>> Decryptor<bool, Vec<u64>> for K {
|
||||||
|
fn decrypt(&self, c: &Vec<u64>) -> bool {
|
||||||
|
BoolEvaluator::with_local(|e| e.sk_decrypt(c, self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "interactive_mp")]
|
||||||
|
fn all_uint8_apis() {
|
||||||
|
use num_traits::Euclid;
|
||||||
|
|
||||||
|
set_single_party_parameter_sets(SP_TEST_BOOL_PARAMS);
|
||||||
|
|
||||||
|
let (ck, sk) = gen_keys();
|
||||||
|
sk.set_server_key();
|
||||||
|
|
||||||
|
for i in 144..=255 {
|
||||||
|
for j in 100..=255 {
|
||||||
|
let m0 = i;
|
||||||
|
let m1 = j;
|
||||||
|
let c0 = ck.encrypt(&m0);
|
||||||
|
let c1 = ck.encrypt(&m1);
|
||||||
|
|
||||||
|
assert!(ck.decrypt(&c0) == m0);
|
||||||
|
assert!(ck.decrypt(&c1) == m1);
|
||||||
|
|
||||||
|
// Arithmetic
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// Add
|
||||||
|
let c_add = &c0 + &c1;
|
||||||
|
let m0_plus_m1 = ck.decrypt(&c_add);
|
||||||
|
assert_eq!(
|
||||||
|
m0_plus_m1,
|
||||||
|
m0.wrapping_add(m1),
|
||||||
|
"Expected {} but got {m0_plus_m1} for {i}+{j}",
|
||||||
|
m0.wrapping_add(m1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Sub
|
||||||
|
let c_sub = &c0 - &c1;
|
||||||
|
let m0_sub_m1 = ck.decrypt(&c_sub);
|
||||||
|
assert_eq!(
|
||||||
|
m0_sub_m1,
|
||||||
|
m0.wrapping_sub(m1),
|
||||||
|
"Expected {} but got {m0_sub_m1} for {i}-{j}",
|
||||||
|
m0.wrapping_sub(m1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Mul
|
||||||
|
let c_m0m1 = &c0 * &c1;
|
||||||
|
let m0m1 = ck.decrypt(&c_m0m1);
|
||||||
|
assert_eq!(
|
||||||
|
m0m1,
|
||||||
|
m0.wrapping_mul(m1),
|
||||||
|
"Expected {} but got {m0m1} for {i}x{j}",
|
||||||
|
m0.wrapping_mul(m1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Div & Rem
|
||||||
|
{
|
||||||
|
let (c_quotient, c_rem) = c0.div_rem(&c1);
|
||||||
|
let m_quotient = ck.decrypt(&c_quotient);
|
||||||
|
let m_remainder = ck.decrypt(&c_rem);
|
||||||
|
if j != 0 {
|
||||||
|
let (q, r) = i.div_rem_euclid(&j);
|
||||||
|
assert_eq!(
|
||||||
|
m_quotient, q,
|
||||||
|
"Expected {} but got {m_quotient} for {i}/{j}",
|
||||||
|
q
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
m_remainder, r,
|
||||||
|
"Expected {} but got {m_quotient} for {i}%{j}",
|
||||||
|
r
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
assert_eq!(
|
||||||
|
m_quotient, 255,
|
||||||
|
"Expected 255 but got {m_quotient}. Case div by zero"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
m_remainder, i,
|
||||||
|
"Expected {i} but got {m_quotient}. Case div by zero"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparisons
|
||||||
|
{
|
||||||
|
{
|
||||||
|
let c_eq = c0.eq(&c1);
|
||||||
|
let is_eq = ck.decrypt(&c_eq);
|
||||||
|
assert_eq!(
|
||||||
|
is_eq,
|
||||||
|
i == j,
|
||||||
|
"Expected {} but got {is_eq} for {i}=={j}",
|
||||||
|
i == j
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let c_gt = c0.gt(&c1);
|
||||||
|
let is_gt = ck.decrypt(&c_gt);
|
||||||
|
assert_eq!(
|
||||||
|
is_gt,
|
||||||
|
i > j,
|
||||||
|
"Expected {} but got {is_gt} for {i}>{j}",
|
||||||
|
i > j
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let c_lt = c0.lt(&c1);
|
||||||
|
let is_lt = ck.decrypt(&c_lt);
|
||||||
|
assert_eq!(
|
||||||
|
is_lt,
|
||||||
|
i < j,
|
||||||
|
"Expected {} but got {is_lt} for {i}<{j}",
|
||||||
|
i < j
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let c_ge = c0.ge(&c1);
|
||||||
|
let is_ge = ck.decrypt(&c_ge);
|
||||||
|
assert_eq!(
|
||||||
|
is_ge,
|
||||||
|
i >= j,
|
||||||
|
"Expected {} but got {is_ge} for {i}>={j}",
|
||||||
|
i >= j
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let c_le = c0.le(&c1);
|
||||||
|
let is_le = ck.decrypt(&c_le);
|
||||||
|
assert_eq!(
|
||||||
|
is_le,
|
||||||
|
i <= j,
|
||||||
|
"Expected {} but got {is_le} for {i}<={j}",
|
||||||
|
i <= j
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -348,24 +348,6 @@ mod impl_enc_dec {
|
|||||||
BatchedFheBools { data }
|
BatchedFheBools { data }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> MultiPartyDecryptor<bool, <Mat as Matrix>::R>
|
|
||||||
for super::super::keys::ClientKey<[u8; 32], E>
|
|
||||||
{
|
|
||||||
type DecryptionShare = <Mat as Matrix>::MatElement;
|
|
||||||
|
|
||||||
fn gen_decryption_share(&self, c: &<Mat as Matrix>::R) -> Self::DecryptionShare {
|
|
||||||
BoolEvaluator::with_local(|e| e.multi_party_decryption_share(c, self))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn aggregate_decryption_shares(
|
|
||||||
&self,
|
|
||||||
c: &<Mat as Matrix>::R,
|
|
||||||
shares: &[Self::DecryptionShare],
|
|
||||||
) -> bool {
|
|
||||||
BoolEvaluator::with_local(|e| e.multi_party_decrypt(shares, c))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -442,25 +442,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const SP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
|
|
||||||
rlwe_q: CiphertextModulus::new_non_native(268369921u64),
|
|
||||||
lwe_q: CiphertextModulus::new_non_native(1 << 16),
|
|
||||||
br_q: 1 << 10,
|
|
||||||
rlwe_n: PolynomialSize(1 << 10),
|
|
||||||
lwe_n: LweDimension(500),
|
|
||||||
lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(4)),
|
|
||||||
rlrg_decomposer_params: (
|
|
||||||
DecompostionLogBase(7),
|
|
||||||
(DecompositionCount(4), DecompositionCount(4)),
|
|
||||||
),
|
|
||||||
rgrg_decomposer_params: None,
|
|
||||||
auto_decomposer_params: (DecompostionLogBase(7), DecompositionCount(4)),
|
|
||||||
non_interactive_ui_to_s_key_switch_decomposer: None,
|
|
||||||
g: 5,
|
|
||||||
w: 5,
|
|
||||||
variant: ParameterVariant::SingleParty,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
|
pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
|
||||||
rlwe_q: CiphertextModulus::new_non_native(1152921504606830593),
|
rlwe_q: CiphertextModulus::new_non_native(1152921504606830593),
|
||||||
lwe_q: CiphertextModulus::new_non_native(1 << 20),
|
lwe_q: CiphertextModulus::new_non_native(1 << 20),
|
||||||
@@ -529,6 +510,27 @@ pub(crate) const NON_INTERACTIVE_SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = Boo
|
|||||||
w: 10,
|
w: 10,
|
||||||
variant: ParameterVariant::NonInteractiveMultiParty,
|
variant: ParameterVariant::NonInteractiveMultiParty,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) const SP_TEST_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
|
||||||
|
rlwe_q: CiphertextModulus::new_non_native(268369921u64),
|
||||||
|
lwe_q: CiphertextModulus::new_non_native(1 << 16),
|
||||||
|
br_q: 1 << 9,
|
||||||
|
rlwe_n: PolynomialSize(1 << 9),
|
||||||
|
lwe_n: LweDimension(100),
|
||||||
|
lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(4)),
|
||||||
|
rlrg_decomposer_params: (
|
||||||
|
DecompostionLogBase(7),
|
||||||
|
(DecompositionCount(4), DecompositionCount(4)),
|
||||||
|
),
|
||||||
|
rgrg_decomposer_params: None,
|
||||||
|
auto_decomposer_params: (DecompostionLogBase(7), DecompositionCount(4)),
|
||||||
|
non_interactive_ui_to_s_key_switch_decomposer: None,
|
||||||
|
g: 5,
|
||||||
|
w: 5,
|
||||||
|
variant: ParameterVariant::SingleParty,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
mod impl_enc_dec {
|
|
||||||
use crate::{Decryptor, Encryptor};
|
|
||||||
|
|
||||||
use super::super::keys::SinglePartyClientKey;
|
|
||||||
|
|
||||||
impl<K> Encryptor<bool, Vec<u64>> for K
|
|
||||||
where
|
|
||||||
K: SinglePartyClientKey,
|
|
||||||
{
|
|
||||||
fn encrypt(&self, m: &bool) -> Vec<u64> {
|
|
||||||
todo!()
|
|
||||||
// BoolEvaluator::with_local(|e| e.sk_encrypt(*m, self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K> Decryptor<bool, Vec<u64>> for K
|
|
||||||
where
|
|
||||||
K: SinglePartyClientKey,
|
|
||||||
{
|
|
||||||
fn decrypt(&self, c: &Vec<u64>) -> bool {
|
|
||||||
todo!()
|
|
||||||
// BoolEvaluator::with_local(|e| e.sk_decrypt(c, self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,3 @@
|
|||||||
use itertools::Itertools;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
bool::{parameters::CiphertextModulus, ClientKey, PublicKey},
|
|
||||||
random::{DefaultSecureRng, NewWithSeed, RandomFillUniformInModulus},
|
|
||||||
utils::{TryConvertFrom1, WithLocal},
|
|
||||||
Decryptor, Encryptor, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor, Row, RowMut,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod enc_dec;
|
mod enc_dec;
|
||||||
mod ops;
|
mod ops;
|
||||||
mod types;
|
mod types;
|
||||||
@@ -14,6 +5,8 @@ mod types;
|
|||||||
pub type FheUint8 = enc_dec::FheUint8<Vec<u64>>;
|
pub type FheUint8 = enc_dec::FheUint8<Vec<u64>>;
|
||||||
pub type FheBool = Vec<u64>;
|
pub type FheBool = Vec<u64>;
|
||||||
|
|
||||||
|
use crate::bool::{evaluator::BooleanGates, BoolEvaluator, RuntimeServerKey};
|
||||||
|
|
||||||
mod frontend {
|
mod frontend {
|
||||||
use super::ops::{
|
use super::ops::{
|
||||||
arbitrary_bit_adder, arbitrary_bit_division_for_quotient_and_rem, arbitrary_bit_subtractor,
|
arbitrary_bit_adder, arbitrary_bit_division_for_quotient_and_rem, arbitrary_bit_subtractor,
|
||||||
@@ -24,7 +17,6 @@ mod frontend {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
mod arithetic {
|
mod arithetic {
|
||||||
use crate::bool::{evaluator::BooleanGates, BoolEvaluator, RuntimeServerKey};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::ops::{Add, AddAssign, Div, Mul, Rem, Sub};
|
use std::ops::{Add, AddAssign, Div, Mul, Rem, Sub};
|
||||||
@@ -149,11 +141,8 @@ mod frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod booleans {
|
mod booleans {
|
||||||
use crate::{
|
use crate::shortint::ops::{
|
||||||
bool::{evaluator::BooleanGates, BoolEvaluator, RuntimeServerKey},
|
arbitrary_bit_comparator, arbitrary_bit_equality, arbitrary_signed_bit_comparator,
|
||||||
shortint::ops::{
|
|
||||||
arbitrary_bit_comparator, arbitrary_bit_equality, arbitrary_signed_bit_comparator,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -223,155 +212,9 @@ mod tests {
|
|||||||
use num_traits::Euclid;
|
use num_traits::Euclid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bool::set_parameter_set, shortint::enc_dec::FheUint8, Decryptor, Encryptor,
|
bool::set_parameter_set, shortint::enc_dec::FheUint8, utils::WithLocal, Decryptor,
|
||||||
MultiPartyDecryptor,
|
Encryptor, MultiPartyDecryptor,
|
||||||
};
|
};
|
||||||
|
|
||||||
// #[test]
|
use super::*;
|
||||||
// fn all_uint8_apis() {
|
|
||||||
// set_parameter_set(crate::ParameterSelector::MultiPartyLessThanOrEqualTo16);
|
|
||||||
|
|
||||||
// let (ck, sk) = gen_keys();
|
|
||||||
// sk.set_server_key();
|
|
||||||
|
|
||||||
// for i in 144..=255 {
|
|
||||||
// for j in 100..=255 {
|
|
||||||
// let m0 = i;
|
|
||||||
// let m1 = j;
|
|
||||||
// let c0 = ck.encrypt(&m0);
|
|
||||||
// let c1 = ck.encrypt(&m1);
|
|
||||||
|
|
||||||
// assert!(ck.decrypt(&c0) == m0);
|
|
||||||
// assert!(ck.decrypt(&c1) == m1);
|
|
||||||
|
|
||||||
// // Arithmetic
|
|
||||||
// {
|
|
||||||
// {
|
|
||||||
// // Add
|
|
||||||
// let mut c_m0_plus_m1 = FheUint8 {
|
|
||||||
// data: c0.data().to_vec(),
|
|
||||||
// };
|
|
||||||
// c_m0_plus_m1 += &c1;
|
|
||||||
// let m0_plus_m1 = ck.decrypt(&c_m0_plus_m1);
|
|
||||||
// assert_eq!(
|
|
||||||
// m0_plus_m1,
|
|
||||||
// m0.wrapping_add(m1),
|
|
||||||
// "Expected {} but got {m0_plus_m1} for {i}+{j}",
|
|
||||||
// m0.wrapping_add(m1)
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// {
|
|
||||||
// // Sub
|
|
||||||
// let c_sub = &c0 - &c1;
|
|
||||||
// let m0_sub_m1 = ck.decrypt(&c_sub);
|
|
||||||
// assert_eq!(
|
|
||||||
// m0_sub_m1,
|
|
||||||
// m0.wrapping_sub(m1),
|
|
||||||
// "Expected {} but got {m0_sub_m1} for {i}-{j}",
|
|
||||||
// m0.wrapping_sub(m1)
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// {
|
|
||||||
// // Mul
|
|
||||||
// let c_m0m1 = &c0 * &c1;
|
|
||||||
// let m0m1 = ck.decrypt(&c_m0m1);
|
|
||||||
// assert_eq!(
|
|
||||||
// m0m1,
|
|
||||||
// m0.wrapping_mul(m1),
|
|
||||||
// "Expected {} but got {m0m1} for {i}x{j}",
|
|
||||||
// m0.wrapping_mul(m1)
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Div & Rem
|
|
||||||
// {
|
|
||||||
// let (c_quotient, c_rem) = c0.div_rem(&c1);
|
|
||||||
// let m_quotient = ck.decrypt(&c_quotient);
|
|
||||||
// let m_remainder = ck.decrypt(&c_rem);
|
|
||||||
// if j != 0 {
|
|
||||||
// let (q, r) = i.div_rem_euclid(&j);
|
|
||||||
// assert_eq!(
|
|
||||||
// m_quotient, q,
|
|
||||||
// "Expected {} but got {m_quotient} for
|
|
||||||
// {i}/{j}", q
|
|
||||||
// );
|
|
||||||
// assert_eq!(
|
|
||||||
// m_remainder, r,
|
|
||||||
// "Expected {} but got {m_quotient} for
|
|
||||||
// {i}%{j}", r
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// assert_eq!(
|
|
||||||
// m_quotient, 255,
|
|
||||||
// "Expected 255 but got {m_quotient}. Case div
|
|
||||||
// by zero" );
|
|
||||||
// assert_eq!(
|
|
||||||
// m_remainder, i,
|
|
||||||
// "Expected {i} but got {m_quotient}. Case div
|
|
||||||
// by zero" )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Comparisons
|
|
||||||
// {
|
|
||||||
// {
|
|
||||||
// let c_eq = c0.eq(&c1);
|
|
||||||
// let is_eq = ck.decrypt(&c_eq);
|
|
||||||
// assert_eq!(
|
|
||||||
// is_eq,
|
|
||||||
// i == j,
|
|
||||||
// "Expected {} but got {is_eq} for {i}=={j}",
|
|
||||||
// i == j
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// {
|
|
||||||
// let c_gt = c0.gt(&c1);
|
|
||||||
// let is_gt = ck.decrypt(&c_gt);
|
|
||||||
// assert_eq!(
|
|
||||||
// is_gt,
|
|
||||||
// i > j,
|
|
||||||
// "Expected {} but got {is_gt} for {i}>{j}",
|
|
||||||
// i > j
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// {
|
|
||||||
// let c_lt = c0.lt(&c1);
|
|
||||||
// let is_lt = ck.decrypt(&c_lt);
|
|
||||||
// assert_eq!(
|
|
||||||
// is_lt,
|
|
||||||
// i < j,
|
|
||||||
// "Expected {} but got {is_lt} for {i}<{j}",
|
|
||||||
// i < j
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// {
|
|
||||||
// let c_ge = c0.ge(&c1);
|
|
||||||
// let is_ge = ck.decrypt(&c_ge);
|
|
||||||
// assert_eq!(
|
|
||||||
// is_ge,
|
|
||||||
// i >= j,
|
|
||||||
// "Expected {} but got {is_ge} for {i}>={j}",
|
|
||||||
// i >= j
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// {
|
|
||||||
// let c_le = c0.le(&c1);
|
|
||||||
// let is_le = ck.decrypt(&c_le);
|
|
||||||
// assert_eq!(
|
|
||||||
// is_le,
|
|
||||||
// i <= j,
|
|
||||||
// "Expected {} but got {is_le} for {i}<={j}",
|
|
||||||
// i <= j
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user