arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
phantom-zone/src/bool/mod.rs
src/bool/mod.rsRaw
  1mod evaluator;
  2mod keys;
  3pub(crate) mod parameters;
  4
  5#[cfg(feature = "interactive_mp")]
  6mod mp_api;
  7#[cfg(feature = "non_interactive_mp")]
  8mod ni_mp_api;
  9
 10#[cfg(feature = "non_interactive_mp")]
 11pub use ni_mp_api::*;
 12
 13#[cfg(feature = "interactive_mp")]
 14pub use mp_api::*;
 15
 16use crate::RowEntity;
 17
 18pub type ClientKey = keys::ClientKey<[u8; 32], u64>;
 19#[cfg(any(feature = "interactive_mp", feature = "non_interactive_mp"))]
 20pub type FheBool = impl_bool_frontend::FheBool<Vec<u64>>;
 21
 22pub(crate) trait BooleanGates {
 23    type Ciphertext: RowEntity;
 24    type Key;
 25
 26    fn and_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
 27    fn nand_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
 28    fn or_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
 29    fn nor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
 30    fn xor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
 31    fn xnor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
 32    fn not_inplace(&self, c: &mut Self::Ciphertext);
 33
 34    fn and(
 35        &mut self,
 36        c0: &Self::Ciphertext,
 37        c1: &Self::Ciphertext,
 38        key: &Self::Key,
 39    ) -> Self::Ciphertext;
 40    fn nand(
 41        &mut self,
 42        c0: &Self::Ciphertext,
 43        c1: &Self::Ciphertext,
 44        key: &Self::Key,
 45    ) -> Self::Ciphertext;
 46    fn or(
 47        &mut self,
 48        c0: &Self::Ciphertext,
 49        c1: &Self::Ciphertext,
 50        key: &Self::Key,
 51    ) -> Self::Ciphertext;
 52    fn nor(
 53        &mut self,
 54        c0: &Self::Ciphertext,
 55        c1: &Self::Ciphertext,
 56        key: &Self::Key,
 57    ) -> Self::Ciphertext;
 58    fn xor(
 59        &mut self,
 60        c0: &Self::Ciphertext,
 61        c1: &Self::Ciphertext,
 62        key: &Self::Key,
 63    ) -> Self::Ciphertext;
 64    fn xnor(
 65        &mut self,
 66        c0: &Self::Ciphertext,
 67        c1: &Self::Ciphertext,
 68        key: &Self::Key,
 69    ) -> Self::Ciphertext;
 70    fn not(&self, c: &Self::Ciphertext) -> Self::Ciphertext;
 71}
 72
 73#[cfg(any(feature = "interactive_mp", feature = "non_interactive_mp"))]
 74mod impl_bool_frontend {
 75    use crate::MultiPartyDecryptor;
 76
 77    /// Fhe Bool ciphertext
 78    #[derive(Clone)]
 79    pub struct FheBool<C> {
 80        /// LWE bool ciphertext
 81        pub(crate) data: C,
 82    }
 83
 84    impl<C> FheBool<C> {
 85        pub(crate) fn data(&self) -> &C {
 86            &self.data
 87        }
 88
 89        pub(crate) fn data_mut(&mut self) -> &mut C {
 90            &mut self.data
 91        }
 92    }
 93
 94    impl<C, K> MultiPartyDecryptor<bool, FheBool<C>> for K
 95    where
 96        K: MultiPartyDecryptor<bool, C>,
 97    {
 98        type DecryptionShare = <K as MultiPartyDecryptor<bool, C>>::DecryptionShare;
 99
100        fn aggregate_decryption_shares(
101            &self,
102            c: &FheBool<C>,
103            shares: &[Self::DecryptionShare],
104        ) -> bool {
105            self.aggregate_decryption_shares(&c.data(), shares)
106        }
107
108        fn gen_decryption_share(&self, c: &FheBool<C>) -> Self::DecryptionShare {
109            self.gen_decryption_share(&c.data())
110        }
111    }
112
113    mod ops {
114        use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
115
116        use crate::{
117            utils::{Global, WithLocal},
118            BooleanGates,
119        };
120
121        use super::super::{BoolEvaluator, RuntimeServerKey};
122
123        type FheBool = super::super::FheBool;
124
125        impl BitAnd for &FheBool {
126            type Output = FheBool;
127            fn bitand(self, rhs: Self) -> Self::Output {
128                BoolEvaluator::with_local_mut(|e| {
129                    let key = RuntimeServerKey::global();
130                    FheBool {
131                        data: e.and(self.data(), rhs.data(), key),
132                    }
133                })
134            }
135        }
136
137        impl BitAndAssign for FheBool {
138            fn bitand_assign(&mut self, rhs: Self) {
139                BoolEvaluator::with_local_mut_mut(&mut |e| {
140                    let key = RuntimeServerKey::global();
141                    e.and_inplace(&mut self.data_mut(), rhs.data(), key);
142                });
143            }
144        }
145
146        impl BitOr for &FheBool {
147            type Output = FheBool;
148            fn bitor(self, rhs: Self) -> Self::Output {
149                BoolEvaluator::with_local_mut(|e| {
150                    let key = RuntimeServerKey::global();
151                    FheBool {
152                        data: e.or(self.data(), rhs.data(), key),
153                    }
154                })
155            }
156        }
157
158        impl BitOrAssign for FheBool {
159            fn bitor_assign(&mut self, rhs: Self) {
160                BoolEvaluator::with_local_mut_mut(&mut |e| {
161                    let key = RuntimeServerKey::global();
162                    e.or_inplace(&mut self.data_mut(), rhs.data(), key);
163                });
164            }
165        }
166
167        impl BitXor for &FheBool {
168            type Output = FheBool;
169            fn bitxor(self, rhs: Self) -> Self::Output {
170                BoolEvaluator::with_local_mut(|e| {
171                    let key = RuntimeServerKey::global();
172                    FheBool {
173                        data: e.xor(self.data(), rhs.data(), key),
174                    }
175                })
176            }
177        }
178
179        impl BitXorAssign for FheBool {
180            fn bitxor_assign(&mut self, rhs: Self) {
181                BoolEvaluator::with_local_mut_mut(&mut |e| {
182                    let key = RuntimeServerKey::global();
183                    e.xor_inplace(&mut self.data_mut(), rhs.data(), key);
184                });
185            }
186        }
187
188        impl Not for &FheBool {
189            type Output = FheBool;
190            fn not(self) -> Self::Output {
191                BoolEvaluator::with_local(|e| FheBool {
192                    data: e.not(self.data()),
193                })
194            }
195        }
196
197        impl FheBool {
198            pub fn nand(&self, rhs: &Self) -> Self {
199                BoolEvaluator::with_local_mut(|e| {
200                    let key = RuntimeServerKey::global();
201                    FheBool {
202                        data: e.nand(self.data(), rhs.data(), key),
203                    }
204                })
205            }
206
207            pub fn xnor(&self, rhs: &Self) -> Self {
208                BoolEvaluator::with_local_mut(|e| {
209                    let key = RuntimeServerKey::global();
210                    FheBool {
211                        data: e.xnor(self.data(), rhs.data(), key),
212                    }
213                })
214            }
215
216            pub fn nor(&self, rhs: &Self) -> Self {
217                BoolEvaluator::with_local_mut(|e| {
218                    let key = RuntimeServerKey::global();
219                    FheBool {
220                        data: e.nor(self.data(), rhs.data(), key),
221                    }
222                })
223            }
224        }
225    }
226}
227
228#[cfg(any(feature = "interactive_mp", feature = "non_interactive_mp"))]
229mod common_mp_enc_dec {
230    use itertools::Itertools;
231
232    use super::{impl_bool_frontend::FheBool, BoolEvaluator};
233    use crate::{
234        pbs::{sample_extract, PbsInfo},
235        utils::WithLocal,
236        Matrix, RowEntity, SampleExtractor,
237    };
238
239    type Mat = Vec<Vec<u64>>;
240
241    /// `Self` stores batch of boolean ciphertexts as collection of `unseeded RLWE ciphertexts` encrypted under the ideal RLWE secret key of the protocol.
242    ///
243    /// Bool ciphertext at `index` can be extracted from the coefficient at `index %
244    /// N` of `index / N`th RLWE ciphertext.
245    pub struct BatchedFheBools<C> {
246        data: Vec<C>,
247        count: usize,
248    }
249
250    impl<C> BatchedFheBools<C> {
251        pub(crate) fn new(data: Vec<C>, count: usize) -> Self {
252            Self { data, count }
253        }
254
255        pub(crate) fn data(&self) -> &[C] {
256            &self.data
257        }
258
259        pub(crate) fn count(&self) -> usize {
260            self.count
261        }
262    }
263
264    impl<M: Matrix> SampleExtractor<FheBool<M::R>> for BatchedFheBools<M>
265    where
266        M: SampleExtractor<M::R>,
267    {
268        fn extract_all(&self) -> Vec<FheBool<M::R>> {
269            if self.data.len() > 0 {
270                let ring_size = self.data[0].dimension().1;
271
272                let mut index = 0;
273                let mut out = Vec::with_capacity(self.count);
274
275                while index < self.count {
276                    let row = index % ring_size;
277                    let col = index / ring_size;
278
279                    out.push(FheBool {
280                        data: SampleExtractor::extract_at(&self.data[col], row),
281                    });
282                    index += 1;
283                }
284
285                out
286            } else {
287                vec![]
288            }
289        }
290        fn extract_at(&self, index: usize) -> FheBool<M::R> {
291            assert!(self.count > index);
292
293            let ring_size = self.data[0].dimension().1;
294            let row = index % ring_size;
295            let col = index / ring_size;
296
297            FheBool {
298                data: SampleExtractor::extract_at(&self.data[col], row),
299            }
300        }
301
302        fn extract_many(&self, how_many: usize) -> Vec<FheBool<M::R>> {
303            assert!(self.count >= how_many);
304            let ring_size = self.data[0].dimension().1;
305
306            let mut index = 0;
307            let mut out = Vec::with_capacity(self.count);
308
309            while index < how_many {
310                let row = index % ring_size;
311                let col = index / ring_size;
312                out.push(FheBool {
313                    data: SampleExtractor::extract_at(&self.data[col], row),
314                });
315                index += 1;
316            }
317
318            out
319        }
320    }
321
322    impl SampleExtractor<<Mat as Matrix>::R> for Mat {
323        /// Sample extract coefficient at `index` as a LWE ciphertext from RLWE
324        /// ciphertext `Self`
325        fn extract_at(&self, index: usize) -> <Mat as Matrix>::R {
326            // input is RLWE ciphertext
327            assert!(self.dimension().0 == 2);
328
329            let ring_size = self.dimension().1;
330            assert!(index < ring_size);
331
332            BoolEvaluator::with_local(|e| {
333                let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
334                sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
335                lwe_out
336            })
337        }
338
339        /// Extract first `how_many` coefficients of `Self` as LWE ciphertexts
340        fn extract_many(&self, how_many: usize) -> Vec<<Mat as Matrix>::R> {
341            assert!(self.dimension().0 == 2);
342
343            let ring_size = self.dimension().1;
344            assert!(how_many <= ring_size);
345
346            (0..how_many)
347                .map(|index| {
348                    BoolEvaluator::with_local(|e| {
349                        let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
350                        sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
351                        lwe_out
352                    })
353                })
354                .collect_vec()
355        }
356
357        /// Extracts all coefficients of `Self` as LWE ciphertexts
358        fn extract_all(&self) -> Vec<<Mat as Matrix>::R> {
359            assert!(self.dimension().0 == 2);
360
361            let ring_size = self.dimension().1;
362
363            (0..ring_size)
364                .map(|index| {
365                    BoolEvaluator::with_local(|e| {
366                        let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
367                        sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
368                        lwe_out
369                    })
370                })
371                .collect_vec()
372        }
373    }
374}
375
376#[cfg(test)]
377mod print_noise;