arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
phantom-zone/src/bool/print_noise.rs
src/bool/print_noise.rsRaw
   1use std::{fmt::Debug, iter::Sum, thread::panicking};
   2
   3use itertools::izip;
   4use num_traits::{FromPrimitive, Pow, PrimInt, Zero};
   5use rand_distr::uniform::SampleUniform;
   6
   7use crate::{
   8    backend::{GetModulus, Modulus},
   9    decomposer::RlweDecomposer,
  10    lwe::{decrypt_lwe, lwe_key_switch},
  11    parameters::{self, BoolParameters, CiphertextModulus},
  12    pbs::PbsKey,
  13    random::{DefaultSecureRng, RandomFillUniformInModulus},
  14    rgsw::{decrypt_rlwe, galois_auto, IsTrivial, RlweCiphertext},
  15    utils::{encode_x_pow_si_with_emebedding_factor, tests::Stats, TryConvertFrom1, WithLocal},
  16    ArithmeticOps, ClientKey, Decomposer, DefaultDecomposer, MatrixEntity, MatrixMut, ModInit, Ntt,
  17    NttInit, RowEntity, RowMut, VectorOps,
  18};
  19
  20use super::{
  21    keys::{
  22        tests::{ideal_sk_lwe, ideal_sk_rlwe},
  23        SeededMultiPartyServerKey, ServerKeyEvaluationDomain,
  24    },
  25    BoolEvaluator,
  26};
  27
  28struct ServerKeyStats<T> {
  29    brk_rgsw_cts: (Stats<T>, Stats<T>),
  30    post_1_auto: Stats<T>,
  31    post_lwe_key_switch: Stats<T>,
  32}
  33
  34impl<T: PrimInt + FromPrimitive + Debug + Sum> ServerKeyStats<T>
  35where
  36    T: for<'a> Sum<&'a T>,
  37{
  38    fn new() -> Self {
  39        ServerKeyStats {
  40            brk_rgsw_cts: (Stats::default(), Stats::default()),
  41            post_1_auto: Stats::default(),
  42            post_lwe_key_switch: Stats::default(),
  43        }
  44    }
  45
  46    fn add_noise_brk_rgsw_cts_nsm(&mut self, noise: &[T]) {
  47        self.brk_rgsw_cts.0.add_more(noise);
  48    }
  49
  50    fn add_noise_brk_rgsw_cts_m(&mut self, noise: &[T]) {
  51        self.brk_rgsw_cts.1.add_more(noise);
  52    }
  53
  54    fn add_noise_post_1_auto(&mut self, noise: &[T]) {
  55        self.post_1_auto.add_more(&noise);
  56    }
  57
  58    fn add_noise_post_kwe_key_switch(&mut self, noise: &[T]) {
  59        self.post_lwe_key_switch.add_more(&noise);
  60    }
  61}
  62
  63fn collect_server_key_stats<
  64    M: MatrixEntity + MatrixMut,
  65    D: Decomposer<Element = M::MatElement>,
  66    NttOp: NttInit<CiphertextModulus<M::MatElement>> + Ntt<Element = M::MatElement>,
  67    ModOp: VectorOps<Element = M::MatElement>
  68        + ArithmeticOps<Element = M::MatElement>
  69        + ModInit<M = CiphertextModulus<M::MatElement>>
  70        + GetModulus<M = CiphertextModulus<M::MatElement>, Element = M::MatElement>,
  71>(
  72    parameters: BoolParameters<M::MatElement>,
  73    client_keys: &[ClientKey],
  74    server_key: &ServerKeyEvaluationDomain<M, BoolParameters<u64>, DefaultSecureRng, NttOp>,
  75) -> ServerKeyStats<i64>
  76where
  77    M::R: RowMut + RowEntity + TryConvertFrom1<[i32], CiphertextModulus<M::MatElement>> + Clone,
  78    M::MatElement: Copy + PrimInt + FromPrimitive + SampleUniform + Zero + Debug,
  79{
  80    let ideal_sk_rlwe = ideal_sk_rlwe(client_keys);
  81    let ideal_sk_lwe = ideal_sk_lwe(client_keys);
  82
  83    let embedding_factor = (2 * parameters.rlwe_n().0) / parameters.br_q();
  84    let rlwe_n = parameters.rlwe_n().0;
  85    let rlwe_q = parameters.rlwe_q();
  86    let lwe_q = parameters.lwe_q();
  87    let rlwe_modop = ModOp::new(rlwe_q.clone());
  88    let rlwe_nttop = NttOp::new(rlwe_q, rlwe_n);
  89    let lwe_modop = ModOp::new(*parameters.lwe_q());
  90
  91    let rlwe_x_rgsw_decomposer = parameters.rlwe_rgsw_decomposer::<D>();
  92    let (rlwe_x_rgsw_gadget_a, rlwe_x_rgsw_gadget_b) = (
  93        rlwe_x_rgsw_decomposer.a().gadget_vector(),
  94        rlwe_x_rgsw_decomposer.b().gadget_vector(),
  95    );
  96
  97    let lwe_ks_decomposer = parameters.lwe_decomposer::<D>();
  98
  99    let mut server_key_stats = ServerKeyStats::new();
 100
 101    let mut rng = DefaultSecureRng::new();
 102
 103    // RGSW ciphertext noise
 104    // Check noise in RGSW ciphertexts of ideal LWE secret elements
 105    {
 106        izip!(ideal_sk_lwe.iter(), server_key.rgsw_cts().iter()).for_each(|(s_i, rgsw_ct_i)| {
 107            // X^{s[i]}
 108            let m_si = encode_x_pow_si_with_emebedding_factor::<M::R, _>(
 109                *s_i,
 110                embedding_factor,
 111                rlwe_n,
 112                rlwe_q,
 113            );
 114
 115            // RLWE'(-sm)
 116            let mut neg_s_eval = M::R::try_convert_from(ideal_sk_rlwe.as_slice(), rlwe_q);
 117            rlwe_modop.elwise_neg_mut(neg_s_eval.as_mut());
 118            rlwe_nttop.forward(neg_s_eval.as_mut());
 119
 120            for j in 0..rlwe_x_rgsw_decomposer.a().decomposition_count() {
 121                // RLWE(B^{j} * -s[X]*X^{s_lwe[i]})
 122
 123                // -s[X]*X^{s_lwe[i]}*B_j
 124                let mut m_ideal = m_si.clone();
 125                rlwe_nttop.forward(m_ideal.as_mut());
 126                rlwe_modop.elwise_mul_mut(m_ideal.as_mut(), neg_s_eval.as_ref());
 127                rlwe_nttop.backward(m_ideal.as_mut());
 128                rlwe_modop.elwise_scalar_mul_mut(m_ideal.as_mut(), &rlwe_x_rgsw_gadget_a[j]);
 129
 130                // RLWE(-s*X^{s_lwe[i]}*B_j)
 131                let mut rlwe_ct = M::zeros(2, rlwe_n);
 132                rlwe_ct
 133                    .get_row_mut(0)
 134                    .copy_from_slice(rgsw_ct_i.get_row_slice(j));
 135                rlwe_ct.get_row_mut(1).copy_from_slice(
 136                    rgsw_ct_i.get_row_slice(j + rlwe_x_rgsw_decomposer.a().decomposition_count()),
 137                );
 138                // RGSW ciphertexts are in eval domain. We put RLWE ciphertexts back in
 139                // coefficient domain
 140                rlwe_ct
 141                    .iter_rows_mut()
 142                    .for_each(|r| rlwe_nttop.backward(r.as_mut()));
 143
 144                let mut m_back = M::R::zeros(rlwe_n);
 145                decrypt_rlwe(
 146                    &rlwe_ct,
 147                    &ideal_sk_rlwe,
 148                    &mut m_back,
 149                    &rlwe_nttop,
 150                    &rlwe_modop,
 151                );
 152
 153                // diff
 154                rlwe_modop.elwise_sub_mut(m_back.as_mut(), m_ideal.as_ref());
 155                server_key_stats.add_noise_brk_rgsw_cts_nsm(&Vec::<i64>::try_convert_from(
 156                    m_back.as_ref(),
 157                    rlwe_q,
 158                ));
 159            }
 160
 161            // RLWE'(m)
 162            for j in 0..rlwe_x_rgsw_decomposer.b().decomposition_count() {
 163                // RLWE(B^{j} * X^{s_lwe[i]})
 164
 165                // X^{s_lwe[i]}*B_j
 166                let mut m_ideal = m_si.clone();
 167                rlwe_modop.elwise_scalar_mul_mut(m_ideal.as_mut(), &rlwe_x_rgsw_gadget_b[j]);
 168
 169                // RLWE(X^{s_lwe[i]}*B_j)
 170                let mut rlwe_ct = M::zeros(2, rlwe_n);
 171                rlwe_ct.get_row_mut(0).copy_from_slice(
 172                    rgsw_ct_i
 173                        .get_row_slice(j + (2 * rlwe_x_rgsw_decomposer.a().decomposition_count())),
 174                );
 175                rlwe_ct
 176                    .get_row_mut(1)
 177                    .copy_from_slice(rgsw_ct_i.get_row_slice(
 178                        j + (2 * rlwe_x_rgsw_decomposer.a().decomposition_count())
 179                            + rlwe_x_rgsw_decomposer.b().decomposition_count(),
 180                    ));
 181                rlwe_ct
 182                    .iter_rows_mut()
 183                    .for_each(|r| rlwe_nttop.backward(r.as_mut()));
 184
 185                let mut m_back = M::R::zeros(rlwe_n);
 186                decrypt_rlwe(
 187                    &rlwe_ct,
 188                    &ideal_sk_rlwe,
 189                    &mut m_back,
 190                    &rlwe_nttop,
 191                    &rlwe_modop,
 192                );
 193
 194                // diff
 195                rlwe_modop.elwise_sub_mut(m_back.as_mut(), m_ideal.as_ref());
 196                server_key_stats.add_noise_brk_rgsw_cts_m(&Vec::<i64>::try_convert_from(
 197                    m_back.as_ref(),
 198                    rlwe_q,
 199                ));
 200            }
 201        });
 202    }
 203
 204    // Noise in ciphertext after 1 auto
 205    // For each auto key g^k. Sample random polynomial m(X) and multiply with
 206    // -s(X^{g^k}) using key corresponding to auto g^k. Then check the noise in
 207    // resutling RLWE(m(X) * -s(X^{g^k}))
 208    {
 209        let neg_s = {
 210            let mut s = M::R::try_convert_from(ideal_sk_rlwe.as_slice(), rlwe_q);
 211            rlwe_modop.elwise_neg_mut(s.as_mut());
 212            s
 213        };
 214        let g = parameters.g();
 215        let br_q = parameters.br_q();
 216        let g_dlogs = parameters.auto_element_dlogs();
 217        let auto_decomposer = parameters.auto_decomposer::<D>();
 218        let mut scratch_matrix = M::zeros(auto_decomposer.decomposition_count() + 2, rlwe_n);
 219
 220        g_dlogs.iter().for_each(|k| {
 221            let g_pow_k = if *k == 0 {
 222                -(g as isize)
 223            } else {
 224                (g.pow(*k as u32) % br_q) as isize
 225            };
 226
 227            // Send s(X) -> s(X^{g^k})
 228            let (auto_index_map, auto_sign_map) = crate::rgsw::generate_auto_map(rlwe_n, g_pow_k);
 229            let mut neg_s_g_k = M::R::zeros(rlwe_n);
 230            izip!(
 231                neg_s.as_ref().iter(),
 232                auto_index_map.iter(),
 233                auto_sign_map.iter()
 234            )
 235            .for_each(|(el, to_index, to_sign)| {
 236                if !to_sign {
 237                    neg_s_g_k.as_mut()[*to_index] = rlwe_modop.neg(el);
 238                } else {
 239                    neg_s_g_k.as_mut()[*to_index] = *el;
 240                }
 241            });
 242
 243            let mut m = M::R::zeros(rlwe_n);
 244            RandomFillUniformInModulus::random_fill(&mut rng, rlwe_q, m.as_mut());
 245
 246            // We want -m(X^{g^k})s(X^{g^k}) after key switch
 247            let want_m = {
 248                let mut m_g_k_eval = M::R::zeros(rlwe_n);
 249                // send m(X) -> m(X^{g^k})
 250                izip!(
 251                    m.as_ref().iter(),
 252                    auto_index_map.iter(),
 253                    auto_sign_map.iter()
 254                )
 255                .for_each(|(el, to_index, to_sign)| {
 256                    if !to_sign {
 257                        m_g_k_eval.as_mut()[*to_index] = rlwe_modop.neg(el);
 258                    } else {
 259                        m_g_k_eval.as_mut()[*to_index] = *el;
 260                    }
 261                });
 262
 263                rlwe_nttop.forward(m_g_k_eval.as_mut());
 264                let mut s_g_k = neg_s_g_k.clone();
 265                rlwe_nttop.forward(s_g_k.as_mut());
 266                rlwe_modop.elwise_mul_mut(m_g_k_eval.as_mut(), s_g_k.as_ref());
 267                rlwe_nttop.backward(m_g_k_eval.as_mut());
 268                m_g_k_eval
 269            };
 270
 271            // RLWE auto sends part A, A(X), of RLWE to A(X^{g^k}) and then multiplies it
 272            // with -s(X^{g^k}) using auto key. Deliberately set RLWE = (0, m(X))
 273            // (ie. m in part A) to get back RLWE(-m(X^{g^k})s(X^{g^k}))
 274            let mut rlwe = RlweCiphertext::<_, DefaultSecureRng>::new_trivial(M::zeros(2, rlwe_n));
 275            rlwe.data.get_row_mut(0).copy_from_slice(m.as_ref());
 276            rlwe.set_not_trivial();
 277
 278            galois_auto(
 279                &mut rlwe,
 280                server_key.galois_key_for_auto(*k),
 281                &mut scratch_matrix,
 282                &auto_index_map,
 283                &auto_sign_map,
 284                &rlwe_modop,
 285                &rlwe_nttop,
 286                &auto_decomposer,
 287            );
 288
 289            // decrypt RLWE(-m(X)s(X^{g^k]}))
 290            let mut back_m = M::R::zeros(rlwe_n);
 291            decrypt_rlwe(&rlwe, &ideal_sk_rlwe, &mut back_m, &rlwe_nttop, &rlwe_modop);
 292
 293            // check difference
 294            let mut diff = back_m;
 295            rlwe_modop.elwise_sub_mut(diff.as_mut(), want_m.as_ref());
 296            server_key_stats
 297                .add_noise_post_1_auto(&Vec::<i64>::try_convert_from(diff.as_ref(), rlwe_q));
 298        });
 299
 300        // sample random m
 301
 302        // key switch
 303    }
 304
 305    // LWE Key switch
 306    // LWE key switches LWE_in = LWE_{Q_ks,N, s}(m) = (b, a_0, ... a_N) -> LWE_out =
 307    // LWE_{Q_{ks}, n, z}(m) = (b', a'_0, ..., a'n)
 308    // If LWE_in = (0, a = {a_0, ..., a_N}), then LWE_out = LWE(-a \cdot s_{rlwe})
 309    for _ in 0..1000 {
 310        let mut lwe_in = M::R::zeros(rlwe_n + 1);
 311        RandomFillUniformInModulus::random_fill(&mut rng, lwe_q, &mut lwe_in.as_mut()[1..]);
 312
 313        // Key switch
 314        let mut lwe_out = M::R::zeros(parameters.lwe_n().0 + 1);
 315        lwe_key_switch(
 316            &mut lwe_out,
 317            &lwe_in,
 318            server_key.lwe_ksk(),
 319            &lwe_modop,
 320            &lwe_ks_decomposer,
 321        );
 322
 323        // -a \cdot s
 324        let mut want_m = M::MatElement::zero();
 325        izip!(lwe_in.as_ref().iter().skip(1), ideal_sk_rlwe.iter()).for_each(|(a, b)| {
 326            want_m = lwe_modop.add(
 327                &want_m,
 328                &lwe_modop.mul(a, &lwe_q.map_element_from_i64(*b as i64)),
 329            );
 330        });
 331        want_m = lwe_modop.neg(&want_m);
 332
 333        // decrypt lwe out
 334        let back_m = decrypt_lwe(&lwe_out, &ideal_sk_lwe, &lwe_modop);
 335
 336        let noise = lwe_modop.sub(&want_m, &back_m);
 337        server_key_stats.add_noise_post_kwe_key_switch(&vec![lwe_q.map_element_to_i64(&noise)]);
 338    }
 339
 340    server_key_stats
 341    // Auto keys noise
 342
 343    // Ksk noise
 344}
 345
 346#[cfg(test)]
 347mod tests {
 348    use itertools::Itertools;
 349
 350    use crate::{
 351        aggregate_public_key_shares, aggregate_server_key_shares,
 352        bool::keys::ServerKeyEvaluationDomain,
 353        evaluator::MultiPartyCrs,
 354        gen_client_key, gen_mp_keys_phase1, gen_mp_keys_phase2,
 355        parameters::{BoolParameters, CiphertextModulus},
 356        random::DefaultSecureRng,
 357        set_mp_seed, set_parameter_set,
 358        utils::WithLocal,
 359        BoolEvaluator, DefaultDecomposer, ModularOpsU64, Ntt, NttBackendU64,
 360    };
 361
 362    use super::collect_server_key_stats;
 363
 364    #[test]
 365    fn qwerty() {
 366        set_parameter_set(crate::ParameterSelector::HighCommunicationButFast2Party);
 367        set_mp_seed(MultiPartyCrs::random().seed);
 368        let parties = 2;
 369        let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
 370        let pk_shares = cks.iter().map(|k| gen_mp_keys_phase1(k)).collect_vec();
 371        let pk = aggregate_public_key_shares(&pk_shares);
 372        let server_key_shares = cks
 373            .iter()
 374            .enumerate()
 375            .map(|(index, k)| gen_mp_keys_phase2(k, index, parties, &pk))
 376            .collect_vec();
 377        let seeded_server_key = aggregate_server_key_shares(&server_key_shares);
 378        let server_key_eval =
 379            ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(
 380                &seeded_server_key,
 381            );
 382
 383        let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
 384        let server_key_stats = collect_server_key_stats::<
 385            _,
 386            DefaultDecomposer<u64>,
 387            NttBackendU64,
 388            ModularOpsU64<CiphertextModulus<u64>>,
 389        >(parameters, &cks, &server_key_eval);
 390
 391        println!(
 392            "Rgsw nsm std log2 {}",
 393            server_key_stats.brk_rgsw_cts.0.std_dev().abs().log2()
 394        );
 395        println!(
 396            "Rgsw m std log2 {}",
 397            server_key_stats.brk_rgsw_cts.1.std_dev().abs().log2()
 398        );
 399        println!(
 400            "rlwe post 1 auto std log2 {}",
 401            server_key_stats.post_1_auto.std_dev().abs().log2()
 402        );
 403        println!(
 404            "key switching noise rlwe secret s to lwe secret z std log2 {}",
 405            server_key_stats.post_lwe_key_switch.std_dev().abs().log2()
 406        );
 407    }
 408}
 409
 410//     #[test]
 411//     fn noise_tester() {
 412//         let bool_evaluator = BoolEvaluator::<
 413//             Vec<Vec<u64>>,
 414//             NttBackendU64,
 415//             ModularOpsU64<CiphertextModulus<u64>>,
 416//             ModularOpsU64<CiphertextModulus<u64>>,
 417//             ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
 418//         >::new(OPTIMISED_SMALL_MP_BOOL_PARAMS);
 419
 420//         // let (_, collective_pk, _, _, server_key_eval, ideal_client_key) =
 421//         //     _multi_party_all_keygen(&bool_evaluator, 20);
 422//         let no_of_parties = 2;
 423//         let lwe_q = bool_evaluator.pbs_info.parameters.lwe_q();
 424//         let rlwe_q = bool_evaluator.pbs_info.parameters.rlwe_q();
 425//         let lwe_n = bool_evaluator.pbs_info.parameters.lwe_n().0;
 426//         let rlwe_n = bool_evaluator.pbs_info.parameters.rlwe_n().0;
 427//         let lwe_modop = &bool_evaluator.pbs_info.lwe_modop;
 428//         let rlwe_nttop = &bool_evaluator.pbs_info.rlwe_nttop;
 429//         let rlwe_modop = &bool_evaluator.pbs_info.rlwe_modop;
 430
 431//         // let rgsw_rgsw_decomposer = &bool_evaluator
 432//         //     .pbs_info
 433//         //     .parameters
 434//         //     .rgsw_rgsw_decomposer::<DefaultDecomposer<u64>>();
 435//         // let rgsw_rgsw_gadget_a = rgsw_rgsw_decomposer.0.gadget_vector();
 436//         // let rgsw_rgsw_gadget_b = rgsw_rgsw_decomposer.1.gadget_vector();
 437
 438//         let rlwe_rgsw_decomposer =
 439// &bool_evaluator.pbs_info.rlwe_rgsw_decomposer;         let rlwe_rgsw_gadget_a
 440// = rlwe_rgsw_decomposer.0.gadget_vector();         let rlwe_rgsw_gadget_b =
 441// rlwe_rgsw_decomposer.1.gadget_vector();
 442
 443//         let auto_decomposer = &bool_evaluator.pbs_info.auto_decomposer;
 444//         let auto_gadget = auto_decomposer.gadget_vector();
 445
 446//         let parties = (0..no_of_parties)
 447//             .map(|_| bool_evaluator.client_key())
 448//             .collect_vec();
 449
 450//         let int_mp_seed = MultiPartyCrs::random();
 451
 452//         let mut ideal_rlwe_sk = vec![0i32; bool_evaluator.pbs_info.rlwe_n()];
 453//         parties.iter().for_each(|k| {
 454//             izip!(
 455//                 ideal_rlwe_sk.iter_mut(),
 456//                 InteractiveMultiPartyClientKey::sk_rlwe(k).iter()
 457//             )
 458//             .for_each(|(ideal_i, s_i)| {
 459//                 *ideal_i = *ideal_i + s_i;
 460//             });
 461//         });
 462//         let mut ideal_lwe_sk = vec![0i32; bool_evaluator.pbs_info.lwe_n()];
 463//         parties.iter().for_each(|k| {
 464//             izip!(
 465//                 ideal_lwe_sk.iter_mut(),
 466//                 InteractiveMultiPartyClientKey::sk_lwe(k).iter()
 467//             )
 468//             .for_each(|(ideal_i, s_i)| {
 469//                 *ideal_i = *ideal_i + s_i;
 470//             });
 471//         });
 472
 473//         let mut rng = DefaultSecureRng::new();
 474
 475//         // check noise in freshly encrypted RLWE ciphertext (ie var_fresh)
 476//         if false {
 477//             let mut rng = DefaultSecureRng::new();
 478//             let mut check = Stats { samples: vec![] };
 479//             for _ in 0..10 {
 480//                 // generate a new collective public key
 481//                 let mut pk_cr_seed = [0u8; 32];
 482//                 rng.fill_bytes(&mut pk_cr_seed);
 483//                 let public_key_share = parties
 484//                     .iter()
 485//                     .map(|k|
 486// bool_evaluator.multi_party_public_key_share(&int_mp_seed, k))
 487// .collect_vec();                 let collective_pk = PublicKey::<
 488//                     Vec<Vec<u64>>,
 489//                     DefaultSecureRng,
 490//                     ModularOpsU64<CiphertextModulus<u64>>,
 491//                 >::from(public_key_share.as_slice());
 492
 493//                 let mut m = vec![0u64; rlwe_n];
 494//                 RandomFillUniformInModulus::random_fill(&mut rng, rlwe_q,
 495// m.as_mut_slice());                 let mut rlwe_ct = vec![vec![0u64; rlwe_n];
 496// 2];                 public_key_encrypt_rlwe::<_, _, _, _, i32, _>(
 497//                     &mut rlwe_ct,
 498//                     collective_pk.key(),
 499//                     &m,
 500//                     rlwe_modop,
 501//                     rlwe_nttop,
 502//                     &mut rng,
 503//                 );
 504
 505//                 let mut m_back = vec![0u64; rlwe_n];
 506//                 decrypt_rlwe(
 507//                     &rlwe_ct,
 508//                     &ideal_rlwe_sk,
 509//                     &mut m_back,
 510//                     rlwe_nttop,
 511//                     rlwe_modop,
 512//                 );
 513
 514//                 rlwe_modop.elwise_sub_mut(m_back.as_mut_slice(),
 515// m.as_slice());
 516
 517//                 check.add_more(Vec::<i64>::try_convert_from(&m_back,
 518// rlwe_q).as_slice());             }
 519
 520//             println!("Public key Std: {}", check.std_dev().abs().log2());
 521//         }
 522
 523//         if true {
 524//             // Generate server key shares
 525//             let public_key_share = parties
 526//                 .iter()
 527//                 .map(|k|
 528// bool_evaluator.multi_party_public_key_share(&int_mp_seed, k))
 529// .collect_vec();             let collective_pk = PublicKey::<
 530//                 Vec<Vec<u64>>,
 531//                 DefaultSecureRng,
 532//                 ModularOpsU64<CiphertextModulus<u64>>,
 533//             >::from(public_key_share.as_slice());
 534
 535//             let server_key_shares = parties
 536//                 .iter()
 537//                 .enumerate()
 538//                 .map(|(user_id, k)| {
 539//                     bool_evaluator.multi_party_server_key_share(
 540//                         user_id,
 541//                         no_of_parties,
 542//                         &int_mp_seed,
 543//                         collective_pk.key(),
 544//                         k,
 545//                     )
 546//                 })
 547//                 .collect_vec();
 548
 549//             let seeded_server_key =
 550//
 551// bool_evaluator.aggregate_multi_party_server_key_shares(&server_key_shares);
 552//         }
 553
 554//         // server key in Evaluation domain
 555//         let runtime_server_key =
 556//             ShoupServerKeyEvaluationDomain::from(ServerKeyEvaluationDomain::<
 557//                 _,
 558//                 _,
 559//                 DefaultSecureRng,
 560//                 NttBackendU64,
 561//             >::from(&seeded_server_key));
 562
 563//         // check noise in RLWE x RGSW(X^{s_i}) where RGSW is accunulated RGSW
 564// ciphertext         if false {
 565//             let mut check = Stats { samples: vec![] };
 566
 567//             ideal_lwe_sk.iter().enumerate().for_each(|(index, s_i)| {
 568//                 let rgsw_ct_i =
 569// runtime_server_key.rgsw_ct_lwe_si(index).as_ref();
 570
 571//                 let mut m = vec![0u64; rlwe_n];
 572//                 RandomFillUniformInModulus::random_fill(&mut rng, rlwe_q,
 573// m.as_mut_slice());                 let mut rlwe_ct = vec![vec![0u64; rlwe_n];
 574// 2];                 public_key_encrypt_rlwe::<_, _, _, _, i32, _>(
 575//                     &mut rlwe_ct,
 576//                     collective_pk.key(),
 577//                     &m,
 578//                     rlwe_modop,
 579//                     rlwe_nttop,
 580//                     &mut rng,
 581//                 );
 582
 583//                 let mut rlwe_after = RlweCiphertext::<_, DefaultSecureRng> {
 584//                     data: rlwe_ct.clone(),
 585//                     is_trivial: false,
 586//                     _phatom: PhantomData,
 587//                 };
 588//                 let mut scratch = vec![
 589//                     vec![0u64; rlwe_n];
 590//                     std::cmp::max(
 591//                         rlwe_rgsw_decomposer.0.decomposition_count(),
 592//                         rlwe_rgsw_decomposer.1.decomposition_count()
 593//                     ) + 2
 594//                 ];
 595//                 rlwe_by_rgsw(
 596//                     &mut rlwe_after,
 597//                     rgsw_ct_i,
 598//                     &mut scratch,
 599//                     rlwe_rgsw_decomposer,
 600//                     rlwe_nttop,
 601//                     rlwe_modop,
 602//                 );
 603
 604//                 // m1 = X^{s[i]}
 605//                 let mut m1 = vec![0u64; rlwe_n];
 606//                 let s_i = *s_i * (bool_evaluator.pbs_info.embedding_factor as
 607// i32);                 if s_i < 0 {
 608//                     m1[rlwe_n - (s_i.abs() as usize)] = rlwe_q.neg_one()
 609//                 } else {
 610//                     m1[s_i as usize] = 1;
 611//                 }
 612
 613//                 // (m+e) * m1
 614//                 let mut m_plus_e_times_m1 = vec![0u64; rlwe_n];
 615//                 decrypt_rlwe(
 616//                     &rlwe_ct,
 617//                     &ideal_rlwe_sk,
 618//                     &mut m_plus_e_times_m1,
 619//                     rlwe_nttop,
 620//                     rlwe_modop,
 621//                 );
 622//                 rlwe_nttop.forward(m_plus_e_times_m1.as_mut_slice());
 623//                 rlwe_nttop.forward(m1.as_mut_slice());
 624
 625//                 rlwe_modop.elwise_mul_mut(m_plus_e_times_m1.as_mut_slice(),
 626// m1.as_slice());
 627// rlwe_nttop.backward(m_plus_e_times_m1.as_mut_slice());
 628
 629//                 // Resulting RLWE ciphertext will equal: (m0m1 + em1) +
 630// e_{rlsw x rgsw}.                 // Hence, resulting rlwe ciphertext will
 631// have error em1 + e_{rlwe x rgsw}.                 // Here we're only
 632// concerned with e_{rlwe x rgsw}, that is noise added by                 //
 633// RLWExRGSW. Also note in practice m1 is a monomial, for ex, X^{s_{i}}, for
 634//                 // some i and var(em1) = var(e).
 635//                 let mut m_plus_e_times_m1_more_e = vec![0u64; rlwe_n];
 636//                 decrypt_rlwe(
 637//                     &rlwe_after,
 638//                     &ideal_rlwe_sk,
 639//                     &mut m_plus_e_times_m1_more_e,
 640//                     rlwe_nttop,
 641//                     rlwe_modop,
 642//                 );
 643
 644//                 // diff
 645//                 rlwe_modop.elwise_sub_mut(
 646//                     m_plus_e_times_m1_more_e.as_mut_slice(),
 647//                     m_plus_e_times_m1.as_slice(),
 648//                 );
 649
 650//                 // let noise = measure_noise(
 651//                 //     &rlwe_after,
 652//                 //     &m_plus_e_times_m1,
 653//                 //     rlwe_nttop,
 654//                 //     rlwe_modop,
 655//                 //     ideal_client_key.sk_rlwe.values(),
 656//                 // );
 657//                 // print!("NOISE: {}", noise);
 658
 659//                 check.add_more(&Vec::<i64>::try_convert_from(
 660//                     &m_plus_e_times_m1_more_e,
 661//                     rlwe_q,
 662//                 ));
 663//             });
 664//             println!(
 665//                 "RLWE x RGSW, where RGSW has noise var_brk, std: {} {}",
 666//                 check.std_dev(),
 667//                 check.std_dev().abs().log2()
 668//             )
 669//         }
 670
 671//         // check noise in Auto key
 672//         if false {
 673//             let mut check = Stats { samples: vec![] };
 674
 675//             let mut neg_s_poly =
 676// Vec::<u64>::try_convert_from(ideal_rlwe_sk.as_slice(), rlwe_q);
 677// rlwe_modop.elwise_neg_mut(neg_s_poly.as_mut_slice());
 678
 679//             let g = bool_evaluator.pbs_info.g();
 680//             let br_q = bool_evaluator.pbs_info.br_q();
 681//             let auto_element_dlogs =
 682// bool_evaluator.pbs_info.parameters.auto_element_dlogs();             for i in
 683// auto_element_dlogs.into_iter() {                 let g_pow = if i == 0 {
 684//                     -g
 685//                 } else {
 686//                     (((g as usize).pow(i as u32)) % br_q) as isize
 687//                 };
 688
 689//                 // -s[X^k]
 690//                 let (auto_indices, auto_sign) = generate_auto_map(rlwe_n,
 691// g_pow);                 let mut neg_s_poly_auto_i = vec![0u64; rlwe_n];
 692//                 izip!(neg_s_poly.iter(), auto_indices.iter(),
 693// auto_sign.iter()).for_each(                     |(v, to_i, to_sign)| {
 694//                         if !to_sign {
 695//                             neg_s_poly_auto_i[*to_i] = rlwe_modop.neg(v);
 696//                         } else {
 697//                             neg_s_poly_auto_i[*to_i] = *v;
 698//                         }
 699//                     },
 700//                 );
 701
 702//                 let mut auto_key_i =
 703// runtime_server_key.galois_key_for_auto(i).as_ref().clone(); //send i^th auto
 704// key to coefficient domain                 auto_key_i
 705//                     .iter_mut()
 706//                     .for_each(|r| rlwe_nttop.backward(r.as_mut_slice()));
 707//                 auto_gadget.iter().enumerate().for_each(|(i, b_i)| {
 708//                     // B^i * -s[X^k]
 709//                     let mut m_ideal = neg_s_poly_auto_i.clone();
 710
 711//                     rlwe_modop.elwise_scalar_mul_mut(m_ideal.as_mut_slice(),
 712// b_i);
 713
 714//                     let mut m_out = vec![0u64; rlwe_n];
 715//                     let mut rlwe_ct = vec![vec![0u64; rlwe_n]; 2];
 716//                     rlwe_ct[0].copy_from_slice(&auto_key_i[i]);
 717//                     rlwe_ct[1]
 718//
 719// .copy_from_slice(&auto_key_i[auto_decomposer.decomposition_count() + i]);
 720//                     decrypt_rlwe(&rlwe_ct, &ideal_rlwe_sk, &mut m_out,
 721// rlwe_nttop, rlwe_modop);
 722
 723//                     // diff
 724//                     rlwe_modop.elwise_sub_mut(m_out.as_mut_slice(),
 725// m_ideal.as_slice());
 726
 727//                     check.add_more(&Vec::<i64>::try_convert_from(&m_out,
 728// rlwe_q));                 });
 729//             }
 730
 731//             println!("Auto key noise std dev: {}",
 732// check.std_dev().abs().log2());         }
 733
 734//         // check noise in RLWE(X^k) after sending RLWE(X) -> RLWE(X^k)using
 735// collective         // auto key
 736//         if false {
 737//             let mut check = Stats { samples: vec![] };
 738//             let br_q = bool_evaluator.pbs_info.br_q();
 739//             let g = bool_evaluator.pbs_info.g();
 740//             let auto_element_dlogs =
 741// bool_evaluator.pbs_info.parameters.auto_element_dlogs();             for i in
 742// auto_element_dlogs.into_iter() {                 for _ in 0..10 {
 743//                     let mut m = vec![0u64; rlwe_n];
 744//                     RandomFillUniformInModulus::random_fill(&mut rng, rlwe_q,
 745// m.as_mut_slice());                     let mut rlwe_ct = RlweCiphertext::<_,
 746// DefaultSecureRng> {                         data: vec![vec![0u64; rlwe_n];
 747// 2],                         is_trivial: false,
 748//                         _phatom: PhantomData,
 749//                     };
 750//                     public_key_encrypt_rlwe::<_, _, _, _, i32, _>(
 751//                         &mut rlwe_ct,
 752//                         collective_pk.key(),
 753//                         &m,
 754//                         rlwe_modop,
 755//                         rlwe_nttop,
 756//                         &mut rng,
 757//                     );
 758
 759//                     // We're only interested in noise increased as a result
 760// of automorphism.                     // Hence, we take m+e as the bench.
 761//                     let mut m_plus_e = vec![0u64; rlwe_n];
 762//                     decrypt_rlwe(
 763//                         &rlwe_ct,
 764//                         &ideal_rlwe_sk,
 765//                         &mut m_plus_e,
 766//                         rlwe_nttop,
 767//                         rlwe_modop,
 768//                     );
 769
 770//                     let auto_key =
 771// runtime_server_key.galois_key_for_auto(i).as_ref();                     let
 772// (auto_map_index, auto_map_sign) = bool_evaluator.pbs_info.rlwe_auto_map(i);
 773//                     let mut scratch =
 774//                         vec![vec![0u64; rlwe_n];
 775// auto_decomposer.decomposition_count() + 2];                     galois_auto(
 776//                         &mut rlwe_ct,
 777//                         auto_key,
 778//                         &mut scratch,
 779//                         &auto_map_index,
 780//                         &auto_map_sign,
 781//                         rlwe_modop,
 782//                         rlwe_nttop,
 783//                         auto_decomposer,
 784//                     );
 785
 786//                     // send m+e from X to X^k
 787//                     let mut m_plus_e_auto = vec![0u64; rlwe_n];
 788//                     izip!(m_plus_e.iter(), auto_map_index.iter(),
 789// auto_map_sign.iter()).for_each(                         |(v, to_index,
 790// to_sign)| {                             if !to_sign {
 791//                                 m_plus_e_auto[*to_index] = rlwe_modop.neg(v);
 792//                             } else {
 793//                                 m_plus_e_auto[*to_index] = *v
 794//                             }
 795//                         },
 796//                     );
 797
 798//                     let mut m_out = vec![0u64; rlwe_n];
 799//                     decrypt_rlwe(&rlwe_ct, &ideal_rlwe_sk, &mut m_out,
 800// rlwe_nttop, rlwe_modop);
 801
 802//                     // diff
 803//                     rlwe_modop.elwise_sub_mut(m_out.as_mut_slice(),
 804// m_plus_e_auto.as_slice());
 805
 806//
 807// check.add_more(&Vec::<i64>::try_convert_from(m_out.as_slice(), rlwe_q));
 808//                 }
 809//             }
 810
 811//             println!("Rlwe Auto Noise Std: {}",
 812// check.std_dev().abs().log2());         }
 813
 814//         // Check noise growth in ksk
 815//         // TODO check in LWE key switching keys
 816//         if false {
 817//             // 1. encrypt LWE ciphertext
 818//             // 2. Key switching
 819//             // 3.
 820//             let mut check = Stats { samples: vec![] };
 821
 822//             for _ in 0..1024 {
 823//                 // Encrypt m \in Q_{ks} using RLWE sk
 824//                 let mut lwe_in_ct = vec![0u64; rlwe_n + 1];
 825//                 let m = RandomElementInModulus::random(&mut rng,
 826// &lwe_q.q().unwrap());                 encrypt_lwe(&mut lwe_in_ct, &m,
 827// &ideal_rlwe_sk, lwe_modop, &mut rng);
 828
 829//                 // Key switch
 830//                 let mut lwe_out = vec![0u64; lwe_n + 1];
 831//                 lwe_key_switch(
 832//                     &mut lwe_out,
 833//                     &lwe_in_ct,
 834//                     runtime_server_key.lwe_ksk(),
 835//                     lwe_modop,
 836//                     bool_evaluator.pbs_info.lwe_decomposer(),
 837//                 );
 838
 839//                 // We only care about noise added by LWE key switch
 840//                 // m+e
 841//                 let m_plus_e = decrypt_lwe(&lwe_in_ct, &ideal_rlwe_sk,
 842// lwe_modop);
 843
 844//                 let m_plus_e_plus_lwe_ksk_noise = decrypt_lwe(&lwe_out,
 845// &ideal_lwe_sk, lwe_modop);
 846
 847//                 let diff = lwe_modop.sub(&m_plus_e_plus_lwe_ksk_noise,
 848// &m_plus_e);
 849
 850//                 check.add_more(&vec![lwe_q.map_element_to_i64(&diff)]);
 851//             }
 852
 853//             println!("Lwe ksk std dev: {}", check.std_dev().abs().log2());
 854//         }
 855//     }
 856
 857//     // Check noise in fresh RGSW ciphertexts, ie X^{s_j[i]}, must equalnoise
 858// in     // // fresh RLWE ciphertext
 859//     if true {}
 860//     // test LWE ksk from RLWE -> LWE
 861//     // if false {
 862//     //     let logp = 2;
 863//     //     let mut rng = DefaultSecureRng::new();
 864
 865//     //     let m = 1;
 866//     //     let encoded_m = m << (lwe_logq - logp);
 867
 868//     //     // Encrypt
 869//     //     let mut lwe_ct = vec![0u64; rlwe_n + 1];
 870//     //     encrypt_lwe(
 871//     //         &mut lwe_ct,
 872//     //         &encoded_m,
 873//     //         ideal_client_key.sk_rlwe.values(),
 874//     //         lwe_modop,
 875//     //         &mut rng,
 876//     //     );
 877
 878//     //     // key switch
 879//     //     let lwe_decomposer = &bool_evaluator.decomposer_lwe;
 880//     //     let mut lwe_out = vec![0u64; lwe_n + 1];
 881//     //     lwe_key_switch(
 882//     //         &mut lwe_out,
 883//     //         &lwe_ct,
 884//     //         &server_key_eval.lwe_ksk,
 885//     //         lwe_modop,
 886//     //         lwe_decomposer,
 887//     //     );
 888
 889//     //     let encoded_m_back = decrypt_lwe(&lwe_out,
 890//     // ideal_client_key.sk_lwe.values(), lwe_modop);     let m_back
 891//     // =         ((encoded_m_back as f64 * (1 << logp) as f64) /
 892//     // (lwe_q as f64)).round() as u64;     dbg!(m_back, m);
 893
 894//     //     let noise = measure_noise_lwe(
 895//     //         &lwe_out,
 896//     //         ideal_client_key.sk_lwe.values(),
 897//     //         lwe_modop,
 898//     //         &encoded_m,
 899//     //     );
 900
 901//     //     println!("Noise: {noise}");
 902//     // }
 903
 904//     // Measure noise in RGSW ciphertexts of ideal LWE secrets
 905//     // if true {
 906//     //     let gadget_vec = gadget_vector(
 907//     //         bool_evaluator.parameters.rlwe_logq,
 908//     //         bool_evaluator.parameters.logb_rgsw,
 909//     //         bool_evaluator.parameters.d_rgsw,
 910//     //     );
 911
 912//     //     for i in 0..20 {
 913//     //         // measure noise in RGSW(s[i])
 914//     //         let si =
 915//     //             ideal_client_key.sk_lwe.values[i] *
 916//     // (bool_evaluator.embedding_factor as i32);         let mut
 917//     // si_poly = vec![0u64; rlwe_n];         if si < 0 {
 918//     //             si_poly[rlwe_n - (si.abs() as usize)] = rlwe_q - 1;
 919//     //         } else {
 920//     //             si_poly[(si.abs() as usize)] = 1;
 921//     //         }
 922
 923//     //         let mut rgsw_si = server_key_eval.rgsw_cts[i].clone();
 924//     //         rgsw_si
 925//     //             .iter_mut()
 926//     //             .for_each(|ri| rlwe_nttop.backward(ri.as_mut()));
 927
 928//     //         println!("####### Noise in RGSW(X^s_{i}) #######");
 929//     //         _measure_noise_rgsw(
 930//     //             &rgsw_si,
 931//     //             &si_poly,
 932//     //             ideal_client_key.sk_rlwe.values(),
 933//     //             &gadget_vec,
 934//     //             rlwe_q,
 935//     //         );
 936//     //         println!("####### ##################### #######");
 937//     //     }
 938//     // }
 939
 940//     // // measure noise grwoth in RLWExRGSW
 941//     // if true {
 942//     //     let mut rng = DefaultSecureRng::new();
 943//     //     let mut carry_m = vec![0u64; rlwe_n];
 944//     //     RandomUniformDist1::random_fill(&mut rng, &rlwe_q,
 945//     // carry_m.as_mut_slice());
 946
 947//     //     // RGSW(carrym)
 948//     //     let trivial_rlwect = vec![vec![0u64; rlwe_n],carry_m.clone()];
 949//     //     let mut rlwe_ct = RlweCiphertext::<_,
 950//     // DefaultSecureRng>::from_raw(trivial_rlwect, true);
 951
 952//     //     let mut scratch_matrix_dplus2_ring = vec![vec![0u64; rlwe_n];
 953//     // d_rgsw + 2];     let mul_mod =
 954//     //         |v0: &u64, v1: &u64| (((*v0 as u128 * *v1 as u128) % (rlwe_q
 955// as u128)) as u64);
 956
 957//     //     for i in 0..bool_evaluator.parameters.lwe_n {
 958//     //         rlwe_by_rgsw(
 959//     //             &mut rlwe_ct,
 960//     //             server_key_eval.rgsw_ct_lwe_si(i),
 961//     //             &mut scratch_matrix_dplus2_ring,
 962//     //             rlwe_decomposer,
 963//     //             rlwe_nttop,
 964//     //             rlwe_modop,
 965//     //         );
 966
 967//     //         // carry_m[X] * s_i[X]
 968//     //         let si =
 969//     //             ideal_client_key.sk_lwe.values[i] *
 970//     // (bool_evaluator.embedding_factor as i32);         let mut
 971//     // si_poly = vec![0u64; rlwe_n];         if si < 0 {
 972//     //             si_poly[rlwe_n - (si.abs() as usize)] = rlwe_q - 1;
 973//     //         } else {
 974//     //             si_poly[(si.abs() as usize)] = 1;
 975//     //         }
 976//     //         carry_m = negacyclic_mul(&carry_m, &si_poly, mul_mod,
 977//     // rlwe_q);
 978
 979//     //         let noise = measure_noise(
 980//     //             &rlwe_ct,
 981//     //             &carry_m,
 982//     //             rlwe_nttop,
 983//     //             rlwe_modop,
 984//     //             ideal_client_key.sk_rlwe.values(),
 985//     //         );
 986//     //         println!("Noise RLWE(carry_m) accumulating {i}^th secret
 987//     // monomial: {noise}");     }
 988//     // }
 989
 990//     // // Check galois keys
 991//     // if false {
 992//     //     let g = bool_evaluator.g() as isize;
 993//     //     let mut rng = DefaultSecureRng::new();
 994//     //     let mut scratch_matrix_dplus2_ring = vec![vec![0u64; rlwe_n];
 995//     // d_rgsw + 2];     for i in [g, -g] {
 996//     //         let mut m = vec![0u64; rlwe_n];
 997//     //         RandomUniformDist1::random_fill(&mut rng, &rlwe_q,
 998//     // m.as_mut_slice());         let mut rlwe_ct = {
 999//     //             let mut data = vec![vec![0u64; rlwe_n]; 2];
