poulpy/poulpy-schemes/src/tfhe/bdd_arithmetic/key.rs
poulpy-schemes/src/tfhe/bdd_arithmetic/key.rsRaw
1#[cfg(test)]
2use crate::tfhe::bdd_arithmetic::FheUintBlocksPreparedDebug;
3use crate::tfhe::{
4 bdd_arithmetic::{FheUintBlocks, FheUintBlocksPrepared, UnsignedInteger},
5 blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory},
6 circuit_bootstrapping::{
7 CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout,
8 CircuitBootstrappingKeyPrepared, CircuitBootstrappingKeyPreparedFactory, CirtuitBootstrappingExecute,
9 },
10};
11use poulpy_core::{
12 GLWEToLWESwitchingKeyEncryptSk, GetDistribution, LWEFromGLWE, ScratchTakeCore,
13 layouts::{
14 GGSWInfos, GGSWPreparedFactory, GLWEInfos, GLWESecretToRef, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey,
15 GLWEToLWESwitchingKeyPreparedFactory, LWE, LWEInfos, LWESecretToRef, prepared::GLWEToLWESwitchingKeyPrepared,
16 },
17};
18use poulpy_hal::{
19 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
20 source::Source,
21};
22
23pub trait BDDKeyInfos {
24 fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout;
25 fn ks_infos(&self) -> GLWEToLWEKeyLayout;
26}
27
28#[derive(Debug, Clone, Copy)]
29pub struct BDDKeyLayout {
30 pub cbt: CircuitBootstrappingKeyLayout,
31 pub ks: GLWEToLWEKeyLayout,
32}
33
34impl BDDKeyInfos for BDDKeyLayout {
35 fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
36 self.cbt
37 }
38
39 fn ks_infos(&self) -> GLWEToLWEKeyLayout {
40 self.ks
41 }
42}
43
44pub struct BDDKey<D, BRA>
45where
46 D: Data,
47 BRA: BlindRotationAlgo,
48{
49 cbt: CircuitBootstrappingKey<D, BRA>,
50 ks: GLWEToLWESwitchingKey<D>,
51}
52
53impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, BRA>
54where
55 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
56{
57 pub fn alloc_from_infos<A>(infos: &A) -> Self
58 where
59 A: BDDKeyInfos,
60 {
61 Self {
62 cbt: CircuitBootstrappingKey::alloc_from_infos(&infos.cbt_infos()),
63 ks: GLWEToLWESwitchingKey::alloc_from_infos(&infos.ks_infos()),
64 }
65 }
66}
67
68pub trait BDDKeyEncryptSk<BRA: BlindRotationAlgo, BE: Backend> {
69 fn bdd_key_encrypt_sk<D, S0, S1>(
70 &self,
71 res: &mut BDDKey<D, BRA>,
72 sk_lwe: &S0,
73 sk_glwe: &S1,
74 source_xa: &mut Source,
75 source_xe: &mut Source,
76 scratch: &mut Scratch<BE>,
77 ) where
78 D: DataMut,
79 S0: LWESecretToRef + GetDistribution + LWEInfos,
80 S1: GLWESecretToRef + GetDistribution + GLWEInfos;
81}
82
83impl<BE: Backend, BRA: BlindRotationAlgo> BDDKeyEncryptSk<BRA, BE> for Module<BE>
84where
85 Self: CircuitBootstrappingKeyEncryptSk<BRA, BE> + GLWEToLWESwitchingKeyEncryptSk<BE>,
86 Scratch<BE>: ScratchTakeCore<BE>,
87{
88 fn bdd_key_encrypt_sk<D, S0, S1>(
89 &self,
90 res: &mut BDDKey<D, BRA>,
91 sk_lwe: &S0,
92 sk_glwe: &S1,
93 source_xa: &mut Source,
94 source_xe: &mut Source,
95 scratch: &mut Scratch<BE>,
96 ) where
97 D: DataMut,
98 S0: LWESecretToRef + GetDistribution + LWEInfos,
99 S1: GLWESecretToRef + GetDistribution + GLWEInfos,
100 {
101 res.ks
102 .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
103 res.cbt
104 .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
105 }
106}
107
108impl<D: DataMut, BRA: BlindRotationAlgo> BDDKey<D, BRA> {
109 pub fn encrypt_sk<S0, S1, M, BE: Backend>(
110 &mut self,
111 module: &M,
112 sk_lwe: &S0,
113 sk_glwe: &S1,
114 source_xa: &mut Source,
115 source_xe: &mut Source,
116 scratch: &mut Scratch<BE>,
117 ) where
118 S0: LWESecretToRef + GetDistribution + LWEInfos,
119 S1: GLWESecretToRef + GetDistribution + GLWEInfos,
120 M: BDDKeyEncryptSk<BRA, BE>,
121 Scratch<BE>: ScratchTakeCore<BE>,
122 {
123 module.bdd_key_encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
124 }
125}
126
127pub struct BDDKeyPrepared<D, BRA, BE>
128where
129 D: Data,
130 BRA: BlindRotationAlgo,
131 BE: Backend,
132{
133 pub(crate) cbt: CircuitBootstrappingKeyPrepared<D, BRA, BE>,
134 pub(crate) ks: GLWEToLWESwitchingKeyPrepared<D, BE>,
135}
136
137pub trait BDDKeyPreparedFactory<BRA: BlindRotationAlgo, BE: Backend>
138where
139 Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWESwitchingKeyPreparedFactory<BE>,
140{
141 fn alloc_bdd_key_from_infos<A>(&self, infos: &A) -> BDDKeyPrepared<Vec<u8>, BRA, BE>
142 where
143 A: BDDKeyInfos,
144 {
145 BDDKeyPrepared {
146 cbt: CircuitBootstrappingKeyPrepared::alloc_from_infos(self, &infos.cbt_infos()),
147 ks: GLWEToLWESwitchingKeyPrepared::alloc_from_infos(self, &infos.ks_infos()),
148 }
149 }
150
151 fn prepare_bdd_key_tmp_bytes<A>(&self, infos: &A) -> usize
152 where
153 A: BDDKeyInfos,
154 {
155 self.circuit_bootstrapping_key_prepare_tmp_bytes(&infos.cbt_infos())
156 .max(self.prepare_glwe_to_lwe_switching_key_tmp_bytes(&infos.ks_infos()))
157 }
158
159 fn prepare_bdd_key<DM, DR>(&self, res: &mut BDDKeyPrepared<DM, BRA, BE>, other: &BDDKey<DR, BRA>, scratch: &mut Scratch<BE>)
160 where
161 DM: DataMut,
162 DR: DataRef,
163 Scratch<BE>: ScratchTakeCore<BE>,
164 {
165 res.cbt.prepare(self, &other.cbt, scratch);
166 res.ks.prepare(self, &other.ks, scratch);
167 }
168}
169impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPreparedFactory<BRA, BE> for Module<BE> where
170 Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWESwitchingKeyPreparedFactory<BE>
171{
172}
173
174impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPrepared<Vec<u8>, BRA, BE> {
175 pub fn alloc_from_infos<M, A>(module: &M, infos: &A) -> Self
176 where
177 M: BDDKeyPreparedFactory<BRA, BE>,
178 A: BDDKeyInfos,
179 {
180 module.alloc_bdd_key_from_infos(infos)
181 }
182}
183
184impl<D: DataMut, BRA: BlindRotationAlgo, BE: Backend> BDDKeyPrepared<D, BRA, BE> {
185 pub fn prepare<DR, M>(&mut self, module: &M, other: &BDDKey<DR, BRA>, scratch: &mut Scratch<BE>)
186 where
187 DR: DataRef,
188 M: BDDKeyPreparedFactory<BRA, BE>,
189 Scratch<BE>: ScratchTakeCore<BE>,
190 {
191 module.prepare_bdd_key(self, other, scratch);
192 }
193}
194
195pub trait FheUintBlocksPrepare<BRA: BlindRotationAlgo, T: UnsignedInteger, BE: Backend> {
196 fn fhe_uint_blocks_prepare_tmp_bytes<R, A>(
197 &self,
198 block_size: usize,
199 extension_factor: usize,
200 res_infos: &R,
201 infos: &A,
202 ) -> usize
203 where
204 R: GGSWInfos,
205 A: BDDKeyInfos;
206 fn fhe_uint_blocks_prepare<DM, DR0, DR1>(
207 &self,
208 res: &mut FheUintBlocksPrepared<DM, T, BE>,
209 bits: &FheUintBlocks<DR0, T>,
210 key: &BDDKeyPrepared<DR1, BRA, BE>,
211 scratch: &mut Scratch<BE>,
212 ) where
213 DM: DataMut,
214 DR0: DataRef,
215 DR1: DataRef;
216}
217
218impl<BRA: BlindRotationAlgo, BE: Backend, T: UnsignedInteger> FheUintBlocksPrepare<BRA, T, BE> for Module<BE>
219where
220 Self: LWEFromGLWE<BE> + CirtuitBootstrappingExecute<BRA, BE> + GGSWPreparedFactory<BE>,
221 Scratch<BE>: ScratchTakeCore<BE>,
222{
223 fn fhe_uint_blocks_prepare_tmp_bytes<R, A>(
224 &self,
225 block_size: usize,
226 extension_factor: usize,
227 res_infos: &R,
228 bdd_infos: &A,
229 ) -> usize
230 where
231 R: GGSWInfos,
232 A: BDDKeyInfos,
233 {
234 self.circuit_bootstrapping_execute_tmp_bytes(
235 block_size,
236 extension_factor,
237 res_infos,
238 &bdd_infos.cbt_infos(),
239 )
240 }
241
242 fn fhe_uint_blocks_prepare<DM, DR0, DR1>(
243 &self,
244 res: &mut FheUintBlocksPrepared<DM, T, BE>,
245 bits: &FheUintBlocks<DR0, T>,
246 key: &BDDKeyPrepared<DR1, BRA, BE>,
247 scratch: &mut Scratch<BE>,
248 ) where
249 DM: DataMut,
250 DR0: DataRef,
251 DR1: DataRef,
252 {
253 assert_eq!(res.blocks.len(), bits.blocks.len());
254
255 let mut lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(&bits.blocks[0]); //TODO: add TakeLWE
256 let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(res);
257 for (dst, src) in res.blocks.iter_mut().zip(bits.blocks.iter()) {
258 lwe.from_glwe(self, src, &key.ks, scratch_1);
259 key.cbt
260 .execute_to_constant(self, &mut tmp_ggsw, &lwe, 1, 1, scratch_1);
261 dst.prepare(self, &tmp_ggsw, scratch_1);
262 }
263 }
264}
265
266impl<D: DataMut, T: UnsignedInteger, BE: Backend> FheUintBlocksPrepared<D, T, BE> {
267 pub fn prepare<BRA, M, O, K>(
268 &mut self,
269 module: &M,
270 other: &FheUintBlocks<O, T>,
271 key: &BDDKeyPrepared<K, BRA, BE>,
272 scratch: &mut Scratch<BE>,
273 ) where
274 BRA: BlindRotationAlgo,
275 O: DataRef,
276 K: DataRef,
277 M: FheUintBlocksPrepare<BRA, T, BE>,
278 Scratch<BE>: ScratchTakeCore<BE>,
279 {
280 module.fhe_uint_blocks_prepare(self, other, key, scratch);
281 }
282}
283
284#[cfg(test)]
285pub(crate) trait FheUintBlockDebugPrepare<BRA: BlindRotationAlgo, T: UnsignedInteger, BE: Backend> {
286 fn fhe_uint_block_debug_prepare<DM, DR0, DR1>(
287 &self,
288 res: &mut FheUintBlocksPreparedDebug<DM, T>,
289 bits: &FheUintBlocks<DR0, T>,
290 key: &BDDKeyPrepared<DR1, BRA, BE>,
291 scratch: &mut Scratch<BE>,
292 ) where
293 DM: DataMut,
294 DR0: DataRef,
295 DR1: DataRef;
296}