arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/blind_rotation/key.rs
poulpy-schemes/src/tfhe/blind_rotation/key.rsRaw
  1use poulpy_hal::{
  2    layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, Scratch, WriterTo},
  3    source::Source,
  4};
  5
  6use std::{fmt, marker::PhantomData};
  7
  8use poulpy_core::{
  9    Distribution,
 10    layouts::{
 11        Base2K, Degree, Dnum, Dsize, GGSW, GGSWInfos, GLWEInfos, LWEInfos, LWESecret, Rank, TorusPrecision,
 12        prepared::GLWESecretPrepared,
 13    },
 14};
 15
 16use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
 17
 18use crate::tfhe::blind_rotation::BlindRotationAlgo;
 19
 20#[derive(PartialEq, Eq, Copy, Clone, Debug)]
 21pub struct BlindRotationKeyLayout {
 22    pub n_glwe: Degree,
 23    pub n_lwe: Degree,
 24    pub base2k: Base2K,
 25    pub k: TorusPrecision,
 26    pub dnum: Dnum,
 27    pub rank: Rank,
 28}
 29
 30impl BlindRotationKeyInfos for BlindRotationKeyLayout {
 31    fn n_glwe(&self) -> Degree {
 32        self.n_glwe
 33    }
 34
 35    fn n_lwe(&self) -> Degree {
 36        self.n_lwe
 37    }
 38}
 39
 40impl GGSWInfos for BlindRotationKeyLayout {
 41    fn dsize(&self) -> Dsize {
 42        Dsize(1)
 43    }
 44
 45    fn dnum(&self) -> Dnum {
 46        self.dnum
 47    }
 48}
 49
 50impl GLWEInfos for BlindRotationKeyLayout {
 51    fn rank(&self) -> Rank {
 52        self.rank
 53    }
 54}
 55
 56impl LWEInfos for BlindRotationKeyLayout {
 57    fn base2k(&self) -> Base2K {
 58        self.base2k
 59    }
 60
 61    fn k(&self) -> TorusPrecision {
 62        self.k
 63    }
 64
 65    fn n(&self) -> Degree {
 66        self.n_glwe
 67    }
 68}
 69
 70pub trait BlindRotationKeyInfos
 71where
 72    Self: GGSWInfos,
 73{
 74    fn n_glwe(&self) -> Degree;
 75    fn n_lwe(&self) -> Degree;
 76}
 77
 78pub trait BlindRotationKeyAlloc {
 79    fn alloc<A>(infos: &A) -> Self
 80    where
 81        A: BlindRotationKeyInfos;
 82}
 83
 84pub trait BlindRotationKeyEncryptSk<B: Backend> {
 85    #[allow(clippy::too_many_arguments)]
 86    fn encrypt_sk<DataSkGLWE, DataSkLWE>(
 87        &mut self,
 88        module: &Module<B>,
 89        sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
 90        sk_lwe: &LWESecret<DataSkLWE>,
 91        source_xa: &mut Source,
 92        source_xe: &mut Source,
 93        scratch: &mut Scratch<B>,
 94    ) where
 95        DataSkGLWE: DataRef,
 96        DataSkLWE: DataRef;
 97}
 98
 99#[derive(Clone)]
100pub struct BlindRotationKey<D: Data, BRT: BlindRotationAlgo> {
101    pub(crate) keys: Vec<GGSW<D>>,
102    pub(crate) dist: Distribution,
103    pub(crate) _phantom: PhantomData<BRT>,
104}
105
106impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Debug for BlindRotationKey<D, BRT> {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        write!(f, "{self}")
109    }
110}
111
112impl<D: Data, BRT: BlindRotationAlgo> PartialEq for BlindRotationKey<D, BRT> {
113    fn eq(&self, other: &Self) -> bool {
114        if self.keys.len() != other.keys.len() {
115            return false;
116        }
117        for (a, b) in self.keys.iter().zip(other.keys.iter()) {
118            if a != b {
119                return false;
120            }
121        }
122
123        self.dist == other.dist && self._phantom == other._phantom
124    }
125}
126
127impl<D: Data, BRT: BlindRotationAlgo> Eq for BlindRotationKey<D, BRT> {}
128
129impl<D: DataRef, BRT: BlindRotationAlgo> fmt::Display for BlindRotationKey<D, BRT> {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        for (i, key) in self.keys.iter().enumerate() {
132            write!(f, "key[{i}]: {key}")?;
133        }
134        writeln!(f, "{:?}", self.dist)
135    }
136}
137
138impl<D: DataMut, BRT: BlindRotationAlgo> FillUniform for BlindRotationKey<D, BRT> {
139    fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
140        self.keys
141            .iter_mut()
142            .for_each(|key| key.fill_uniform(log_bound, source));
143    }
144}
145
146impl<D: DataMut, BRT: BlindRotationAlgo> ReaderFrom for BlindRotationKey<D, BRT> {
147    fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
148        match Distribution::read_from(reader) {
149            Ok(dist) => self.dist = dist,
150            Err(e) => return Err(e),
151        }
152        let len: usize = reader.read_u64::<LittleEndian>()? as usize;
153        if self.keys.len() != len {
154            return Err(std::io::Error::new(
155                std::io::ErrorKind::InvalidData,
156                format!("self.keys.len()={} != read len={}", self.keys.len(), len),
157            ));
158        }
159        for key in &mut self.keys {
160            key.read_from(reader)?;
161        }
162        Ok(())
163    }
164}
165
166impl<D: DataRef, BRT: BlindRotationAlgo> WriterTo for BlindRotationKey<D, BRT> {
167    fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
168        match self.dist.write_to(writer) {
169            Ok(()) => {}
170            Err(e) => return Err(e),
171        }
172        writer.write_u64::<LittleEndian>(self.keys.len() as u64)?;
173        for key in &self.keys {
174            key.write_to(writer)?;
175        }
176        Ok(())
177    }
178}
179
180impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKeyInfos for BlindRotationKey<D, BRT> {
181    fn n_glwe(&self) -> Degree {
182        self.n()
183    }
184
185    fn n_lwe(&self) -> Degree {
186        Degree(self.keys.len() as u32)
187    }
188}
189
190impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKey<D, BRT> {
191    #[allow(dead_code)]
192    fn block_size(&self) -> usize {
193        match self.dist {
194            Distribution::BinaryBlock(value) => value,
195            _ => 1,
196        }
197    }
198}
199
200impl<D: DataRef, BRT: BlindRotationAlgo> LWEInfos for BlindRotationKey<D, BRT> {
201    fn base2k(&self) -> Base2K {
202        self.keys[0].base2k()
203    }
204
205    fn k(&self) -> TorusPrecision {
206        self.keys[0].k()
207    }
208
209    fn n(&self) -> Degree {
210        self.keys[0].n()
211    }
212
213    fn size(&self) -> usize {
214        self.keys[0].size()
215    }
216}
217
218impl<D: DataRef, BRT: BlindRotationAlgo> GLWEInfos for BlindRotationKey<D, BRT> {
219    fn rank(&self) -> Rank {
220        self.keys[0].rank()
221    }
222}
223impl<D: DataRef, BRT: BlindRotationAlgo> GGSWInfos for BlindRotationKey<D, BRT> {
224    fn dsize(&self) -> poulpy_core::layouts::Dsize {
225        Dsize(1)
226    }
227
228    fn dnum(&self) -> Dnum {
229        self.keys[0].dnum()
230    }
231}