1000//     //             public_key_encrypt_rlwe(
1001//     //                 &mut data,
1002//     //                 &collective_pk.key,
1003//     //                 &m,
1004//     //                 rlwe_modop,
1005//     //                 rlwe_nttop,
1006//     //                 &mut rng,
1007//     //             );
1008//     //             RlweCiphertext::<_, DefaultSecureRng>::from_raw(data,
1009//     // false)         };
1010
1011//     //         let auto_key = server_key_eval.galois_key_for_auto(i);
1012//     //         let (auto_map_index, auto_map_sign) =
1013//     // generate_auto_map(rlwe_n, i);         galois_auto(
1014//     //             &mut rlwe_ct,
1015//     //             auto_key,
1016//     //             &mut scratch_matrix_dplus2_ring,
1017//     //             &auto_map_index,
1018//     //             &auto_map_sign,
1019//     //             rlwe_modop,
1020//     //             rlwe_nttop,
1021//     //             rlwe_decomposer,
1022//     //         );
1023
1024//     //         // send m(X) -> m(X^i)
1025//     //         let mut m_k = vec![0u64; rlwe_n];
1026//     //         izip!(m.iter(), auto_map_index.iter(),
1027//     // auto_map_sign.iter()).for_each(             |(mi, to_index,to_sign)|
1028//     // // {                 if !to_sign {
1029//     // m_k[*to_index] = rlwe_q - *mi;                 } else {
1030//     //                     m_k[*to_index] = *mi;
1031//     //                 }
1032//     //             },
1033//     //         );
1034
1035//     //         // measure noise
1036//     //         let noise = measure_noise(
1037//     //             &rlwe_ct,
1038//     //             &m_k,
1039//     //             rlwe_nttop,
1040//     //             rlwe_modop,
1041//     //             ideal_client_key.sk_rlwe.values(),
1042//     //         );
1043
1044//     //         println!("Noise after auto k={i}: {noise}");
1045//     //     }
1046//     // }
1047// }