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>;
19pub type FheBool = impl_bool_frontend::FheBool<Vec<u64>>;
20
21pub(crate) trait BooleanGates {
22 type Ciphertext: RowEntity;
23 type Key;
24
25 fn and_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
26 fn nand_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
27 fn or_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
28 fn nor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
29 fn xor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
30 fn xnor_inplace(&mut self, c0: &mut Self::Ciphertext, c1: &Self::Ciphertext, key: &Self::Key);
31 fn not_inplace(&self, c: &mut Self::Ciphertext);
32
33 fn and(
34 &mut self,
35 c0: &Self::Ciphertext,
36 c1: &Self::Ciphertext,
37 key: &Self::Key,
38 ) -> Self::Ciphertext;
39 fn nand(
40 &mut self,
41 c0: &Self::Ciphertext,
42 c1: &Self::Ciphertext,
43 key: &Self::Key,
44 ) -> Self::Ciphertext;
45 fn or(
46 &mut self,
47 c0: &Self::Ciphertext,
48 c1: &Self::Ciphertext,
49 key: &Self::Key,
50 ) -> Self::Ciphertext;
51 fn nor(
52 &mut self,
53 c0: &Self::Ciphertext,
54 c1: &Self::Ciphertext,
55 key: &Self::Key,
56 ) -> Self::Ciphertext;
57 fn xor(
58 &mut self,
59 c0: &Self::Ciphertext,
60 c1: &Self::Ciphertext,
61 key: &Self::Key,
62 ) -> Self::Ciphertext;
63 fn xnor(
64 &mut self,
65 c0: &Self::Ciphertext,
66 c1: &Self::Ciphertext,
67 key: &Self::Key,
68 ) -> Self::Ciphertext;
69 fn not(&self, c: &Self::Ciphertext) -> Self::Ciphertext;
70}
71
72mod impl_bool_frontend {
73 use crate::MultiPartyDecryptor;
74
75 /// Fhe Bool ciphertext
76 #[derive(Clone)]
77 pub struct FheBool<C> {
78 pub(crate) data: C,
79 }
80
81 impl<C> FheBool<C> {
82 pub(crate) fn data(&self) -> &C {
83 &self.data
84 }
85
86 pub(crate) fn data_mut(&mut self) -> &mut C {
87 &mut self.data
88 }
89 }
90
91 impl<C, K> MultiPartyDecryptor<bool, FheBool<C>> for K
92 where
93 K: MultiPartyDecryptor<bool, C>,
94 {
95 type DecryptionShare = <K as MultiPartyDecryptor<bool, C>>::DecryptionShare;
96
97 fn aggregate_decryption_shares(
98 &self,
99 c: &FheBool<C>,
100 shares: &[Self::DecryptionShare],
101 ) -> bool {
102 self.aggregate_decryption_shares(&c.data, shares)
103 }
104
105 fn gen_decryption_share(&self, c: &FheBool<C>) -> Self::DecryptionShare {
106 self.gen_decryption_share(&c.data)
107 }
108 }
109
110 mod ops {
111 use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
112
113 use crate::{
114 utils::{Global, WithLocal},
115 BooleanGates,
116 };
117
118 use super::super::{BoolEvaluator, RuntimeServerKey};
119
120 type FheBool = super::super::FheBool;
121
122 impl BitAnd for &FheBool {
123 type Output = FheBool;
124 fn bitand(self, rhs: Self) -> Self::Output {
125 BoolEvaluator::with_local_mut(|e| {
126 let key = RuntimeServerKey::global();
127 FheBool {
128 data: e.and(self.data(), rhs.data(), key),
129 }
130 })
131 }
132 }
133
134 impl BitAndAssign for FheBool {
135 fn bitand_assign(&mut self, rhs: Self) {
136 BoolEvaluator::with_local_mut_mut(&mut |e| {
137 let key = RuntimeServerKey::global();
138 e.and_inplace(&mut self.data_mut(), rhs.data(), key);
139 });
140 }
141 }
142
143 impl BitOr for &FheBool {
144 type Output = FheBool;
145 fn bitor(self, rhs: Self) -> Self::Output {
146 BoolEvaluator::with_local_mut(|e| {
147 let key = RuntimeServerKey::global();
148 FheBool {
149 data: e.or(self.data(), rhs.data(), key),
150 }
151 })
152 }
153 }
154
155 impl BitOrAssign for FheBool {
156 fn bitor_assign(&mut self, rhs: Self) {
157 BoolEvaluator::with_local_mut_mut(&mut |e| {
158 let key = RuntimeServerKey::global();
159 e.or_inplace(&mut self.data_mut(), rhs.data(), key);
160 });
161 }
162 }
163
164 impl BitXor for &FheBool {
165 type Output = FheBool;
166 fn bitxor(self, rhs: Self) -> Self::Output {
167 BoolEvaluator::with_local_mut(|e| {
168 let key = RuntimeServerKey::global();
169 FheBool {
170 data: e.xor(self.data(), rhs.data(), key),
171 }
172 })
173 }
174 }
175
176 impl BitXorAssign for FheBool {
177 fn bitxor_assign(&mut self, rhs: Self) {
178 BoolEvaluator::with_local_mut_mut(&mut |e| {
179 let key = RuntimeServerKey::global();
180 e.xor_inplace(&mut self.data_mut(), rhs.data(), key);
181 });
182 }
183 }
184
185 impl Not for &FheBool {
186 type Output = FheBool;
187 fn not(self) -> Self::Output {
188 BoolEvaluator::with_local(|e| FheBool {
189 data: e.not(self.data()),
190 })
191 }
192 }
193 }
194}
195
196mod common_mp_enc_dec {
197 use itertools::Itertools;
198
199 use super::BoolEvaluator;
200 use crate::{
201 pbs::{sample_extract, PbsInfo},
202 utils::WithLocal,
203 Matrix, MultiPartyDecryptor, RowEntity, SampleExtractor,
204 };
205
206 type Mat = Vec<Vec<u64>>;
207
208 impl<E> MultiPartyDecryptor<bool, <Mat as Matrix>::R> for super::keys::ClientKey<[u8; 32], E> {
209 type DecryptionShare = <Mat as Matrix>::MatElement;
210
211 /// Generate multi-party decryption share for LWE ciphertext `c`
212 fn gen_decryption_share(&self, c: &<Mat as Matrix>::R) -> Self::DecryptionShare {
213 BoolEvaluator::with_local(|e| e.multi_party_decryption_share(c, self))
214 }
215
216 /// Aggregate mult-party decryptions shares of all parties, decrypt LWE
217 /// ciphertext `c`, and return the bool plaintext
218 fn aggregate_decryption_shares(
219 &self,
220 c: &<Mat as Matrix>::R,
221 shares: &[Self::DecryptionShare],
222 ) -> bool {
223 BoolEvaluator::with_local(|e| e.multi_party_decrypt(shares, c))
224 }
225 }
226
227 impl SampleExtractor<<Mat as Matrix>::R> for Mat {
228 /// Sample extract coefficient at `index` as a LWE ciphertext from RLWE
229 /// ciphertext `Self`
230 fn extract_at(&self, index: usize) -> <Mat as Matrix>::R {
231 // input is RLWE ciphertext
232 assert!(self.dimension().0 == 2);
233
234 let ring_size = self.dimension().1;
235 assert!(index < ring_size);
236
237 BoolEvaluator::with_local(|e| {
238 let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
239 sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
240 lwe_out
241 })
242 }
243
244 /// Extract first `how_many` coefficients of `Self` as LWE ciphertexts
245 fn extract_many(&self, how_many: usize) -> Vec<<Mat as Matrix>::R> {
246 assert!(self.dimension().0 == 2);
247
248 let ring_size = self.dimension().1;
249 assert!(how_many <= ring_size);
250
251 (0..how_many)
252 .map(|index| {
253 BoolEvaluator::with_local(|e| {
254 let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
255 sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
256 lwe_out
257 })
258 })
259 .collect_vec()
260 }
261
262 /// Extracts all coefficients of `Self` as LWE ciphertexts
263 fn extract_all(&self) -> Vec<<Mat as Matrix>::R> {
264 assert!(self.dimension().0 == 2);
265
266 let ring_size = self.dimension().1;
267
268 (0..ring_size)
269 .map(|index| {
270 BoolEvaluator::with_local(|e| {
271 let mut lwe_out = <Mat as Matrix>::R::zeros(ring_size + 1);
272 sample_extract(&mut lwe_out, self, e.pbs_info().modop_rlweq(), index);
273 lwe_out
274 })
275 })
276 .collect_vec()
277 }
278 }
279}
280
281#[cfg(test)]
282mod print_noise;