#[cfg(test)] use crate::tfhe::bdd_arithmetic::FheUintBlocksPrepDebug; use crate::tfhe::{ bdd_arithmetic::{FheUintBlocks, FheUintBlocksPrep, UnsignedInteger}, blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk}, circuit_bootstrapping::{ CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout, CircuitBootstrappingKeyPrepared, CirtuitBootstrappingExecute, }, }; use poulpy_core::{ TakeGGSW, TakeGLWECt, layouts::{ GLWESecret, GLWEToLWEKey, GLWEToLWEKeyLayout, LWECiphertext, LWESecret, prepared::{GLWEToLWESwitchingKeyPrepared, Prepare, PrepareAlloc}, }, }; use poulpy_hal::{ api::{ ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPrepare, }, layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, source::Source, }; pub trait BDDKeyInfos { fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout; fn ks_infos(&self) -> GLWEToLWEKeyLayout; } #[derive(Debug, Clone, Copy)] pub struct BDDKeyLayout { pub cbt: CircuitBootstrappingKeyLayout, pub ks: GLWEToLWEKeyLayout, } impl BDDKeyInfos for BDDKeyLayout { fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout { self.cbt } fn ks_infos(&self) -> GLWEToLWEKeyLayout { self.ks } } pub struct BDDKey where CBT: Data, LWE: Data, BRA: BlindRotationAlgo, { cbt: CircuitBootstrappingKey, ks: GLWEToLWEKey, } impl BDDKey, Vec, BRA> { pub fn encrypt_sk( module: &Module, sk_lwe: &LWESecret, sk_glwe: &GLWESecret, infos: &A, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch, ) -> Self where A: BDDKeyInfos, DLwe: DataRef, DGlwe: DataRef, BlindRotationKey, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk, Module: SvpApplyDftToDft + VecZnxIdftApplyTmpA + VecZnxAddScalarInplace + VecZnxDftAllocBytes + VecZnxBigNormalize + VecZnxDftApply + SvpApplyDftToDftInplace + VecZnxIdftApplyConsume + VecZnxNormalizeTmpBytes + VecZnxFillUniform + VecZnxSubInplace + VecZnxAddInplace + VecZnxNormalizeInplace + VecZnxAddNormal + VecZnxNormalize + VecZnxSub + SvpPrepare + VecZnxSwitchRing + SvpPPolAllocBytes + SvpPPolAlloc + VecZnxAutomorphism + VecZnxAutomorphismInplace, Scratch: TakeVecZnxDft + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeSvpPPol + TakeVecZnxBig, { let mut ks: GLWEToLWEKey> = GLWEToLWEKey::alloc(&infos.ks_infos()); ks.encrypt_sk(module, sk_lwe, sk_glwe, source_xa, source_xe, scratch); Self { cbt: CircuitBootstrappingKey::encrypt_sk( module, sk_lwe, sk_glwe, &infos.cbt_infos(), source_xa, source_xe, scratch, ), ks, } } } pub struct BDDKeyPrepared where CBT: Data, LWE: Data, BRA: BlindRotationAlgo, BE: Backend, { cbt: CircuitBootstrappingKeyPrepared, ks: GLWEToLWESwitchingKeyPrepared, } impl PrepareAlloc> for BDDKey where CircuitBootstrappingKey: PrepareAlloc>, GLWEToLWEKey: PrepareAlloc>, { fn prepare_alloc(&self, module: &Module, scratch: &mut Scratch) -> BDDKeyPrepared { BDDKeyPrepared { cbt: self.cbt.prepare_alloc(module, scratch), ks: self.ks.prepare_alloc(module, scratch), } } } pub trait FheUintPrepare { fn prepare(&self, module: &Module, out: &mut OUT, bits: &IN, scratch: &mut Scratch); } impl FheUintPrepare, FheUintBlocks> for BDDKeyPrepared where T: UnsignedInteger, CBT: DataRef, OUT: DataMut, IN: DataRef, LWE: DataRef, BRA: BlindRotationAlgo, BE: Backend, Module: VmpPrepare + VecZnxRotate + VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft + VmpApplyDftToDftAdd + VecZnxDftApply + VecZnxIdftApplyConsume + VecZnxBigAddSmallInplace + VecZnxBigNormalize + VecZnxNormalize + VecZnxNormalizeTmpBytes, Scratch: ScratchAvailable + TakeVecZnxDft + TakeGLWECt + TakeVecZnx + TakeGGSW, CircuitBootstrappingKeyPrepared: CirtuitBootstrappingExecute, { fn prepare( &self, module: &Module, out: &mut FheUintBlocksPrep, bits: &FheUintBlocks, scratch: &mut Scratch, ) { #[cfg(debug_assertions)] { assert_eq!(out.blocks.len(), bits.blocks.len()); } let mut lwe: LWECiphertext> = LWECiphertext::alloc(&bits.blocks[0]); //TODO: add TakeLWE let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(out); for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) { lwe.from_glwe(module, src, &self.ks, scratch_1); self.cbt .execute_to_constant(module, &mut tmp_ggsw, &lwe, 1, 1, scratch_1); dst.prepare(module, &tmp_ggsw, scratch_1); } } } #[cfg(test)] impl FheUintPrepare, FheUintBlocks> for BDDKeyPrepared where T: UnsignedInteger, CBT: DataRef, OUT: DataMut, IN: DataRef, LWE: DataRef, BRA: BlindRotationAlgo, BE: Backend, Module: VmpPrepare + VecZnxRotate + VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft + VmpApplyDftToDftAdd + VecZnxDftApply + VecZnxIdftApplyConsume + VecZnxBigAddSmallInplace + VecZnxBigNormalize + VecZnxNormalize + VecZnxNormalizeTmpBytes, Scratch: ScratchAvailable + TakeVecZnxDft + TakeGLWECt + TakeVecZnx + TakeGGSW, CircuitBootstrappingKeyPrepared: CirtuitBootstrappingExecute, { fn prepare( &self, module: &Module, out: &mut FheUintBlocksPrepDebug, bits: &FheUintBlocks, scratch: &mut Scratch, ) { #[cfg(debug_assertions)] { assert_eq!(out.blocks.len(), bits.blocks.len()); } let mut lwe: LWECiphertext> = LWECiphertext::alloc(&bits.blocks[0]); //TODO: add TakeLWE for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) { lwe.from_glwe(module, src, &self.ks, scratch); self.cbt .execute_to_constant(module, dst, &lwe, 1, 1, scratch); } } }