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(crate) 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().0;
271
272                let 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                    out.push(FheBool {
279                        data: SampleExtractor::extract_at(&self.data[col], row),
280                    });
281                }
282
283                out
284            } else {
285                vec![]
286            }
287        }
288        fn extract_at(&self, index: usize) -> FheBool<M::R> {
289            assert!(self.count > index);
290
291            let ring_size = self.data[0].dimension().0;
292            let row = index % ring_size;
293            let col = index / ring_size;
294
295            FheBool {
296                data: SampleExtractor::extract_at(&self.data[col], row),
297            }
298        }
299
300        fn extract_many(&self, how_many: usize) -> Vec<FheBool<M::R>> {
301            assert!(self.count >= how_many);
302            let ring_size = self.data[0].dimension().0;
303
304            let index = 0;
305            let mut out = Vec::with_capacity(self.count);
306
307            while index < how_many {
308                let row = index % ring_size;
309                let col = index / ring_size;
310                out.push(FheBool {
311                    data: SampleExtractor::extract_at(&self.data[col], row),
312                });
313            }
314
315            out
316        }
317    }
318
319    impl SampleExtractor<<Mat as Matrix>::R> for Mat {
320        /// Sample extract coefficient at `index` as a LWE ciphertext from RLWE
321        /// ciphertext `Self`
322        fn extract_at(&self, index: usize) -> <Mat as Matrix>::R {
323            // input is RLWE ciphertext
324            assert!(self.dimension().0 == 2);
325
326            let ring_size = self.dimension().1;
327            assert!(index < ring_size);
328
329            BoolEvaluator::with_local(|e| {
330                let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
331                sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
332                lwe_out
333            })
334        }
335
336        /// Extract first `how_many` coefficients of `Self` as LWE ciphertexts
337        fn extract_many(&self, how_many: usize) -> Vec<<Mat as Matrix>::R> {
338            assert!(self.dimension().0 == 2);
339
340            let ring_size = self.dimension().1;
341            assert!(how_many <= ring_size);
342
343            (0..how_many)
344                .map(|index| {
345                    BoolEvaluator::with_local(|e| {
346                        let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
347                        sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
348                        lwe_out
349                    })
350                })
351                .collect_vec()
352        }
353
354        /// Extracts all coefficients of `Self` as LWE ciphertexts
355        fn extract_all(&self) -> Vec<<Mat as Matrix>::R> {
356            assert!(self.dimension().0 == 2);
357
358            let ring_size = self.dimension().1;
359
360            (0..ring_size)
361                .map(|index| {
362                    BoolEvaluator::with_local(|e| {
363                        let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
364                        sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
365                        lwe_out
366                    })
367                })
368                .collect_vec()
369        }
370    }
371}
372
373#[cfg(test)]
374mod print_noise;