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::FheUintBlocksPrepDebug;
3use crate::tfhe::{
4 bdd_arithmetic::{FheUintBlocks, FheUintBlocksPrep, UnsignedInteger},
5 blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk},
6 circuit_bootstrapping::{
7 CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout,
8 CircuitBootstrappingKeyPrepared, CirtuitBootstrappingExecute,
9 },
10};
11use poulpy_core::{
12 layouts::{
13 prepared::GLWEToLWESwitchingKeyPrepared, GLWESecret, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, LWESecret
14 }, ScratchTakeCore,
15};
16use poulpy_hal::{
17 api::{
18 ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace,
19 VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
20 VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize,
21 VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing,
22 VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPrepare,
23 },
24 layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
25 source::Source,
26};
27
28pub trait BDDKeyInfos {
29 fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout;
30 fn ks_infos(&self) -> GLWEToLWEKeyLayout;
31}
32
33#[derive(Debug, Clone, Copy)]
34pub struct BDDKeyLayout {
35 pub cbt: CircuitBootstrappingKeyLayout,
36 pub ks: GLWEToLWEKeyLayout,
37}
38
39impl BDDKeyInfos for BDDKeyLayout {
40 fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
41 self.cbt
42 }
43
44 fn ks_infos(&self) -> GLWEToLWEKeyLayout {
45 self.ks
46 }
47}
48
49pub struct BDDKey<CBT, LWE, BRA>
50where
51 CBT: Data,
52 LWE: Data,
53 BRA: BlindRotationAlgo,
54{
55 cbt: CircuitBootstrappingKey<CBT, BRA>,
56 ks: GLWEToLWESwitchingKey<LWE>,
57}
58
59impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, Vec<u8>, BRA> {
60 pub fn encrypt_sk<DLwe, DGlwe, A, BE: Backend>(
61 module: &Module<BE>,
62 sk_lwe: &LWESecret<DLwe>,
63 sk_glwe: &GLWESecret<DGlwe>,
64 infos: &A,
65 source_xa: &mut Source,
66 source_xe: &mut Source,
67 scratch: &mut Scratch<BE>,
68 ) -> Self
69 where
70 A: BDDKeyInfos,
71 DLwe: DataRef,
72 DGlwe: DataRef,
73 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<BE>,
74 Module<BE>: SvpApplyDftToDft<BE>
75 + VecZnxIdftApplyTmpA<BE>
76 + VecZnxAddScalarInplace
77 + VecZnxDftBytesOf
78 + VecZnxBigNormalize<BE>
79 + VecZnxDftApply<BE>
80 + SvpApplyDftToDftInplace<BE>
81 + VecZnxIdftApplyConsume<BE>
82 + VecZnxNormalizeTmpBytes
83 + VecZnxFillUniform
84 + VecZnxSubInplace
85 + VecZnxAddInplace
86 + VecZnxNormalizeInplace<BE>
87 + VecZnxAddNormal
88 + VecZnxNormalize<BE>
89 + VecZnxSub
90 + SvpPrepare<BE>
91 + VecZnxSwitchRing
92 + SvpPPolBytesOf
93 + SvpPPolAlloc<BE>
94 + VecZnxAutomorphism
95 + VecZnxAutomorphismInplace<BE>,
96 Scratch<BE>: ScratchTakeCore<BE>,
97 {
98 let mut ks: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(&infos.ks_infos());
99 ks.encrypt_sk(module, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
100
101 Self {
102 cbt: CircuitBootstrappingKey::encrypt_sk(
103 module,
104 sk_lwe,
105 sk_glwe,
106 &infos.cbt_infos(),
107 source_xa,
108 source_xe,
109 scratch,
110 ),
111 ks,
112 }
113 }
114}
115
116pub struct BDDKeyPrepared<CBT, LWE, BRA, BE>
117where
118 CBT: Data,
119 LWE: Data,
120 BRA: BlindRotationAlgo,
121 BE: Backend,
122{
123 cbt: CircuitBootstrappingKeyPrepared<CBT, BRA, BE>,
124 ks: GLWEToLWESwitchingKeyPrepared<LWE, BE>,
125}
126
127impl<CBT: DataMut, LWE: DataMut, BRA: BlindRotationAlgo, BE: Backend> PrepareAlloc<BE, BDDKeyPrepared<CBT, LWE, BRA, BE>>
128 for BDDKey<CBT, LWE, BRA>
129where
130 CircuitBootstrappingKey<CBT, BRA>: PrepareAlloc<BE, CircuitBootstrappingKeyPrepared<CBT, BRA, BE>>,
131 GLWEToLWESwitchingKey<LWE>: PrepareAlloc<BE, GLWEToLWESwitchingKeyPrepared<LWE, BE>>,
132{
133 fn prepare_alloc(&self, module: &Module<BE>, scratch: &mut Scratch<BE>) -> BDDKeyPrepared<CBT, LWE, BRA, BE> {
134 BDDKeyPrepared {
135 cbt: self.cbt.prepare_alloc(module, scratch),
136 ks: self.ks.prepare_alloc(module, scratch),
137 }
138 }
139}
140
141pub trait FheUintPrepare<BE: Backend, OUT, IN> {
142 fn prepare(&self, module: &Module<BE>, out: &mut OUT, bits: &IN, scratch: &mut Scratch<BE>);
143}
144
145impl<CBT, OUT, IN, LWE, BRA, BE, T> FheUintPrepare<BE, FheUintBlocksPrep<OUT, BE, T>, FheUintBlocks<IN, T>>
146 for BDDKeyPrepared<CBT, LWE, BRA, BE>
147where
148 T: UnsignedInteger,
149 CBT: DataRef,
150 OUT: DataMut,
151 IN: DataRef,
152 LWE: DataRef,
153 BRA: BlindRotationAlgo,
154 BE: Backend,
155 Module<BE>: VmpPrepare<BE>
156 + VecZnxRotate
157 + VecZnxDftBytesOf
158 + VmpApplyDftToDftTmpBytes
159 + VecZnxBigNormalizeTmpBytes
160 + VmpApplyDftToDft<BE>
161 + VmpApplyDftToDftAdd<BE>
162 + VecZnxDftApply<BE>
163 + VecZnxIdftApplyConsume<BE>
164 + VecZnxBigAddSmallInplace<BE>
165 + VecZnxBigNormalize<BE>
166 + VecZnxNormalize<BE>
167 + VecZnxNormalizeTmpBytes,
168 Scratch<BE>: ScratchAvailable + TakeVecZnxDft<BE> + TakeGLWE + TakeVecZnx + TakeGGSW,
169 CircuitBootstrappingKeyPrepared<CBT, BRA, BE>: CirtuitBootstrappingExecute<BE>,
170{
171 fn prepare(
172 &self,
173 module: &Module<BE>,
174 out: &mut FheUintBlocksPrep<OUT, BE, T>,
175 bits: &FheUintBlocks<IN, T>,
176 scratch: &mut Scratch<BE>,
177 ) {
178 #[cfg(debug_assertions)]
179 {
180 assert_eq!(out.blocks.len(), bits.blocks.len());
181 }
182 let mut lwe: LWE<Vec<u8>> = LWE::alloc(&bits.blocks[0]); //TODO: add TakeLWE
183 let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(out);
184 for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) {
185 lwe.from_glwe(module, src, &self.ks, scratch_1);
186 self.cbt
187 .execute_to_constant(module, &mut tmp_ggsw, &lwe, 1, 1, scratch_1);
188 dst.prepare(module, &tmp_ggsw, scratch_1);
189 }
190 }
191}
192
193#[cfg(test)]
194impl<CBT, OUT, IN, LWE, BRA, BE, T> FheUintPrepare<BE, FheUintBlocksPrepDebug<OUT, T>, FheUintBlocks<IN, T>>
195 for BDDKeyPrepared<CBT, LWE, BRA, BE>
196where
197 T: UnsignedInteger,
198 CBT: DataRef,
199 OUT: DataMut,
200 IN: DataRef,
201 LWE: DataRef,
202 BRA: BlindRotationAlgo,
203 BE: Backend,
204 Module<BE>: VmpPrepare<BE>
205 + VecZnxRotate
206 + VecZnxDftBytesOf
207 + VmpApplyDftToDftTmpBytes
208 + VecZnxBigNormalizeTmpBytes
209 + VmpApplyDftToDft<BE>
210 + VmpApplyDftToDftAdd<BE>
211 + VecZnxDftApply<BE>
212 + VecZnxIdftApplyConsume<BE>
213 + VecZnxBigAddSmallInplace<BE>
214 + VecZnxBigNormalize<BE>
215 + VecZnxNormalize<BE>
216 + VecZnxNormalizeTmpBytes,
217 Scratch<BE>: ScratchTakeCore<BE>,
218 CircuitBootstrappingKeyPrepared<CBT, BRA, BE>: CirtuitBootstrappingExecute<BE>,
219{
220 fn prepare(
221 &self,
222 module: &Module<BE>,
223 out: &mut FheUintBlocksPrepDebug<OUT, T>,
224 bits: &FheUintBlocks<IN, T>,
225 scratch: &mut Scratch<BE>,
226 ) {
227 #[cfg(debug_assertions)]
228 {
229 assert_eq!(out.blocks.len(), bits.blocks.len());
230 }
231 let mut lwe: LWE<Vec<u8>> = LWE::alloc(&bits.blocks[0]); //TODO: add TakeLWE
232 for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) {
233 lwe.from_glwe(module, src, &self.ks, scratch);
234 self.cbt
235 .execute_to_constant(module, dst, &lwe, 1, 1, scratch);
236 }
237 }
238}