poulpy/poulpy-schemes/src/tfhe/bdd_arithmetic/key.rs
poulpy-schemes/src/tfhe/bdd_arithmetic/key.rsRaw
1use crate::tfhe::bdd_arithmetic::FheUintPreparedDebug;
2use crate::tfhe::circuit_bootstrapping::CircuitBootstrappingKeyInfos;
3use crate::tfhe::{
4 bdd_arithmetic::{FheUint, UnsignedInteger},
5 blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory},
6 circuit_bootstrapping::{
7 CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout,
8 CircuitBootstrappingKeyPrepared, CircuitBootstrappingKeyPreparedFactory,
9 },
10};
11
12use poulpy_core::GLWESwitchingKeyEncryptSk;
13use poulpy_core::layouts::{
14 GGLWEInfos, GLWEAutomorphismKeyHelper, GLWEAutomorphismKeyPrepared, GLWESecret, GLWESwitchingKey, GLWESwitchingKeyLayout,
15 GLWESwitchingKeyPrepared,
16};
17use poulpy_core::{
18 GLWEToLWESwitchingKeyEncryptSk, GetDistribution, ScratchTakeCore,
19 layouts::{
20 GLWEInfos, GLWESecretToRef, GLWEToLWEKey, GLWEToLWEKeyLayout, GLWEToLWEKeyPreparedFactory, LWEInfos, LWESecretToRef,
21 prepared::GLWEToLWEKeyPrepared,
22 },
23};
24use poulpy_hal::{
25 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
26 source::Source,
27};
28
29pub trait BDDKeyInfos {
30 fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout;
31 fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout;
32 fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout>;
33}
34
35#[derive(Debug, Clone, Copy)]
36pub struct BDDKeyLayout {
37 pub cbt: CircuitBootstrappingKeyLayout,
38 pub ks_glwe: Option<GLWESwitchingKeyLayout>,
39 pub ks_lwe: GLWEToLWEKeyLayout,
40}
41
42impl BDDKeyInfos for BDDKeyLayout {
43 fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
44 self.cbt
45 }
46
47 fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
48 self.ks_glwe
49 }
50
51 fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout {
52 self.ks_lwe
53 }
54}
55
56pub struct BDDKey<D, BRA>
57where
58 D: Data,
59 BRA: BlindRotationAlgo,
60{
61 pub(crate) cbt: CircuitBootstrappingKey<D, BRA>,
62 pub(crate) ks_glwe: Option<GLWESwitchingKey<D>>,
63 pub(crate) ks_lwe: GLWEToLWEKey<D>,
64}
65
66impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, BRA>
67where
68 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
69{
70 pub fn alloc_from_infos<A>(infos: &A) -> Self
71 where
72 A: BDDKeyInfos,
73 {
74 let ks_glwe: Option<GLWESwitchingKey<Vec<u8>>> = if let Some(ks_infos) = &infos.ks_glwe_infos() {
75 Some(GLWESwitchingKey::alloc_from_infos(ks_infos))
76 } else {
77 None
78 };
79
80 Self {
81 cbt: CircuitBootstrappingKey::alloc_from_infos(&infos.cbt_infos()),
82 ks_glwe: ks_glwe,
83 ks_lwe: GLWEToLWEKey::alloc_from_infos(&infos.ks_lwe_infos()),
84 }
85 }
86}
87
88pub trait BDDKeyEncryptSk<BRA: BlindRotationAlgo, BE: Backend> {
89 fn bdd_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
90 where
91 A: BDDKeyInfos;
92
93 fn bdd_key_encrypt_sk<D, S0, S1>(
94 &self,
95 res: &mut BDDKey<D, BRA>,
96 sk_lwe: &S0,
97 sk_glwe: &S1,
98 source_xa: &mut Source,
99 source_xe: &mut Source,
100 scratch: &mut Scratch<BE>,
101 ) where
102 D: DataMut,
103 S0: LWESecretToRef + GetDistribution + LWEInfos,
104 S1: GLWESecretToRef + GetDistribution + GLWEInfos;
105}
106
107impl<BE: Backend, BRA: BlindRotationAlgo> BDDKeyEncryptSk<BRA, BE> for Module<BE>
108where
109 Self: CircuitBootstrappingKeyEncryptSk<BRA, BE> + GLWEToLWESwitchingKeyEncryptSk<BE> + GLWESwitchingKeyEncryptSk<BE>,
110 Scratch<BE>: ScratchTakeCore<BE>,
111{
112 fn bdd_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
113 where
114 A: BDDKeyInfos,
115 {
116 self.circuit_bootstrapping_key_encrypt_sk_tmp_bytes(&infos.cbt_infos())
117 .max(self.glwe_to_lwe_key_encrypt_sk_tmp_bytes(&infos.ks_lwe_infos()))
118 }
119
120 fn bdd_key_encrypt_sk<D, S0, S1>(
121 &self,
122 res: &mut BDDKey<D, BRA>,
123 sk_lwe: &S0,
124 sk_glwe: &S1,
125 source_xa: &mut Source,
126 source_xe: &mut Source,
127 scratch: &mut Scratch<BE>,
128 ) where
129 D: DataMut,
130 S0: LWESecretToRef + GetDistribution + LWEInfos,
131 S1: GLWESecretToRef + GetDistribution + GLWEInfos,
132 {
133 if let Some(key) = &mut res.ks_glwe {
134 let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(sk_glwe.n(), key.rank_out());
135 sk_out.fill_ternary_prob(0.5, source_xe);
136 key.encrypt_sk(self, sk_glwe, &sk_out, source_xa, source_xe, scratch);
137 res.ks_lwe
138 .encrypt_sk(self, sk_lwe, &sk_out, source_xa, source_xe, scratch);
139 } else {
140 res.ks_lwe
141 .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
142 }
143
144 res.cbt
145 .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
146 }
147}
148
149impl<D: DataMut, BRA: BlindRotationAlgo> BDDKey<D, BRA> {
150 pub fn encrypt_sk<S0, S1, M, BE: Backend>(
151 &mut self,
152 module: &M,
153 sk_lwe: &S0,
154 sk_glwe: &S1,
155 source_xa: &mut Source,
156 source_xe: &mut Source,
157 scratch: &mut Scratch<BE>,
158 ) where
159 S0: LWESecretToRef + GetDistribution + LWEInfos,
160 S1: GLWESecretToRef + GetDistribution + GLWEInfos,
161 M: BDDKeyEncryptSk<BRA, BE>,
162 Scratch<BE>: ScratchTakeCore<BE>,
163 {
164 module.bdd_key_encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
165 }
166}
167
168pub struct BDDKeyPrepared<D, BRA, BE>
169where
170 D: Data,
171 BRA: BlindRotationAlgo,
172 BE: Backend,
173{
174 pub(crate) cbt: CircuitBootstrappingKeyPrepared<D, BRA, BE>,
175 pub(crate) ks_glwe: Option<GLWESwitchingKeyPrepared<D, BE>>,
176 pub(crate) ks_lwe: GLWEToLWEKeyPrepared<D, BE>,
177}
178
179impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BDDKeyInfos for BDDKeyPrepared<D, BRA, BE> {
180 fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
181 CircuitBootstrappingKeyLayout {
182 layout_brk: self.cbt.brk_infos(),
183 layout_atk: self.cbt.atk_infos(),
184 layout_tsk: self.cbt.tsk_infos(),
185 }
186 }
187 fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
188 if let Some(ks_glwe) = &self.ks_glwe {
189 Some(GLWESwitchingKeyLayout {
190 n: ks_glwe.n(),
191 base2k: ks_glwe.base2k(),
192 k: ks_glwe.k(),
193 rank_in: ks_glwe.rank_in(),
194 rank_out: ks_glwe.rank_out(),
195 dnum: ks_glwe.dnum(),
196 dsize: ks_glwe.dsize(),
197 })
198 } else {
199 None
200 }
201 }
202 fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout {
203 GLWEToLWEKeyLayout {
204 n: self.ks_lwe.n(),
205 base2k: self.ks_lwe.base2k(),
206 k: self.ks_lwe.k(),
207 rank_in: self.ks_lwe.rank_in(),
208 dnum: self.ks_lwe.dnum(),
209 }
210 }
211}
212
213impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> GLWEAutomorphismKeyHelper<GLWEAutomorphismKeyPrepared<D, BE>, BE>
214 for BDDKeyPrepared<D, BRA, BE>
215{
216 fn automorphism_key_infos(&self) -> poulpy_core::layouts::GGLWELayout {
217 self.cbt.automorphism_key_infos()
218 }
219
220 fn get_automorphism_key(&self, k: i64) -> Option<&GLWEAutomorphismKeyPrepared<D, BE>> {
221 self.cbt.get_automorphism_key(k)
222 }
223}
224
225pub trait BDDKeyPreparedFactory<BRA: BlindRotationAlgo, BE: Backend>
226where
227 Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWEKeyPreparedFactory<BE>,
228{
229 fn alloc_bdd_key_from_infos<A>(&self, infos: &A) -> BDDKeyPrepared<Vec<u8>, BRA, BE>
230 where
231 A: BDDKeyInfos,
232 {
233 let ks_glwe = if let Some(ks_glwe_infos) = &infos.ks_glwe_infos() {
234 Some(GLWESwitchingKeyPrepared::alloc_from_infos(
235 self,
236 ks_glwe_infos,
237 ))
238 } else {
239 None
240 };
241
242 BDDKeyPrepared {
243 cbt: CircuitBootstrappingKeyPrepared::alloc_from_infos(self, &infos.cbt_infos()),
244 ks_glwe,
245 ks_lwe: GLWEToLWEKeyPrepared::alloc_from_infos(self, &infos.ks_lwe_infos()),
246 }
247 }
248
249 fn prepare_bdd_key_tmp_bytes<A>(&self, infos: &A) -> usize
250 where
251 A: BDDKeyInfos,
252 {
253 self.circuit_bootstrapping_key_prepare_tmp_bytes(&infos.cbt_infos())
254 .max(self.prepare_glwe_to_lwe_key_tmp_bytes(&infos.ks_lwe_infos()))
255 }
256
257 fn prepare_bdd_key<DM, DR>(&self, res: &mut BDDKeyPrepared<DM, BRA, BE>, other: &BDDKey<DR, BRA>, scratch: &mut Scratch<BE>)
258 where
259 DM: DataMut,
260 DR: DataRef,
261 Scratch<BE>: ScratchTakeCore<BE>,
262 {
263 res.cbt.prepare(self, &other.cbt, scratch);
264
265 if let Some(key_prep) = &mut res.ks_glwe {
266 if let Some(other) = &other.ks_glwe {
267 key_prep.prepare(self, other, scratch);
268 } else {
269 panic!("incompatible keys: res has Some(ks_glwe) but other has none")
270 }
271 }
272
273 res.ks_lwe.prepare(self, &other.ks_lwe, scratch);
274 }
275}
276impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPreparedFactory<BRA, BE> for Module<BE> where
277 Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWEKeyPreparedFactory<BE>
278{
279}
280
281impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPrepared<Vec<u8>, BRA, BE> {
282 pub fn alloc_from_infos<M, A>(module: &M, infos: &A) -> Self
283 where
284 M: BDDKeyPreparedFactory<BRA, BE>,
285 A: BDDKeyInfos,
286 {
287 module.alloc_bdd_key_from_infos(infos)
288 }
289}
290
291impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BDDKeyHelper<D, BRA, BE> for BDDKeyPrepared<D, BRA, BE> {
292 fn get_cbt_key(
293 &self,
294 ) -> (
295 &CircuitBootstrappingKeyPrepared<D, BRA, BE>,
296 Option<&GLWESwitchingKeyPrepared<D, BE>>,
297 &GLWEToLWEKeyPrepared<D, BE>,
298 ) {
299 (&self.cbt, self.ks_glwe.as_ref(), &self.ks_lwe)
300 }
301}
302
303pub trait BDDKeyHelper<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> {
304 fn get_cbt_key(
305 &self,
306 ) -> (
307 &CircuitBootstrappingKeyPrepared<D, BRA, BE>,
308 Option<&GLWESwitchingKeyPrepared<D, BE>>,
309 &GLWEToLWEKeyPrepared<D, BE>,
310 );
311}
312
313pub trait FheUintPrepareDebug<BRA: BlindRotationAlgo, T: UnsignedInteger, BE: Backend> {
314 fn fhe_uint_debug_prepare<DM, DR0, DR1>(
315 &self,
316 res: &mut FheUintPreparedDebug<DM, T>,
317 bits: &FheUint<DR0, T>,
318 key: &BDDKeyPrepared<DR1, BRA, BE>,
319 scratch: &mut Scratch<BE>,
320 ) where
321 DM: DataMut,
322 DR0: DataRef,
323 DR1: DataRef;
324}