arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rs
poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rsRaw
  1use poulpy_core::layouts::{
  2    GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWELayoutInfos, GGLWETensorKey, GGLWETensorKeyLayout, GGSWInfos,
  3    GLWECiphertext, GLWEInfos, GLWESecret, LWEInfos, LWESecret,
  4    prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, PrepareAlloc},
  5};
  6use std::collections::HashMap;
  7
  8use poulpy_hal::{
  9    api::{
 10        ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx,
 11        TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace,
 12        VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume,
 13        VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace,
 14        VecZnxSwitchRing, VmpPMatAlloc, VmpPrepare,
 15    },
 16    layouts::{Backend, Data, DataRef, Module, Scratch},
 17    source::Source,
 18};
 19
 20use crate::tfhe::blind_rotation::{
 21    BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyInfos,
 22    BlindRotationKeyLayout, BlindRotationKeyPrepared,
 23};
 24
 25pub trait CircuitBootstrappingKeyInfos {
 26    fn layout_brk(&self) -> BlindRotationKeyLayout;
 27    fn layout_atk(&self) -> GGLWEAutomorphismKeyLayout;
 28    fn layout_tsk(&self) -> GGLWETensorKeyLayout;
 29}
 30
 31pub struct CircuitBootstrappingKeyLayout {
 32    pub layout_brk: BlindRotationKeyLayout,
 33    pub layout_atk: GGLWEAutomorphismKeyLayout,
 34    pub layout_tsk: GGLWETensorKeyLayout,
 35}
 36
 37impl CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyLayout {
 38    fn layout_atk(&self) -> GGLWEAutomorphismKeyLayout {
 39        self.layout_atk
 40    }
 41
 42    fn layout_brk(&self) -> BlindRotationKeyLayout {
 43        self.layout_brk
 44    }
 45
 46    fn layout_tsk(&self) -> GGLWETensorKeyLayout {
 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: GGLWETensorKey<Vec<u8>>,
 71    pub(crate) atk: HashMap<i64, GGLWEAutomorphismKey<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        + VecZnxDftAllocBytes
 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        + SvpPPolAllocBytes
 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        Module<B>:,
114    {
115        assert_eq!(sk_lwe.n(), cbt_infos.layout_brk().n_lwe());
116        assert_eq!(sk_glwe.n(), cbt_infos.layout_brk().n_glwe());
117        assert_eq!(sk_glwe.n(), cbt_infos.layout_atk().n());
118        assert_eq!(sk_glwe.n(), cbt_infos.layout_tsk().n());
119
120        let atk_infos: GGLWEAutomorphismKeyLayout = cbt_infos.layout_atk();
121        let brk_infos: BlindRotationKeyLayout = cbt_infos.layout_brk();
122        let trk_infos: GGLWETensorKeyLayout = cbt_infos.layout_tsk();
123
124        let mut auto_keys: HashMap<i64, GGLWEAutomorphismKey<Vec<u8>>> = HashMap::new();
125        let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(module);
126        gal_els.iter().for_each(|gal_el| {
127            let mut key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&atk_infos);
128            key.encrypt_sk(module, *gal_el, sk_glwe, source_xa, source_xe, scratch);
129            auto_keys.insert(*gal_el, key);
130        });
131
132        let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch);
133
134        let mut brk: BlindRotationKey<Vec<u8>, BRA> = BlindRotationKey::<Vec<u8>, BRA>::alloc(&brk_infos);
135        brk.encrypt_sk(
136            module,
137            &sk_glwe_prepared,
138            sk_lwe,
139            source_xa,
140            source_xe,
141            scratch,
142        );
143
144        let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&trk_infos);
145        tsk.encrypt_sk(module, sk_glwe, source_xa, source_xe, scratch);
146
147        Self {
148            brk,
149            atk: auto_keys,
150            tsk,
151        }
152    }
153}
154
155pub struct CircuitBootstrappingKeyPrepared<D: Data, BRA: BlindRotationAlgo, B: Backend> {
156    pub(crate) brk: BlindRotationKeyPrepared<D, BRA, B>,
157    pub(crate) tsk: GGLWETensorKeyPrepared<Vec<u8>, B>,
158    pub(crate) atk: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>,
159}
160
161impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyPrepared<D, BRA, B> {
162    fn layout_atk(&self) -> GGLWEAutomorphismKeyLayout {
163        let (_, atk) = self.atk.iter().next().expect("atk is empty");
164        GGLWEAutomorphismKeyLayout {
165            n: atk.n(),
166            base2k: atk.base2k(),
167            k: atk.k(),
168            rows: atk.rows(),
169            digits: atk.digits(),
170            rank: atk.rank(),
171        }
172    }
173
174    fn layout_brk(&self) -> BlindRotationKeyLayout {
175        BlindRotationKeyLayout {
176            n_glwe: self.brk.n_glwe(),
177            n_lwe: self.brk.n_lwe(),
178            base2k: self.brk.base2k(),
179            k: self.brk.k(),
180            rows: self.brk.rows(),
181            rank: self.brk.rank(),
182        }
183    }
184
185    fn layout_tsk(&self) -> GGLWETensorKeyLayout {
186        GGLWETensorKeyLayout {
187            n: self.tsk.n(),
188            base2k: self.tsk.base2k(),
189            k: self.tsk.k(),
190            rows: self.tsk.rows(),
191            digits: self.tsk.digits(),
192            rank: self.tsk.rank(),
193        }
194    }
195}
196
197impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> PrepareAlloc<B, CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B>>
198    for CircuitBootstrappingKey<D, BRA>
199where
200    Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
201    BlindRotationKey<D, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>,
202    GGLWETensorKey<D>: PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>>,
203    GGLWEAutomorphismKey<D>: PrepareAlloc<B, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>,
204{
205    fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> {
206        let brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = self.brk.prepare_alloc(module, scratch);
207        let tsk: GGLWETensorKeyPrepared<Vec<u8>, B> = self.tsk.prepare_alloc(module, scratch);
208        let mut atk: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new();
209        for (key, value) in &self.atk {
210            atk.insert(*key, value.prepare_alloc(module, scratch));
211        }
212        CircuitBootstrappingKeyPrepared { brk, tsk, atk }
213    }
214}