arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
phantom-zone/src/bool/keys.rs
src/bool/keys.rsRaw
   1use std::{collections::HashMap, hash::Hash, marker::PhantomData};
   2
   3use crate::{
   4    backend::{ModInit, VectorOps},
   5    pbs::WithShoupRepr,
   6    random::{NewWithSeed, RandomFillUniformInModulus},
   7    rgsw::RlweSecret,
   8    utils::{ToShoup, WithLocal},
   9    Decryptor, Encryptor, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor, RowEntity, RowMut,
  10};
  11
  12use super::{
  13    evaluator::BoolEvaluator,
  14    parameters::{BoolParameters, CiphertextModulus},
  15};
  16
  17pub(crate) trait SinglePartyClientKey {
  18    type Element;
  19    fn sk_rlwe(&self) -> Vec<Self::Element>;
  20    fn sk_lwe(&self) -> Vec<Self::Element>;
  21}
  22
  23pub(crate) trait InteractiveMultiPartyClientKey {
  24    type Element;
  25    fn sk_rlwe(&self) -> Vec<Self::Element>;
  26    fn sk_lwe(&self) -> Vec<Self::Element>;
  27}
  28
  29pub(crate) trait NonInteractiveMultiPartyClientKey {
  30    type Element;
  31    fn sk_rlwe(&self) -> Vec<Self::Element>;
  32    fn sk_u_rlwe(&self) -> Vec<Self::Element>;
  33    fn sk_lwe(&self) -> Vec<Self::Element>;
  34}
  35
  36/// Client key
  37///
  38/// Key is used for all parameter varians - Single party, interactive
  39/// multi-party, and non-interactive multi-party. The only stored the main seed
  40/// and seeds of the Rlwe/Lwe secrets are derived at puncturing the seed desired
  41/// number of times.
  42///
  43/// ### Punctures required:
  44///
  45///     Puncture 1 -> Seed of RLWE secret used as main RLWE secret for
  46///                   single-party, interactive/non-interactive multi-party
  47///
  48///     Puncture 2 -> Seed of LWE secret used main LWE secret for single-party,
  49///                   interactive/non-interactive multi-party
  50///
  51///     Puncture 3 -> Seed of RLWE secret used as `u` in
  52///                   interactive/non-interactive multi-party.
  53#[derive(Clone)]
  54pub struct ClientKey<S, E> {
  55    seed: S,
  56    parameters: BoolParameters<E>,
  57}
  58
  59mod impl_ck {
  60    use crate::{
  61        random::DefaultSecureRng,
  62        utils::{fill_random_ternary_secret_with_hamming_weight, puncture_p_rng},
  63    };
  64
  65    use super::*;
  66
  67    impl<E> ClientKey<[u8; 32], E> {
  68        pub(in super::super) fn new(parameters: BoolParameters<E>) -> ClientKey<[u8; 32], E> {
  69            let mut rng = DefaultSecureRng::new();
  70            let mut seed = [0u8; 32];
  71            rng.fill_bytes(&mut seed);
  72            Self { seed, parameters }
  73        }
  74    }
  75
  76    impl<E> SinglePartyClientKey for ClientKey<[u8; 32], E> {
  77        type Element = i32;
  78        fn sk_lwe(&self) -> Vec<Self::Element> {
  79            let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
  80            let lwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 2);
  81
  82            let mut lwe_prng = DefaultSecureRng::new_seeded(lwe_seed);
  83            let mut out = vec![0i32; self.parameters.lwe_n().0];
  84            fill_random_ternary_secret_with_hamming_weight(
  85                &mut out,
  86                self.parameters.lwe_n().0 >> 1,
  87                &mut lwe_prng,
  88            );
  89            out
  90        }
  91        fn sk_rlwe(&self) -> Vec<Self::Element> {
  92            let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
  93            let rlwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 1);
  94
  95            let mut rlwe_prng = DefaultSecureRng::new_seeded(rlwe_seed);
  96            let mut out = vec![0i32; self.parameters.rlwe_n().0];
  97            fill_random_ternary_secret_with_hamming_weight(
  98                &mut out,
  99                self.parameters.rlwe_n().0 >> 1,
 100                &mut rlwe_prng,
 101            );
 102            out
 103        }
 104    }
 105
 106    impl<E> InteractiveMultiPartyClientKey for ClientKey<[u8; 32], E> {
 107        type Element = i32;
 108        fn sk_lwe(&self) -> Vec<Self::Element> {
 109            <Self as SinglePartyClientKey>::sk_lwe(&self)
 110        }
 111        fn sk_rlwe(&self) -> Vec<Self::Element> {
 112            <Self as SinglePartyClientKey>::sk_rlwe(&self)
 113        }
 114    }
 115
 116    impl<E> NonInteractiveMultiPartyClientKey for ClientKey<[u8; 32], E> {
 117        type Element = i32;
 118        fn sk_lwe(&self) -> Vec<Self::Element> {
 119            <Self as SinglePartyClientKey>::sk_lwe(&self)
 120        }
 121        fn sk_rlwe(&self) -> Vec<Self::Element> {
 122            <Self as SinglePartyClientKey>::sk_rlwe(&self)
 123        }
 124        fn sk_u_rlwe(&self) -> Vec<Self::Element> {
 125            let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
 126            let rlwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 3);
 127
 128            let mut rlwe_prng = DefaultSecureRng::new_seeded(rlwe_seed);
 129            let mut out = vec![0i32; self.parameters.rlwe_n().0];
 130            fill_random_ternary_secret_with_hamming_weight(
 131                &mut out,
 132                self.parameters.rlwe_n().0 >> 1,
 133                &mut rlwe_prng,
 134            );
 135            out
 136        }
 137    }
 138}
 139
 140/// Public key
 141pub struct PublicKey<M, Rng, ModOp> {
 142    key: M,
 143    _phantom: PhantomData<(Rng, ModOp)>,
 144}
 145
 146pub(super) mod impl_pk {
 147    use crate::evaluator::MultiPartyCrs;
 148
 149    use super::*;
 150
 151    impl<M, R, Mo> PublicKey<M, R, Mo> {
 152        pub(in super::super) fn key(&self) -> &M {
 153            &self.key
 154        }
 155    }
 156
 157    impl<
 158            M: MatrixMut + MatrixEntity,
 159            Rng: NewWithSeed
 160                + RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>,
 161            ModOp,
 162        > From<SeededPublicKey<M::R, Rng::Seed, BoolParameters<M::MatElement>, ModOp>>
 163        for PublicKey<M, Rng, ModOp>
 164    where
 165        <M as Matrix>::R: RowMut,
 166        M::MatElement: Copy,
 167    {
 168        fn from(
 169            value: SeededPublicKey<M::R, Rng::Seed, BoolParameters<M::MatElement>, ModOp>,
 170        ) -> Self {
 171            let mut prng = Rng::new_with_seed(value.seed);
 172
 173            let mut key = M::zeros(2, value.parameters.rlwe_n().0);
 174            // sample A
 175            RandomFillUniformInModulus::random_fill(
 176                &mut prng,
 177                value.parameters.rlwe_q(),
 178                key.get_row_mut(0),
 179            );
 180            // Copy over B
 181            key.get_row_mut(1).copy_from_slice(value.part_b.as_ref());
 182
 183            PublicKey {
 184                key,
 185                _phantom: PhantomData,
 186            }
 187        }
 188    }
 189
 190    impl<
 191            M: MatrixMut + MatrixEntity,
 192            Rng: NewWithSeed
 193                + RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>,
 194            ModOp: VectorOps<Element = M::MatElement> + ModInit<M = CiphertextModulus<M::MatElement>>,
 195        >
 196        From<
 197            &[CommonReferenceSeededCollectivePublicKeyShare<
 198                M::R,
 199                Rng::Seed,
 200                BoolParameters<M::MatElement>,
 201            >],
 202        > for PublicKey<M, Rng, ModOp>
 203    where
 204        <M as Matrix>::R: RowMut,
 205        Rng::Seed: Copy + PartialEq,
 206        M::MatElement: PartialEq + Copy,
 207    {
 208        fn from(
 209            value: &[CommonReferenceSeededCollectivePublicKeyShare<
 210                M::R,
 211                Rng::Seed,
 212                BoolParameters<M::MatElement>,
 213            >],
 214        ) -> Self {
 215            assert!(value.len() > 0);
 216
 217            let parameters = &value[0].parameters;
 218            let mut key = M::zeros(2, parameters.rlwe_n().0);
 219
 220            // sample A
 221            let seed = value[0].cr_seed;
 222            let mut main_rng = Rng::new_with_seed(seed);
 223            RandomFillUniformInModulus::random_fill(
 224                &mut main_rng,
 225                parameters.rlwe_q(),
 226                key.get_row_mut(0),
 227            );
 228
 229            // Sum all Bs
 230            let rlweq_modop = ModOp::new(parameters.rlwe_q().clone());
 231            value.iter().for_each(|share_i| {
 232                assert!(share_i.cr_seed == seed);
 233                assert!(&share_i.parameters == parameters);
 234
 235                rlweq_modop.elwise_add_mut(key.get_row_mut(1), share_i.share.as_ref());
 236            });
 237
 238            PublicKey {
 239                key,
 240                _phantom: PhantomData,
 241            }
 242        }
 243    }
 244}
 245
 246/// Seeded public key
 247struct SeededPublicKey<Ro, S, P, ModOp> {
 248    part_b: Ro,
 249    seed: S,
 250    parameters: P,
 251    _phantom: PhantomData<ModOp>,
 252}
 253
 254mod impl_seeded_pk {
 255    use super::*;
 256
 257    impl<R, S, ModOp>
 258        From<&[CommonReferenceSeededCollectivePublicKeyShare<R, S, BoolParameters<R::Element>>]>
 259        for SeededPublicKey<R, S, BoolParameters<R::Element>, ModOp>
 260    where
 261        ModOp: VectorOps<Element = R::Element> + ModInit<M = CiphertextModulus<R::Element>>,
 262        S: PartialEq + Clone,
 263        R: RowMut + RowEntity + Clone,
 264        R::Element: Clone + PartialEq,
 265    {
 266        fn from(
 267            value: &[CommonReferenceSeededCollectivePublicKeyShare<
 268                R,
 269                S,
 270                BoolParameters<R::Element>,
 271            >],
 272        ) -> Self {
 273            assert!(value.len() > 0);
 274
 275            let parameters = &value[0].parameters;
 276            let cr_seed = value[0].cr_seed.clone();
 277
 278            // Sum all Bs
 279            let rlweq_modop = ModOp::new(parameters.rlwe_q().clone());
 280            let mut part_b = value[0].share.clone();
 281            value.iter().skip(1).for_each(|share_i| {
 282                assert!(&share_i.cr_seed == &cr_seed);
 283                assert!(&share_i.parameters == parameters);
 284
 285                rlweq_modop.elwise_add_mut(part_b.as_mut(), share_i.share.as_ref());
 286            });
 287
 288            Self {
 289                part_b,
 290                seed: cr_seed,
 291                parameters: parameters.clone(),
 292                _phantom: PhantomData,
 293            }
 294        }
 295    }
 296}
 297
 298/// CRS seeded collective public key share
 299pub struct CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
 300    share: Ro,
 301    cr_seed: S,
 302    parameters: P,
 303}
 304impl<Ro, S, P> CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
 305    pub(super) fn new(share: Ro, cr_seed: S, parameters: P) -> Self {
 306        CommonReferenceSeededCollectivePublicKeyShare {
 307            share,
 308            cr_seed,
 309            parameters,
 310        }
 311    }
 312}
 313
 314/// CRS seeded Multi-party server key share
 315pub struct CommonReferenceSeededMultiPartyServerKeyShare<M: Matrix, P, S> {
 316    self_leader_rgsws: Vec<M>,
 317    not_self_leader_rgsws: Vec<M>,
 318    /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
 319    /// to -g is at 0
 320    auto_keys: HashMap<usize, M>,
 321    lwe_ksk: M::R,
 322    /// Common reference seed
 323    cr_seed: S,
 324    parameters: P,
 325    user_id: usize,
 326}
 327
 328impl<M: Matrix, P, S> CommonReferenceSeededMultiPartyServerKeyShare<M, P, S> {
 329    pub(super) fn new(
 330        self_leader_rgsws: Vec<M>,
 331        not_self_leader_rgsws: Vec<M>,
 332        auto_keys: HashMap<usize, M>,
 333        lwe_ksk: M::R,
 334        cr_seed: S,
 335        parameters: P,
 336        user_id: usize,
 337    ) -> Self {
 338        CommonReferenceSeededMultiPartyServerKeyShare {
 339            self_leader_rgsws,
 340            not_self_leader_rgsws,
 341            auto_keys,
 342            lwe_ksk,
 343            cr_seed,
 344            parameters,
 345            user_id,
 346        }
 347    }
 348
 349    pub(super) fn cr_seed(&self) -> &S {
 350        &self.cr_seed
 351    }
 352
 353    pub(super) fn parameters(&self) -> &P {
 354        &self.parameters
 355    }
 356
 357    pub(super) fn auto_keys(&self) -> &HashMap<usize, M> {
 358        &self.auto_keys
 359    }
 360
 361    pub(crate) fn self_leader_rgsws(&self) -> &[M] {
 362        &self.self_leader_rgsws
 363    }
 364
 365    pub(super) fn not_self_leader_rgsws(&self) -> &[M] {
 366        &self.not_self_leader_rgsws
 367    }
 368
 369    pub(super) fn lwe_ksk(&self) -> &M::R {
 370        &self.lwe_ksk
 371    }
 372
 373    pub(super) fn user_id(&self) -> usize {
 374        self.user_id
 375    }
 376}
 377
 378/// CRS seeded MultiParty server key
 379pub struct SeededMultiPartyServerKey<M: Matrix, S, P> {
 380    rgsw_cts: Vec<M>,
 381    /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
 382    /// to -g is at 0
 383    auto_keys: HashMap<usize, M>,
 384    lwe_ksk: M::R,
 385    cr_seed: S,
 386    parameters: P,
 387}
 388
 389impl<M: Matrix, S, P> SeededMultiPartyServerKey<M, S, P> {
 390    pub(super) fn new(
 391        rgsw_cts: Vec<M>,
 392        auto_keys: HashMap<usize, M>,
 393        lwe_ksk: M::R,
 394        cr_seed: S,
 395        parameters: P,
 396    ) -> Self {
 397        SeededMultiPartyServerKey {
 398            rgsw_cts,
 399            auto_keys,
 400            lwe_ksk,
 401            cr_seed,
 402            parameters,
 403        }
 404    }
 405
 406    pub(super) fn rgsw_cts(&self) -> &[M] {
 407        &self.rgsw_cts
 408    }
 409}
 410
 411/// Seeded single party server key
 412pub struct SeededSinglePartyServerKey<M: Matrix, P, S> {
 413    /// Rgsw cts of LWE secret elements
 414    pub(crate) rgsw_cts: Vec<M>,
 415    /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
 416    /// to -g is at 0
 417    pub(crate) auto_keys: HashMap<usize, M>,
 418    /// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
 419    pub(crate) lwe_ksk: M::R,
 420    /// Parameters
 421    pub(crate) parameters: P,
 422    /// Main seed
 423    pub(crate) seed: S,
 424}
 425impl<M: Matrix, S> SeededSinglePartyServerKey<M, BoolParameters<M::MatElement>, S> {
 426    pub(super) fn from_raw(
 427        auto_keys: HashMap<usize, M>,
 428        rgsw_cts: Vec<M>,
 429        lwe_ksk: M::R,
 430        parameters: BoolParameters<M::MatElement>,
 431        seed: S,
 432    ) -> Self {
 433        // sanity checks
 434        auto_keys.iter().for_each(|v| {
 435            assert!(
 436                v.1.dimension()
 437                    == (
 438                        parameters.auto_decomposition_count().0,
 439                        parameters.rlwe_n().0
 440                    )
 441            )
 442        });
 443
 444        let (part_a_d, part_b_d) = parameters.rlwe_rgsw_decomposition_count();
 445        rgsw_cts.iter().for_each(|v| {
 446            assert!(v.dimension() == (part_a_d.0 * 2 + part_b_d.0, parameters.rlwe_n().0))
 447        });
 448        assert!(
 449            lwe_ksk.as_ref().len()
 450                == (parameters.lwe_decomposition_count().0 * parameters.rlwe_n().0)
 451        );
 452
 453        SeededSinglePartyServerKey {
 454            rgsw_cts,
 455            auto_keys,
 456            lwe_ksk,
 457            parameters,
 458            seed,
 459        }
 460    }
 461}
 462
 463/// Server key in evaluation domain
 464pub(crate) struct ServerKeyEvaluationDomain<M, P, R, N> {
 465    /// Rgsw cts of LWE secret elements
 466    rgsw_cts: Vec<M>,
 467    /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
 468    /// to -g is at 0
 469    galois_keys: HashMap<usize, M>,
 470    /// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
 471    lwe_ksk: M,
 472    parameters: P,
 473    _phanton: PhantomData<(R, N)>,
 474}
 475
 476pub(super) mod impl_server_key_eval_domain {
 477    use itertools::{izip, Itertools};
 478
 479    use crate::{
 480        evaluator::MultiPartyCrs,
 481        ntt::{Ntt, NttInit},
 482        pbs::PbsKey,
 483        random::RandomFill,
 484    };
 485
 486    use super::*;
 487
 488    impl<M, Mod, R, N> ServerKeyEvaluationDomain<M, Mod, R, N> {
 489        pub(in super::super) fn rgsw_cts(&self) -> &[M] {
 490            &self.rgsw_cts
 491        }
 492    }
 493
 494    impl<
 495            M: MatrixMut + MatrixEntity,
 496            R: RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>
 497                + NewWithSeed,
 498            N: NttInit<CiphertextModulus<M::MatElement>> + Ntt<Element = M::MatElement>,
 499        > From<&SeededSinglePartyServerKey<M, BoolParameters<M::MatElement>, R::Seed>>
 500        for ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>
 501    where
 502        <M as Matrix>::R: RowMut,
 503        M::MatElement: Copy,
 504        R::Seed: Clone,
 505    {
 506        fn from(
 507            value: &SeededSinglePartyServerKey<M, BoolParameters<M::MatElement>, R::Seed>,
 508        ) -> Self {
 509            let mut main_prng = R::new_with_seed(value.seed.clone());
 510            let parameters = &value.parameters;
 511            let g = parameters.g() as isize;
 512            let ring_size = value.parameters.rlwe_n().0;
 513            let lwe_n = value.parameters.lwe_n().0;
 514            let rlwe_q = value.parameters.rlwe_q();
 515            let lwq_q = value.parameters.lwe_q();
 516
 517            let nttop = N::new(rlwe_q, ring_size);
 518
 519            // galois keys
 520            let mut auto_keys = HashMap::new();
 521            let auto_decomp_count = parameters.auto_decomposition_count().0;
 522            let auto_element_dlogs = parameters.auto_element_dlogs();
 523            for i in auto_element_dlogs.into_iter() {
 524                let seeded_auto_key = value.auto_keys.get(&i).unwrap();
 525                assert!(seeded_auto_key.dimension() == (auto_decomp_count, ring_size));
 526
 527                let mut data = M::zeros(auto_decomp_count * 2, ring_size);
 528
 529                // sample RLWE'_A(-s(X^k))
 530                data.iter_rows_mut().take(auto_decomp_count).for_each(|ri| {
 531                    RandomFillUniformInModulus::random_fill(&mut main_prng, &rlwe_q, ri.as_mut())
 532                });
 533
 534                // copy over RLWE'B_(-s(X^k))
 535                izip!(
 536                    data.iter_rows_mut().skip(auto_decomp_count),
 537                    seeded_auto_key.iter_rows()
 538                )
 539                .for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
 540
 541                // Send to Evaluation domain
 542                data.iter_rows_mut()
 543                    .for_each(|ri| nttop.forward(ri.as_mut()));
 544
 545                auto_keys.insert(i, data);
 546            }
 547
 548            // RGSW ciphertexts
 549            let (rlrg_a_decomp, rlrg_b_decomp) = parameters.rlwe_rgsw_decomposition_count();
 550            let rgsw_cts = value
 551                .rgsw_cts
 552                .iter()
 553                .map(|seeded_rgsw_si| {
 554                    assert!(
 555                        seeded_rgsw_si.dimension()
 556                            == (rlrg_a_decomp.0 * 2 + rlrg_b_decomp.0, ring_size)
 557                    );
 558
 559                    let mut data = M::zeros(rlrg_a_decomp.0 * 2 + rlrg_b_decomp.0 * 2, ring_size);
 560
 561                    // copy over RLWE'(-sm)
 562                    izip!(
 563                        data.iter_rows_mut().take(rlrg_a_decomp.0 * 2),
 564                        seeded_rgsw_si.iter_rows().take(rlrg_a_decomp.0 * 2)
 565                    )
 566                    .for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
 567
 568                    // sample RLWE'_A(m)
 569                    data.iter_rows_mut()
 570                        .skip(rlrg_a_decomp.0 * 2)
 571                        .take(rlrg_b_decomp.0)
 572                        .for_each(|ri| {
 573                            RandomFillUniformInModulus::random_fill(
 574                                &mut main_prng,
 575                                &rlwe_q,
 576                                ri.as_mut(),
 577                            )
 578                        });
 579
 580                    // copy over RLWE'_B(m)
 581                    izip!(
 582                        data.iter_rows_mut()
 583                            .skip(rlrg_a_decomp.0 * 2 + rlrg_b_decomp.0),
 584                        seeded_rgsw_si.iter_rows().skip(rlrg_a_decomp.0 * 2)
 585                    )
 586                    .for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
 587
 588                    // send polynomials to evaluation domain
 589                    data.iter_rows_mut()
 590                        .for_each(|ri| nttop.forward(ri.as_mut()));
 591
 592                    data
 593                })
 594                .collect_vec();
 595
 596            // LWE ksk
 597            let lwe_ksk = {
 598                let d = parameters.lwe_decomposition_count().0;
 599                assert!(value.lwe_ksk.as_ref().len() == d * ring_size);
 600
 601                let mut data = M::zeros(d * ring_size, lwe_n + 1);
 602                izip!(data.iter_rows_mut(), value.lwe_ksk.as_ref().iter()).for_each(
 603                    |(lwe_i, bi)| {
 604                        RandomFillUniformInModulus::random_fill(
 605                            &mut main_prng,
 606                            &lwq_q,
 607                            &mut lwe_i.as_mut()[1..],
 608                        );
 609                        lwe_i.as_mut()[0] = *bi;
 610                    },
 611                );
 612
 613                data
 614            };
 615
 616            ServerKeyEvaluationDomain {
 617                rgsw_cts,
 618                galois_keys: auto_keys,
 619                lwe_ksk,
 620                parameters: parameters.clone(),
 621                _phanton: PhantomData,
 622            }
 623        }
 624    }
 625
 626    impl<
 627            M: MatrixMut + MatrixEntity,
 628            Rng: NewWithSeed,
 629            N: NttInit<CiphertextModulus<M::MatElement>> + Ntt<Element = M::MatElement>,
 630        >
 631        From<&SeededMultiPartyServerKey<M, MultiPartyCrs<Rng::Seed>, BoolParameters<M::MatElement>>>
 632        for ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, Rng, N>
 633    where
 634        <M as Matrix>::R: RowMut,
 635        Rng::Seed: Copy + Default,
 636        Rng: RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>
 637            + RandomFill<Rng::Seed>,
 638        M::MatElement: Copy,
 639    {
 640        fn from(
 641            value: &SeededMultiPartyServerKey<
 642                M,
 643                MultiPartyCrs<Rng::Seed>,
 644                BoolParameters<M::MatElement>,
 645            >,
 646        ) -> Self {
 647            let g = value.parameters.g() as isize;
 648            let rlwe_n = value.parameters.rlwe_n().0;
 649            let lwe_n = value.parameters.lwe_n().0;
 650            let rlwe_q = value.parameters.rlwe_q();
 651            let lwe_q = value.parameters.lwe_q();
 652
 653            let rlwe_nttop = N::new(rlwe_q, rlwe_n);
 654
 655            // auto keys
 656            let mut auto_keys = HashMap::new();
 657            {
 658                let mut auto_prng = Rng::new_with_seed(value.cr_seed.auto_keys_cts_seed::<Rng>());
 659                let auto_d_count = value.parameters.auto_decomposition_count().0;
 660                let auto_element_dlogs = value.parameters.auto_element_dlogs();
 661                for i in auto_element_dlogs.into_iter() {
 662                    let mut key = M::zeros(auto_d_count * 2, rlwe_n);
 663
 664                    // sample a
 665                    key.iter_rows_mut().take(auto_d_count).for_each(|ri| {
 666                        RandomFillUniformInModulus::random_fill(
 667                            &mut auto_prng,
 668                            &rlwe_q,
 669                            ri.as_mut(),
 670                        )
 671                    });
 672
 673                    let key_part_b = value.auto_keys.get(&i).unwrap();
 674                    assert!(key_part_b.dimension() == (auto_d_count, rlwe_n));
 675                    izip!(
 676                        key.iter_rows_mut().skip(auto_d_count),
 677                        key_part_b.iter_rows()
 678                    )
 679                    .for_each(|(to_ri, from_ri)| {
 680                        to_ri.as_mut().copy_from_slice(from_ri.as_ref());
 681                    });
 682
 683                    // send to evaluation domain
 684                    key.iter_rows_mut()
 685                        .for_each(|ri| rlwe_nttop.forward(ri.as_mut()));
 686
 687                    auto_keys.insert(i, key);
 688                }
 689            }
 690
 691            // rgsw cts
 692            let (rlrg_d_a, rlrg_d_b) = value.parameters.rlwe_rgsw_decomposition_count();
 693            let rgsw_ct_out = rlrg_d_a.0 * 2 + rlrg_d_b.0 * 2;
 694            let rgsw_cts = value
 695                .rgsw_cts
 696                .iter()
 697                .map(|ct_i_in| {
 698                    assert!(ct_i_in.dimension() == (rgsw_ct_out, rlwe_n));
 699                    let mut eval_ct_i_out = M::zeros(rgsw_ct_out, rlwe_n);
 700
 701                    izip!(eval_ct_i_out.iter_rows_mut(), ct_i_in.iter_rows()).for_each(
 702                        |(to_ri, from_ri)| {
 703                            to_ri.as_mut().copy_from_slice(from_ri.as_ref());
 704                            rlwe_nttop.forward(to_ri.as_mut());
 705                        },
 706                    );
 707
 708                    eval_ct_i_out
 709                })
 710                .collect_vec();
 711
 712            // lwe ksk
 713            let mut lwe_ksk_prng = Rng::new_with_seed(value.cr_seed.lwe_ksk_cts_seed_seed::<Rng>());
 714            let d_lwe = value.parameters.lwe_decomposition_count().0;
 715            let mut lwe_ksk = M::zeros(rlwe_n * d_lwe, lwe_n + 1);
 716            izip!(lwe_ksk.iter_rows_mut(), value.lwe_ksk.as_ref().iter()).for_each(
 717                |(lwe_i, bi)| {
 718                    RandomFillUniformInModulus::random_fill(
 719                        &mut lwe_ksk_prng,
 720                        &lwe_q,
 721                        &mut lwe_i.as_mut()[1..],
 722                    );
 723                    lwe_i.as_mut()[0] = *bi;
 724                },
 725            );
 726
 727            ServerKeyEvaluationDomain {
 728                rgsw_cts,
 729                galois_keys: auto_keys,
 730                lwe_ksk,
 731                parameters: value.parameters.clone(),
 732                _phanton: PhantomData,
 733            }
 734        }
 735    }
 736
 737    impl<M: Matrix, P, R, N> PbsKey for ServerKeyEvaluationDomain<M, P, R, N> {
 738        type AutoKey = M;
 739        type LweKskKey = M;
 740        type RgswCt = M;
 741
 742        fn galois_key_for_auto(&self, k: usize) -> &Self::AutoKey {
 743            self.galois_keys.get(&k).unwrap()
 744        }
 745        fn rgsw_ct_lwe_si(&self, si: usize) -> &Self::RgswCt {
 746            &self.rgsw_cts[si]
 747        }
 748
 749        fn lwe_ksk(&self) -> &Self::LweKskKey {
 750            &self.lwe_ksk
 751        }
 752    }
 753
 754    #[cfg(test)]
 755    impl<M, P, R, N> super::super::print_noise::CollectRuntimeServerKeyStats
 756        for ServerKeyEvaluationDomain<M, P, R, N>
 757    {
 758        type M = M;
 759        fn galois_key_for_auto(&self, k: usize) -> &Self::M {
 760            self.galois_keys.get(&k).unwrap()
 761        }
 762        fn lwe_ksk(&self) -> &Self::M {
 763            &self.lwe_ksk
 764        }
 765        fn rgsw_cts_lwe_si(&self, s_index: usize) -> &Self::M {
 766            &self.rgsw_cts[s_index]
 767        }
 768    }
 769}
 770
 771pub(crate) struct NonInteractiveServerKeyEvaluationDomain<M, P, R, N> {
 772    /// RGSW ciphertexts ideal lwe secret key elements under ideal rlwe secret
 773    rgsw_cts: Vec<M>,
 774    /// Automorphism keys under ideal rlwe secret
 775    auto_keys: HashMap<usize, M>,
 776    /// LWE key switching key from Q -> Q_{ks}
 777    lwe_ksk: M,
 778    /// Key switching key from user j to ideal secret key s. User j's ksk is at
 779    /// j'th element
 780    ui_to_s_ksks: Vec<M>,
 781    parameters: P,
 782    _phanton: PhantomData<(R, N)>,
 783}
 784
 785pub(super) mod impl_non_interactive_server_key_eval_domain {
 786    use itertools::{izip, Itertools};
 787
 788    use crate::{bool::evaluator::NonInteractiveMultiPartyCrs, random::RandomFill, Ntt, NttInit};
 789
 790    use super::*;
 791
 792    impl<M, P, R, N> NonInteractiveServerKeyEvaluationDomain<M, P, R, N> {
 793        pub(in super::super) fn rgsw_cts(&self) -> &[M] {
 794            &self.rgsw_cts
 795        }
 796    }
 797
 798    impl<M, Rng, N>
 799        From<
 800            &SeededNonInteractiveMultiPartyServerKey<
 801                M,
 802                NonInteractiveMultiPartyCrs<Rng::Seed>,
 803                BoolParameters<M::MatElement>,
 804            >,
 805        > for NonInteractiveServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, Rng, N>
 806    where
 807        M: MatrixMut + MatrixEntity + Clone,
 808        Rng: NewWithSeed
 809            + RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>
 810            + RandomFill<<Rng as NewWithSeed>::Seed>,
 811        N: Ntt<Element = M::MatElement> + NttInit<CiphertextModulus<M::MatElement>>,
 812        M::R: RowMut,
 813        M::MatElement: Copy,
 814        Rng::Seed: Clone + Copy + Default,
 815    {
 816        fn from(
 817            value: &SeededNonInteractiveMultiPartyServerKey<
 818                M,
 819                NonInteractiveMultiPartyCrs<Rng::Seed>,
 820                BoolParameters<M::MatElement>,
 821            >,
 822        ) -> Self {
 823            let rlwe_nttop = N::new(value.parameters.rlwe_q(), value.parameters.rlwe_n().0);
 824            let ring_size = value.parameters.rlwe_n().0;
 825
 826            // RGSW cts
 827            // copy over rgsw cts and send to evaluation domain
 828            let mut rgsw_cts = value.rgsw_cts.clone();
 829            rgsw_cts.iter_mut().for_each(|c| {
 830                c.iter_rows_mut()
 831                    .for_each(|ri| rlwe_nttop.forward(ri.as_mut()))
 832            });
 833
 834            // Auto keys
 835            // populate pseudo random part of auto keys. Then send auto keys to
 836            // evaluation domain
 837            let mut auto_keys = HashMap::new();
 838            let auto_seed = value.cr_seed.auto_keys_cts_seed::<Rng>();
 839            let mut auto_prng = Rng::new_with_seed(auto_seed);
 840            let auto_element_dlogs = value.parameters.auto_element_dlogs();
 841            let d_auto = value.parameters.auto_decomposition_count().0;
 842            auto_element_dlogs.iter().for_each(|el| {
 843                let auto_part_b = value
 844                    .auto_keys
 845                    .get(el)
 846                    .expect(&format!("Auto key for element g^{el} not found"));
 847
 848                assert!(auto_part_b.dimension() == (d_auto, ring_size));
 849
 850                let mut auto_ct = M::zeros(d_auto * 2, ring_size);
 851
 852                // sample part A
 853                auto_ct.iter_rows_mut().take(d_auto).for_each(|ri| {
 854                    RandomFillUniformInModulus::random_fill(
 855                        &mut auto_prng,
 856                        value.parameters.rlwe_q(),
 857                        ri.as_mut(),
 858                    )
 859                });
 860
 861                // Copy over part B
 862                izip!(
 863                    auto_ct.iter_rows_mut().skip(d_auto),
 864                    auto_part_b.iter_rows()
 865                )
 866                .for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
 867
 868                // send to evaluation domain
 869                auto_ct
 870                    .iter_rows_mut()
 871                    .for_each(|r| rlwe_nttop.forward(r.as_mut()));
 872
 873                auto_keys.insert(*el, auto_ct);
 874            });
 875
 876            // LWE ksk
 877            // populate pseudo random part of lwe ciphertexts in ksk and copy over part b
 878            // elements
 879            let lwe_ksk_seed = value.cr_seed.lwe_ksk_cts_seed::<Rng>();
 880            let mut lwe_ksk_prng = Rng::new_with_seed(lwe_ksk_seed);
 881            let mut lwe_ksk = M::zeros(
 882                value.parameters.lwe_decomposition_count().0 * ring_size,
 883                value.parameters.lwe_n().0 + 1,
 884            );
 885            lwe_ksk.iter_rows_mut().for_each(|ri| {
 886                // first element is resereved for part b. Only sample a_is in the rest
 887                RandomFillUniformInModulus::random_fill(
 888                    &mut lwe_ksk_prng,
 889                    value.parameters.lwe_q(),
 890                    &mut ri.as_mut()[1..],
 891                )
 892            });
 893            // copy over part bs
 894            assert!(
 895                value.lwe_ksk.as_ref().len()
 896                    == value.parameters.lwe_decomposition_count().0 * ring_size
 897            );
 898            izip!(value.lwe_ksk.as_ref().iter(), lwe_ksk.iter_rows_mut()).for_each(
 899                |(b_el, lwe_ct)| {
 900                    lwe_ct.as_mut()[0] = *b_el;
 901                },
 902            );
 903
 904            // u_i to s ksk
 905            let d_uitos = value
 906                .parameters
 907                .non_interactive_ui_to_s_key_switch_decomposition_count()
 908                .0;
 909            let ui_to_s_ksks = value
 910                .ui_to_s_ksks
 911                .iter()
 912                .enumerate()
 913                .map(|(user_id, incoming_ksk_partb)| {
 914                    let user_i_seed = value.cr_seed.ui_to_s_ks_seed_for_user_i::<Rng>(user_id);
 915                    let mut prng = Rng::new_with_seed(user_i_seed);
 916
 917                    let mut ksk_ct = M::zeros(d_uitos * 2, ring_size);
 918
 919                    ksk_ct.iter_rows_mut().take(d_uitos).for_each(|r| {
 920                        RandomFillUniformInModulus::random_fill(
 921                            &mut prng,
 922                            value.parameters.rlwe_q(),
 923                            r.as_mut(),
 924                        );
 925                    });
 926
 927                    assert!(incoming_ksk_partb.dimension() == (d_uitos, ring_size));
 928                    izip!(
 929                        ksk_ct.iter_rows_mut().skip(d_uitos),
 930                        incoming_ksk_partb.iter_rows()
 931                    )
 932                    .for_each(|(to_ri, from_ri)| {
 933                        to_ri.as_mut().copy_from_slice(from_ri.as_ref());
 934                    });
 935
 936                    ksk_ct
 937                        .iter_rows_mut()
 938                        .for_each(|r| rlwe_nttop.forward(r.as_mut()));
 939                    ksk_ct
 940                })
 941                .collect_vec();
 942
 943            NonInteractiveServerKeyEvaluationDomain {
 944                rgsw_cts,
 945                auto_keys,
 946                lwe_ksk,
 947                ui_to_s_ksks,
 948                parameters: value.parameters.clone(),
 949                _phanton: PhantomData,
 950            }
 951        }
 952    }
 953
 954    #[cfg(test)]
 955    impl<M, P, R, N> super::super::print_noise::CollectRuntimeServerKeyStats
 956        for NonInteractiveServerKeyEvaluationDomain<M, P, R, N>
 957    {
 958        type M = M;
 959        fn galois_key_for_auto(&self, k: usize) -> &Self::M {
 960            self.auto_keys.get(&k).unwrap()
 961        }
 962        fn lwe_ksk(&self) -> &Self::M {
 963            &self.lwe_ksk
 964        }
 965        fn rgsw_cts_lwe_si(&self, s_index: usize) -> &Self::M {
 966            &self.rgsw_cts[s_index]
 967        }
 968    }
 969}
 970
 971pub struct SeededNonInteractiveMultiPartyServerKey<M: Matrix, S, P> {
 972    /// u_i to s key switching keys in random order. Key switchin key for user j
 973    /// is stored at j^th index
 974    ui_to_s_ksks: Vec<M>,
 975    /// RGSW ciphertets
 976    rgsw_cts: Vec<M>,
 977    auto_keys: HashMap<usize, M>,
 978    lwe_ksk: M::R,
 979    cr_seed: S,
 980    parameters: P,
 981}
 982
 983impl<M: Matrix, S, P> SeededNonInteractiveMultiPartyServerKey<M, S, P> {
 984    pub(super) fn new(
 985        ui_to_s_ksks: Vec<M>,
 986
 987        rgsw_cts: Vec<M>,
 988        auto_keys: HashMap<usize, M>,
 989        lwe_ksk: M::R,
 990        cr_seed: S,
 991        parameters: P,
 992    ) -> Self {
 993        Self {
 994            ui_to_s_ksks,
 995
 996            rgsw_cts,
 997            auto_keys,
 998            lwe_ksk,
 999            cr_seed,
1000            parameters,
1001        }
1002    }
1003}
1004
1005pub(crate) struct ShoupNonInteractiveServerKeyEvaluationDomain<M> {
1006    /// RGSW ciphertexts ideal lwe secret key elements under ideal rlwe secret
1007    rgsw_cts: Vec<NormalAndShoup<M>>,
1008    /// Automorphism keys under ideal rlwe secret
1009    auto_keys: HashMap<usize, NormalAndShoup<M>>,
1010    /// LWE key switching key from Q -> Q_{ks}
1011    lwe_ksk: M,
1012    /// Key switching key from user j to ideal secret key s. User j's ksk is at
1013    /// j'th element
1014    ui_to_s_ksks: Vec<NormalAndShoup<M>>,
1015}
1016
1017mod impl_shoup_non_interactive_server_key_eval_domain {
1018    use itertools::Itertools;
1019    use num_traits::{FromPrimitive, PrimInt, ToPrimitive};
1020
1021    use super::*;
1022    use crate::{backend::Modulus, pbs::PbsKey};
1023
1024    impl<M> ShoupNonInteractiveServerKeyEvaluationDomain<M> {
1025        pub(in super::super) fn ui_to_s_ksk(&self, user_id: usize) -> &NormalAndShoup<M> {
1026            &self.ui_to_s_ksks[user_id]
1027        }
1028    }
1029
1030    impl<M: Matrix + ToShoup<Modulus = M::MatElement>, R, N>
1031        From<NonInteractiveServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>>
1032        for ShoupNonInteractiveServerKeyEvaluationDomain<M>
1033    where
1034        M::MatElement: FromPrimitive + ToPrimitive + PrimInt,
1035    {
1036        fn from(
1037            value: NonInteractiveServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>,
1038        ) -> Self {
1039            let rlwe_q = value.parameters.rlwe_q().q().unwrap();
1040
1041            let rgsw_dim = (
1042                value.parameters.rlwe_rgsw_decomposition_count().0 .0 * 2
1043                    + value.parameters.rlwe_rgsw_decomposition_count().1 .0 * 2,
1044                value.parameters.rlwe_n().0,
1045            );
1046            let rgsw_cts = value
1047                .rgsw_cts
1048                .into_iter()
1049                .map(|m| {
1050                    assert!(m.dimension() == rgsw_dim);
1051                    NormalAndShoup::new_with_modulus(m, rlwe_q)
1052                })
1053                .collect_vec();
1054
1055            let auto_dim = (
1056                value.parameters.auto_decomposition_count().0 * 2,
1057                value.parameters.rlwe_n().0,
1058            );
1059            let mut auto_keys = HashMap::new();
1060            value.auto_keys.into_iter().for_each(|(k, v)| {
1061                assert!(v.dimension() == auto_dim);
1062                auto_keys.insert(k, NormalAndShoup::new_with_modulus(v, rlwe_q));
1063            });
1064
1065            let ui_ks_dim = (
1066                value
1067                    .parameters
1068                    .non_interactive_ui_to_s_key_switch_decomposition_count()
1069                    .0
1070                    * 2,
1071                value.parameters.rlwe_n().0,
1072            );
1073            let ui_to_s_ksks = value
1074                .ui_to_s_ksks
1075                .into_iter()
1076                .map(|m| {
1077                    assert!(m.dimension() == ui_ks_dim);
1078                    NormalAndShoup::new_with_modulus(m, rlwe_q)
1079                })
1080                .collect_vec();
1081
1082            assert!(
1083                value.lwe_ksk.dimension()
1084                    == (
1085                        value.parameters.rlwe_n().0 * value.parameters.lwe_decomposition_count().0,
1086                        value.parameters.lwe_n().0 + 1
1087                    )
1088            );
1089
1090            Self {
1091                rgsw_cts,
1092                auto_keys,
1093                lwe_ksk: value.lwe_ksk,
1094                ui_to_s_ksks,
1095            }
1096        }
1097    }
1098
1099    impl<M: Matrix> PbsKey for ShoupNonInteractiveServerKeyEvaluationDomain<M> {
1100        type AutoKey = NormalAndShoup<M>;
1101        type LweKskKey = M;
1102        type RgswCt = NormalAndShoup<M>;
1103
1104        fn galois_key_for_auto(&self, k: usize) -> &Self::AutoKey {
1105            let d = self.auto_keys.get(&k).unwrap();
1106            d
1107        }
1108        fn rgsw_ct_lwe_si(&self, si: usize) -> &Self::RgswCt {
1109            &self.rgsw_cts[si]
1110        }
1111
1112        fn lwe_ksk(&self) -> &Self::LweKskKey {
1113            &self.lwe_ksk
1114        }
1115    }
1116}
1117
1118/// Server key in evaluation domain with Shoup representations
1119pub(crate) struct ShoupServerKeyEvaluationDomain<M> {
1120    /// Rgsw cts of LWE secret elements
1121    rgsw_cts: Vec<NormalAndShoup<M>>,
1122    /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
1123    /// to -g is at 0
1124    galois_keys: HashMap<usize, NormalAndShoup<M>>,
1125    /// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
1126    lwe_ksk: M,
1127}
1128
1129mod shoup_server_key_eval_domain {
1130    use itertools::{izip, Itertools};
1131    use num_traits::{FromPrimitive, PrimInt};
1132
1133    use crate::{backend::Modulus, pbs::PbsKey};
1134
1135    use super::*;
1136
1137    impl<M: MatrixMut + MatrixEntity + ToShoup<Modulus = M::MatElement>, R, N>
1138        From<ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>>
1139        for ShoupServerKeyEvaluationDomain<M>
1140    where
1141        <M as Matrix>::R: RowMut,
1142        M::MatElement: PrimInt + FromPrimitive,
1143    {
1144        fn from(value: ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>) -> Self {
1145            let q = value.parameters.rlwe_q().q().unwrap();
1146            // Rgsw ciphertexts
1147            let rgsw_cts = value
1148                .rgsw_cts
1149                .into_iter()
1150                .map(|ct| NormalAndShoup::new_with_modulus(ct, q))
1151                .collect_vec();
1152
1153            let mut auto_keys = HashMap::new();
1154            value.galois_keys.into_iter().for_each(|(index, key)| {
1155                auto_keys.insert(index, NormalAndShoup::new_with_modulus(key, q));
1156            });
1157
1158            Self {
1159                rgsw_cts,
1160                galois_keys: auto_keys,
1161                lwe_ksk: value.lwe_ksk,
1162            }
1163        }
1164    }
1165
1166    impl<M: Matrix> PbsKey for ShoupServerKeyEvaluationDomain<M> {
1167        type AutoKey = NormalAndShoup<M>;
1168        type LweKskKey = M;
1169        type RgswCt = NormalAndShoup<M>;
1170
1171        fn galois_key_for_auto(&self, k: usize) -> &Self::AutoKey {
1172            self.galois_keys.get(&k).unwrap()
1173        }
1174        fn rgsw_ct_lwe_si(&self, si: usize) -> &Self::RgswCt {
1175            &self.rgsw_cts[si]
1176        }
1177
1178        fn lwe_ksk(&self) -> &Self::LweKskKey {
1179            &self.lwe_ksk
1180        }
1181    }
1182}
1183
1184pub struct CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M: Matrix, S> {
1185    /// Non-interactive RGSW ciphertexts for secret indices for which user is
1186    /// the leader
1187    self_leader_ni_rgsw_cts: Vec<M>,
1188    /// Non-interactive RGSW ciphertexts for secret indices for which user is
1189    /// not the leader
1190    not_self_leader_ni_rgsw_cts: Vec<M>,
1191    /// Zero encryptions for RGSW ciphertexts for all indicces
1192    ni_rgsw_zero_encs: Vec<M>,
1193
1194    /// (ak*si + e + \beta ui, ak*si + e)
1195    ui_to_s_ksk: M,
1196    ksk_zero_encs_for_others: Vec<M>,
1197
1198    auto_keys_share: HashMap<usize, M>,
1199    lwe_ksk_share: M::R,
1200
1201    user_index: usize,
1202    total_users: usize,
1203    lwe_n: usize,
1204    cr_seed: S,
1205}
1206
1207mod impl_common_ref_non_interactive_multi_party_server_share {
1208    use crate::evaluator::interactive_mult_party_user_id_lwe_segment;
1209
1210    use super::*;
1211
1212    impl<M: Matrix, S> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M, S> {
1213        pub(in super::super) fn new(
1214            self_leader_ni_rgsw_cts: Vec<M>,
1215            not_self_leader_ni_rgsw_cts: Vec<M>,
1216            ni_rgsw_zero_encs: Vec<M>,
1217            ui_to_s_ksk: M,
1218            ksk_zero_encs_for_others: Vec<M>,
1219            auto_keys_share: HashMap<usize, M>,
1220            lwe_ksk_share: M::R,
1221            user_index: usize,
1222            total_users: usize,
1223            lwe_n: usize,
1224            cr_seed: S,
1225        ) -> Self {
1226            Self {
1227                self_leader_ni_rgsw_cts,
1228                not_self_leader_ni_rgsw_cts,
1229                ni_rgsw_zero_encs,
1230                ui_to_s_ksk,
1231                ksk_zero_encs_for_others,
1232                auto_keys_share,
1233                lwe_ksk_share,
1234                user_index,
1235                total_users,
1236                lwe_n,
1237                cr_seed,
1238            }
1239        }
1240
1241        pub(in super::super) fn ni_rgsw_cts_for_self_leader_lwe_index(
1242            &self,
1243            lwe_index: usize,
1244        ) -> &M {
1245            let self_segment = interactive_mult_party_user_id_lwe_segment(
1246                self.user_index,
1247                self.total_users,
1248                self.lwe_n,
1249            );
1250            assert!(lwe_index >= self_segment.0 && lwe_index < self_segment.1);
1251            &self.self_leader_ni_rgsw_cts[lwe_index - self_segment.0]
1252        }
1253
1254        pub(in super::super) fn ni_rgsw_cts_for_self_not_leader_lwe_index(
1255            &self,
1256            lwe_index: usize,
1257        ) -> &M {
1258            let self_segment = interactive_mult_party_user_id_lwe_segment(
1259                self.user_index,
1260                self.total_users,
1261                self.lwe_n,
1262            );
1263            // Non-interactive RGSW cts when self is not leader are stored in
1264            // sorted-order. For ex, if self is the leader for indices (5, 6]
1265            // then self stores NI-RGSW cts for rest of indices like [0, 1, 2,
1266            // 3, 4, 6, 7, 8, 9]
1267            assert!(lwe_index < self.lwe_n);
1268            assert!(lwe_index < self_segment.0 || lwe_index >= self_segment.1);
1269            if lwe_index < self_segment.0 {
1270                &self.not_self_leader_ni_rgsw_cts[lwe_index]
1271            } else {
1272                &self.not_self_leader_ni_rgsw_cts[lwe_index - (self_segment.1 - self_segment.0)]
1273            }
1274        }
1275
1276        pub(in super::super) fn ni_rgsw_zero_enc_for_lwe_index(&self, lwe_index: usize) -> &M {
1277            &self.ni_rgsw_zero_encs[lwe_index]
1278        }
1279
1280        pub(in super::super) fn ui_to_s_ksk(&self) -> &M {
1281            &self.ui_to_s_ksk
1282        }
1283
1284        pub(in super::super) fn user_index(&self) -> usize {
1285            self.user_index
1286        }
1287
1288        pub(in super::super) fn auto_keys_share(&self) -> &HashMap<usize, M> {
1289            &self.auto_keys_share
1290        }
1291
1292        pub(in super::super) fn lwe_ksk_share(&self) -> &M::R {
1293            &self.lwe_ksk_share
1294        }
1295
1296        pub(in super::super) fn ui_to_s_ksk_zero_encs_for_user_i(&self, user_i: usize) -> &M {
1297            assert!(user_i != self.user_index);
1298            if user_i < self.user_index {
1299                &self.ksk_zero_encs_for_others[user_i]
1300            } else {
1301                &self.ksk_zero_encs_for_others[user_i - 1]
1302            }
1303        }
1304    }
1305}
1306
1307/// Stores normal and shoup representation of Matrix elements (Normal, Shoup)
1308pub(crate) struct NormalAndShoup<M>(M, M);
1309
1310impl<M: ToShoup> NormalAndShoup<M> {
1311    fn new_with_modulus(value: M, modulus: <M as ToShoup>::Modulus) -> Self {
1312        let value_shoup = M::to_shoup(&value, modulus);
1313        NormalAndShoup(value, value_shoup)
1314    }
1315}
1316
1317impl<M> AsRef<M> for NormalAndShoup<M> {
1318    fn as_ref(&self) -> &M {
1319        &self.0
1320    }
1321}
1322
1323impl<M> WithShoupRepr for NormalAndShoup<M> {
1324    type M = M;
1325    fn shoup_repr(&self) -> &Self::M {
1326        &self.1
1327    }
1328}
1329
1330pub(super) mod tests {
1331    use itertools::izip;
1332    use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Zero};
1333
1334    use crate::{
1335        backend::{GetModulus, Modulus},
1336        bool::ClientKey,
1337        lwe::decrypt_lwe,
1338        parameters::CiphertextModulus,
1339        utils::TryConvertFrom1,
1340        ArithmeticOps, Row,
1341    };
1342
1343    use super::SinglePartyClientKey;
1344
1345    pub(crate) fn ideal_sk_rlwe(cks: &[ClientKey]) -> Vec<i32> {
1346        let mut ideal_rlwe_sk = cks[0].sk_rlwe();
1347        cks.iter().skip(1).for_each(|k| {
1348            let sk_rlwe = k.sk_rlwe();
1349            izip!(ideal_rlwe_sk.iter_mut(), sk_rlwe.iter()).for_each(|(a, b)| {
1350                *a = *a + b;
1351            });
1352        });
1353        ideal_rlwe_sk
1354    }
1355
1356    pub(crate) fn ideal_sk_lwe(cks: &[ClientKey]) -> Vec<i32> {
1357        let mut ideal_rlwe_sk = cks[0].sk_lwe();
1358        cks.iter().skip(1).for_each(|k| {
1359            let sk_rlwe = k.sk_lwe();
1360            izip!(ideal_rlwe_sk.iter_mut(), sk_rlwe.iter()).for_each(|(a, b)| {
1361                *a = *a + b;
1362            });
1363        });
1364        ideal_rlwe_sk
1365    }
1366
1367    pub(crate) fn measure_noise_lwe<
1368        R: Row,
1369        S,
1370        Modop: ArithmeticOps<Element = R::Element>
1371            + GetModulus<M = CiphertextModulus<R::Element>, Element = R::Element>,
1372    >(
1373        lwe_ct: &R,
1374        m_expected: R::Element,
1375        sk: &[S],
1376        modop: &Modop,
1377    ) -> f64
1378    where
1379        R: TryConvertFrom1<[S], CiphertextModulus<R::Element>>,
1380        R::Element: Zero + FromPrimitive + PrimInt,
1381    {
1382        let noisy_m = decrypt_lwe(lwe_ct, &sk, modop);
1383        let noise = modop.sub(&m_expected, &noisy_m);
1384        modop
1385            .modulus()
1386            .map_element_to_i64(&noise)
1387            .abs()
1388            .to_f64()
1389            .unwrap()
1390            .log2()
1391    }
1392}