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().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;