poulpy/poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rs
poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rsRaw
1use poulpy_core::layouts::{
2 AutomorphismKey, AutomorphismKeyLayout, GGLWEInfos, GGSWInfos, GLWE, GLWEInfos, GLWESecret, LWEInfos, LWESecret, TensorKey,
3 TensorKeyLayout,
4 prepared::{GLWEAutomorphismKeyPrepared, GLWESecretPrepared, TensorKeyPrepared},
5};
6use std::collections::HashMap;
7
8use poulpy_hal::{
9 api::{
10 ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace,
11 VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume,
12 VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace,
13 VecZnxSwitchRing, VmpPMatAlloc, VmpPrepare,
14 },
15 layouts::{Backend, Data, DataRef, Module, Scratch},
16 source::Source,
17};
18
19use crate::tfhe::blind_rotation::{
20 BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyInfos,
21 BlindRotationKeyLayout, BlindRotationKeyPrepared,
22};
23
24pub trait CircuitBootstrappingKeyInfos {
25 fn brk_infos(&self) -> BlindRotationKeyLayout;
26 fn atk_infos(&self) -> AutomorphismKeyLayout;
27 fn tsk_infos(&self) -> TensorKeyLayout;
28}
29
30#[derive(Debug, Clone, Copy)]
31pub struct CircuitBootstrappingKeyLayout {
32 pub layout_brk: BlindRotationKeyLayout,
33 pub layout_atk: AutomorphismKeyLayout,
34 pub layout_tsk: TensorKeyLayout,
35}
36
37impl CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyLayout {
38 fn atk_infos(&self) -> AutomorphismKeyLayout {
39 self.layout_atk
40 }
41
42 fn brk_infos(&self) -> BlindRotationKeyLayout {
43 self.layout_brk
44 }
45
46 fn tsk_infos(&self) -> TensorKeyLayout {
47 self.layout_tsk
48 }
49}
50
51pub trait CircuitBootstrappingKeyEncryptSk<B: Backend> {
52 #[allow(clippy::too_many_arguments)]
53 fn encrypt_sk<DLwe, DGlwe, INFOS>(
54 module: &Module<B>,
55 sk_lwe: &LWESecret<DLwe>,
56 sk_glwe: &GLWESecret<DGlwe>,
57 cbt_infos: &INFOS,
58 source_xa: &mut Source,
59 source_xe: &mut Source,
60 scratch: &mut Scratch<B>,
61 ) -> Self
62 where
63 INFOS: CircuitBootstrappingKeyInfos,
64 DLwe: DataRef,
65 DGlwe: DataRef;
66}
67
68pub struct CircuitBootstrappingKey<D: Data, BRA: BlindRotationAlgo> {
69 pub(crate) brk: BlindRotationKey<D, BRA>,
70 pub(crate) tsk: TensorKey<Vec<u8>>,
71 pub(crate) atk: HashMap<i64, AutomorphismKey<Vec<u8>>>,
72}
73
74impl<BRA: BlindRotationAlgo, B: Backend> CircuitBootstrappingKeyEncryptSk<B> for CircuitBootstrappingKey<Vec<u8>, BRA>
75where
76 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>,
77 Module<B>: SvpApplyDftToDft<B>
78 + VecZnxIdftApplyTmpA<B>
79 + VecZnxAddScalarInplace
80 + VecZnxDftBytesOf
81 + VecZnxBigNormalize<B>
82 + VecZnxDftApply<B>
83 + SvpApplyDftToDftInplace<B>
84 + VecZnxIdftApplyConsume<B>
85 + VecZnxNormalizeTmpBytes
86 + VecZnxFillUniform
87 + VecZnxSubInplace
88 + VecZnxAddInplace
89 + VecZnxNormalizeInplace<B>
90 + VecZnxAddNormal
91 + VecZnxNormalize<B>
92 + VecZnxSub
93 + SvpPrepare<B>
94 + VecZnxSwitchRing
95 + SvpPPolBytesOf
96 + SvpPPolAlloc<B>
97 + VecZnxAutomorphism,
98 Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeSvpPPol<B> + TakeVecZnxBig<B>,
99{
100 fn encrypt_sk<DLwe, DGlwe, INFOS>(
101 module: &Module<B>,
102 sk_lwe: &LWESecret<DLwe>,
103 sk_glwe: &GLWESecret<DGlwe>,
104 cbt_infos: &INFOS,
105 source_xa: &mut Source,
106 source_xe: &mut Source,
107 scratch: &mut Scratch<B>,
108 ) -> Self
109 where
110 INFOS: CircuitBootstrappingKeyInfos,
111 DLwe: DataRef,
112 DGlwe: DataRef,
113 {
114 assert_eq!(sk_lwe.n(), cbt_infos.brk_infos().n_lwe());
115 assert_eq!(sk_glwe.n(), cbt_infos.brk_infos().n_glwe());
116 assert_eq!(sk_glwe.n(), cbt_infos.atk_infos().n());
117 assert_eq!(sk_glwe.n(), cbt_infos.tsk_infos().n());
118
119 let atk_infos: AutomorphismKeyLayout = cbt_infos.atk_infos();
120 let brk_infos: BlindRotationKeyLayout = cbt_infos.brk_infos();
121 let trk_infos: TensorKeyLayout = cbt_infos.tsk_infos();
122
123 let mut auto_keys: HashMap<i64, AutomorphismKey<Vec<u8>>> = HashMap::new();
124 let gal_els: Vec<i64> = GLWE::trace_galois_elements(module);
125 gal_els.iter().for_each(|gal_el| {
126 let mut key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&atk_infos);
127 key.encrypt_sk(module, *gal_el, sk_glwe, source_xa, source_xe, scratch);
128 auto_keys.insert(*gal_el, key);
129 });
130
131 let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch);
132
133 let mut brk: BlindRotationKey<Vec<u8>, BRA> = BlindRotationKey::<Vec<u8>, BRA>::alloc(&brk_infos);
134 brk.encrypt_sk(
135 module,
136 &sk_glwe_prepared,
137 sk_lwe,
138 source_xa,
139 source_xe,
140 scratch,
141 );
142
143 let mut tsk: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&trk_infos);
144 tsk.encrypt_sk(module, sk_glwe, source_xa, source_xe, scratch);
145
146 Self {
147 brk,
148 atk: auto_keys,
149 tsk,
150 }
151 }
152}
153
154pub struct CircuitBootstrappingKeyPrepared<D: Data, BRA: BlindRotationAlgo, B: Backend> {
155 pub(crate) brk: BlindRotationKeyPrepared<D, BRA, B>,
156 pub(crate) tsk: TensorKeyPrepared<Vec<u8>, B>,
157 pub(crate) atk: HashMap<i64, GLWEAutomorphismKeyPrepared<Vec<u8>, B>>,
158}
159
160impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyPrepared<D, BRA, B> {
161 fn atk_infos(&self) -> AutomorphismKeyLayout {
162 let (_, atk) = self.atk.iter().next().expect("atk is empty");
163 AutomorphismKeyLayout {
164 n: atk.n(),
165 base2k: atk.base2k(),
166 k: atk.k(),
167 dnum: atk.dnum(),
168 dsize: atk.dsize(),
169 rank: atk.rank(),
170 }
171 }
172
173 fn brk_infos(&self) -> BlindRotationKeyLayout {
174 BlindRotationKeyLayout {
175 n_glwe: self.brk.n_glwe(),
176 n_lwe: self.brk.n_lwe(),
177 base2k: self.brk.base2k(),
178 k: self.brk.k(),
179 dnum: self.brk.dnum(),
180 rank: self.brk.rank(),
181 }
182 }
183
184 fn tsk_infos(&self) -> TensorKeyLayout {
185 TensorKeyLayout {
186 n: self.tsk.n(),
187 base2k: self.tsk.base2k(),
188 k: self.tsk.k(),
189 dnum: self.tsk.dnum(),
190 dsize: self.tsk.dsize(),
191 rank: self.tsk.rank(),
192 }
193 }
194}
195
196impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> PrepareAlloc<B, CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B>>
197 for CircuitBootstrappingKey<D, BRA>
198where
199 Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
200 BlindRotationKey<D, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>,
201 TensorKey<D>: PrepareAlloc<B, TensorKeyPrepared<Vec<u8>, B>>,
202 AutomorphismKey<D>: PrepareAlloc<B, GLWEAutomorphismKeyPrepared<Vec<u8>, B>>,
203{
204 fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> {
205 let brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = self.brk.prepare_alloc(module, scratch);
206 let tsk: TensorKeyPrepared<Vec<u8>, B> = self.tsk.prepare_alloc(module, scratch);
207 let mut atk: HashMap<i64, GLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new();
208 for (key, value) in &self.atk {
209 atk.insert(*key, value.prepare_alloc(module, scratch));
210 }
211 CircuitBootstrappingKeyPrepared { brk, tsk, atk }
212 }
213}