1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
use super::engine_error;
use crate::specification::engines::AbstractEngine;
use crate::specification::entities::{
LweBootstrapKeyEntity, LweCiphertextVectorEntity,
LweCircuitBootstrapPrivateFunctionalPackingKeyswitchKeysEntity, PlaintextVectorEntity,
};
use crate::specification::parameters::{DecompositionBaseLog, DecompositionLevelCount};
engine_error! {
LweCiphertextVectorDiscardingCircuitBootstrapBooleanVerticalPackingError for
LweCiphertextVectorDiscardingCircuitBootstrapBooleanVerticalPackingEngine @
NullDecompositionBaseLog => "The circuit bootstrap decomposition base log must be greater \
than zero.",
NullDecompositionLevelCount => "The circuit bootstrap decomposition level count must be \
greater than zero.",
DecompositionTooLarge => "The decomposition precision (base log * level count) must not exceed \
the precision of the ciphertext.",
KeysLweDimensionMismatch => "The bootstrap key output LWE dimension must be the same as the \
input LWE dimension of the circuit bootstrap private functional \
packing keyswitch keys.",
InputLweDimensionMismatch => "The input ciphertexts LWE dimension must be the same as the \
bootstrap key input LWE dimension.",
OutputLweDimensionMismatch => "The output ciphertexts LWE dimension must be the same as the \
`cbs_pfpksk` output GLWE dimension times its output polynomial \
size.",
MalformedLookUpTables => "The input `luts` must have a size divisible by the circuit bootstrap \
private functional packing keyswitch keys output polynomial size \
times the number of output ciphertexts. This is required to get \
small look-up tables of polynomials of the same size for each \
output ciphertext.",
InvalidSmallLookUpTableSize => "The number of polynomials times the polynomial size in a small \
look-up table must be equal to 2 to the power the number of \
input ciphertexts encrypting bits."
}
impl<EngineError: std::error::Error>
LweCiphertextVectorDiscardingCircuitBootstrapBooleanVerticalPackingError<EngineError>
{
#[allow(clippy::too_many_arguments)]
pub fn perform_generic_checks<
Input: LweCiphertextVectorEntity,
Output: LweCiphertextVectorEntity,
BootstrapKey: LweBootstrapKeyEntity,
LUTs: PlaintextVectorEntity,
CBSPFPKSK: LweCircuitBootstrapPrivateFunctionalPackingKeyswitchKeysEntity,
>(
input: &Input,
output: &Output,
bsk: &BootstrapKey,
luts: &LUTs,
cbs_decomposition_level_count: DecompositionLevelCount,
cbs_decomposition_base_log: DecompositionBaseLog,
cbs_pfpksk: &CBSPFPKSK,
ciphertext_modulus_log: usize,
) -> Result<(), Self> {
if bsk.output_lwe_dimension() != cbs_pfpksk.input_lwe_dimension() {
return Err(Self::KeysLweDimensionMismatch);
}
if input.lwe_dimension() != bsk.input_lwe_dimension() {
return Err(Self::InputLweDimensionMismatch);
}
if output.lwe_dimension().0
!= cbs_pfpksk.output_glwe_dimension().0 * cbs_pfpksk.output_polynomial_size().0
{
return Err(Self::OutputLweDimensionMismatch);
}
let lut_polynomial_size = cbs_pfpksk.output_polynomial_size().0;
if luts.plaintext_count().0 % (lut_polynomial_size * output.lwe_ciphertext_count().0) != 0 {
return Err(Self::MalformedLookUpTables);
}
let small_lut_size = luts.plaintext_count().0 / output.lwe_ciphertext_count().0;
if small_lut_size < lut_polynomial_size {
return Err(Self::InvalidSmallLookUpTableSize);
}
if cbs_decomposition_level_count.0 == 0 {
return Err(Self::NullDecompositionBaseLog);
}
if cbs_decomposition_level_count.0 == 0 {
return Err(Self::NullDecompositionLevelCount);
}
if cbs_decomposition_base_log.0 * cbs_decomposition_level_count.0 > ciphertext_modulus_log {
return Err(Self::DecompositionTooLarge);
}
Ok(())
}
}
pub trait LweCiphertextVectorDiscardingCircuitBootstrapBooleanVerticalPackingEngine<
Input,
Output,
BootstrapKey,
LUTs,
CirctuiBootstrapFunctionalPackingKeyswitchKeys,
>: AbstractEngine where
Input: LweCiphertextVectorEntity,
Output: LweCiphertextVectorEntity,
BootstrapKey: LweBootstrapKeyEntity,
LUTs: PlaintextVectorEntity,
CirctuiBootstrapFunctionalPackingKeyswitchKeys:
LweCircuitBootstrapPrivateFunctionalPackingKeyswitchKeysEntity,
{
#[allow(clippy::too_many_arguments)]
fn discard_circuit_bootstrap_boolean_vertical_packing_lwe_ciphertext_vector(
&mut self,
output: &mut Output,
input: &Input,
bsk: &BootstrapKey,
luts: &LUTs,
cbs_level_count: DecompositionLevelCount,
cbs_base_log: DecompositionBaseLog,
cbs_pfpksk: &CirctuiBootstrapFunctionalPackingKeyswitchKeys,
) -> Result<
(),
LweCiphertextVectorDiscardingCircuitBootstrapBooleanVerticalPackingError<Self::EngineError>,
>;
#[allow(clippy::too_many_arguments)]
unsafe fn discard_circuit_bootstrap_boolean_vertical_packing_lwe_ciphertext_vector_unchecked(
&mut self,
output: &mut Output,
input: &Input,
bsk: &BootstrapKey,
luts: &LUTs,
cbs_level_count: DecompositionLevelCount,
cbs_base_log: DecompositionBaseLog,
cbs_pfpksk: &CirctuiBootstrapFunctionalPackingKeyswitchKeys,
);
}