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}