Skip to content

Commit bcc3fd0

Browse files
committed
chore(versionable)!: Impl std::error::Error for UnversionizeError
BREAKING CHANGE: The `Upgrade` trait now requires to specify the Error type as an associated type (similar to `TryFrom`)
1 parent 411f625 commit bcc3fd0

File tree

17 files changed

+164
-55
lines changed

17 files changed

+164
-55
lines changed

tfhe/src/core_crypto/backward_compatibility/entities/compressed_modulus_switched_lwe_ciphertext.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::Infallible;
2+
13
use tfhe_versionable::{Upgrade, Version, VersionsDispatch};
24

35
use crate::core_crypto::prelude::compressed_modulus_switched_lwe_ciphertext::CompressedModulusSwitchedLweCiphertext;
@@ -17,7 +19,9 @@ pub struct CompressedModulusSwitchedLweCiphertextV0<Scalar: UnsignedInteger> {
1719
impl<Scalar: UnsignedInteger> Upgrade<CompressedModulusSwitchedLweCiphertext<Scalar>>
1820
for CompressedModulusSwitchedLweCiphertextV0<Scalar>
1921
{
20-
fn upgrade(self) -> Result<CompressedModulusSwitchedLweCiphertext<Scalar>, String> {
22+
type Error = Infallible;
23+
24+
fn upgrade(self) -> Result<CompressedModulusSwitchedLweCiphertext<Scalar>, Self::Error> {
2125
let packed_integers = PackedIntegers {
2226
packed_coeffs: self.packed_coeffs,
2327
log_modulus: self.log_modulus,

tfhe/src/core_crypto/commons/ciphertext_modulus.rs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::core_crypto::commons::traits::UnsignedInteger;
77
use crate::core_crypto::prelude::CastInto;
88
use core::num::NonZeroU128;
99
use std::cmp::Ordering;
10+
use std::fmt::Display;
1011
use std::marker::PhantomData;
1112

1213
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -58,6 +59,31 @@ pub struct SerializableCiphertextModulus {
5859
pub scalar_bits: usize,
5960
}
6061

62+
#[derive(Clone, Copy, Debug)]
63+
pub enum CiphertextModulusDeserializationError {
64+
InvalidBitWidth { expected: usize, found: usize },
65+
ZeroCustomModulus,
66+
}
67+
68+
impl Display for CiphertextModulusDeserializationError {
69+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70+
match self {
71+
Self::InvalidBitWidth { expected, found } => write!(
72+
f,
73+
"Expected an unsigned integer with {expected} bits, \
74+
found {found} bits during deserialization of CiphertextModulus, \
75+
have you mixed types during deserialization?",
76+
),
77+
Self::ZeroCustomModulus => write!(
78+
f,
79+
"Got zero modulus for CiphertextModulusInner::Custom variant"
80+
),
81+
}
82+
}
83+
}
84+
85+
impl std::error::Error for CiphertextModulusDeserializationError {}
86+
6187
impl<Scalar: UnsignedInteger> From<CiphertextModulus<Scalar>> for SerializableCiphertextModulus {
6288
fn from(value: CiphertextModulus<Scalar>) -> Self {
6389
let modulus = match value.inner {
@@ -73,17 +99,14 @@ impl<Scalar: UnsignedInteger> From<CiphertextModulus<Scalar>> for SerializableCi
7399
}
74100

75101
impl<Scalar: UnsignedInteger> TryFrom<SerializableCiphertextModulus> for CiphertextModulus<Scalar> {
76-
type Error = String;
102+
type Error = CiphertextModulusDeserializationError;
77103

78104
fn try_from(value: SerializableCiphertextModulus) -> Result<Self, Self::Error> {
79105
if value.scalar_bits != Scalar::BITS {
80-
return Err(format!(
81-
"Expected an unsigned integer with {} bits, \
82-
found {} bits during deserialization of CiphertextModulus, \
83-
have you mixed types during deserialization?",
84-
Scalar::BITS,
85-
value.scalar_bits
86-
));
106+
return Err(CiphertextModulusDeserializationError::InvalidBitWidth {
107+
expected: Scalar::BITS,
108+
found: value.scalar_bits,
109+
});
87110
}
88111

89112
let res = if value.modulus == 0 {
@@ -93,9 +116,10 @@ impl<Scalar: UnsignedInteger> TryFrom<SerializableCiphertextModulus> for Ciphert
93116
}
94117
} else {
95118
Self {
96-
inner: CiphertextModulusInner::Custom(NonZeroU128::new(value.modulus).ok_or_else(
97-
|| "Got zero modulus for CiphertextModulusInner::Custom variant".to_string(),
98-
)?),
119+
inner: CiphertextModulusInner::Custom(
120+
NonZeroU128::new(value.modulus)
121+
.ok_or(CiphertextModulusDeserializationError::ZeroCustomModulus)?,
122+
),
99123
_scalar: PhantomData,
100124
}
101125
};

tfhe/src/high_level_api/backward_compatibility/integers.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![allow(deprecated)]
22

3+
use std::convert::Infallible;
4+
35
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
46
use tfhe_versionable::{Upgrade, Version, Versionize, VersionsDispatch};
57

@@ -53,7 +55,9 @@ pub enum CompressedSignedRadixCiphertextV0 {
5355
}
5456

5557
impl Upgrade<CompressedSignedRadixCiphertext> for CompressedSignedRadixCiphertextV0 {
56-
fn upgrade(self) -> Result<CompressedSignedRadixCiphertext, String> {
58+
type Error = Infallible;
59+
60+
fn upgrade(self) -> Result<CompressedSignedRadixCiphertext, Self::Error> {
5761
match self {
5862
Self::Seeded(ct) => Ok(CompressedSignedRadixCiphertext::Seeded(ct)),
5963

@@ -89,7 +93,9 @@ pub enum CompressedRadixCiphertextV0 {
8993
}
9094

9195
impl Upgrade<CompressedRadixCiphertext> for CompressedRadixCiphertextV0 {
92-
fn upgrade(self) -> Result<CompressedRadixCiphertext, String> {
96+
type Error = Infallible;
97+
98+
fn upgrade(self) -> Result<CompressedRadixCiphertext, Self::Error> {
9399
match self {
94100
Self::Seeded(ct) => Ok(CompressedRadixCiphertext::Seeded(ct)),
95101

tfhe/src/high_level_api/backward_compatibility/keys.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ pub(crate) struct IntegerClientKeyV0 {
7171
}
7272

7373
impl Upgrade<IntegerClientKey> for IntegerClientKeyV0 {
74-
fn upgrade(self) -> Result<IntegerClientKey, String> {
74+
type Error = Infallible;
75+
76+
fn upgrade(self) -> Result<IntegerClientKey, Self::Error> {
7577
Ok(IntegerClientKey {
7678
key: self.key,
7779
wopbs_block_parameters: self.wopbs_block_parameters,
@@ -95,7 +97,9 @@ pub struct IntegerServerKeyV0 {
9597
}
9698

9799
impl Upgrade<IntegerServerKey> for IntegerServerKeyV0 {
98-
fn upgrade(self) -> Result<IntegerServerKey, String> {
100+
type Error = Infallible;
101+
102+
fn upgrade(self) -> Result<IntegerServerKey, Self::Error> {
99103
Ok(IntegerServerKey {
100104
key: self.key,
101105
wopbs_key: self.wopbs_key,
@@ -118,7 +122,9 @@ pub struct IntegerCompressedServerKeyV0 {
118122
}
119123

120124
impl Upgrade<IntegerCompressedServerKey> for IntegerCompressedServerKeyV0 {
121-
fn upgrade(self) -> Result<IntegerCompressedServerKey, String> {
125+
type Error = Infallible;
126+
127+
fn upgrade(self) -> Result<IntegerCompressedServerKey, Self::Error> {
122128
Ok(IntegerCompressedServerKey {
123129
key: self.key,
124130
cpk_key_switching_key_material: None,

tfhe/src/integer/backward_compatibility/ciphertext/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::Infallible;
2+
13
use tfhe_versionable::{Upgrade, Version, VersionsDispatch};
24

35
use crate::integer::ciphertext::{
@@ -31,7 +33,9 @@ pub struct CompactCiphertextListV0 {
3133
}
3234

3335
impl Upgrade<CompactCiphertextList> for CompactCiphertextListV0 {
34-
fn upgrade(self) -> Result<CompactCiphertextList, String> {
36+
type Error = Infallible;
37+
38+
fn upgrade(self) -> Result<CompactCiphertextList, Self::Error> {
3539
let radix_count =
3640
self.ct_list.ct_list.lwe_ciphertext_count().0 / self.num_blocks_per_integer;
3741
// Since we can't guess the type of data here, we set them by default as unsigned integer.

tfhe/src/shortint/backward_compatibility/ciphertext/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::Infallible;
2+
13
use crate::core_crypto::prelude::{
24
CompressedModulusSwitchedLweCiphertext, LweCompactCiphertextListOwned,
35
};
@@ -42,7 +44,9 @@ pub struct CompactCiphertextListV0 {
4244
}
4345

4446
impl Upgrade<CompactCiphertextList> for CompactCiphertextListV0 {
45-
fn upgrade(self) -> Result<CompactCiphertextList, String> {
47+
type Error = Infallible;
48+
49+
fn upgrade(self) -> Result<CompactCiphertextList, Self::Error> {
4650
Ok(CompactCiphertextList {
4751
ct_list: self.ct_list,
4852
degree: self.degree,
@@ -76,7 +80,9 @@ pub struct CompressedModulusSwitchedCiphertextV0 {
7680
}
7781

7882
impl Upgrade<CompressedModulusSwitchedCiphertext> for CompressedModulusSwitchedCiphertextV0 {
79-
fn upgrade(self) -> Result<CompressedModulusSwitchedCiphertext, String> {
83+
type Error = Infallible;
84+
85+
fn upgrade(self) -> Result<CompressedModulusSwitchedCiphertext, Self::Error> {
8086
Ok(CompressedModulusSwitchedCiphertext {
8187
compressed_modulus_switched_lwe_ciphertext:
8288
InternalCompressedModulusSwitchedCiphertext::Classic(

tfhe/src/shortint/backward_compatibility/public_key/mod.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,15 @@ pub struct CompactPublicKeyV0 {
2121
}
2222

2323
impl Upgrade<CompactPublicKey> for CompactPublicKeyV0 {
24-
fn upgrade(self) -> Result<CompactPublicKey, String> {
25-
let parameters = self
26-
.parameters
27-
.try_into()
28-
.map_err(|err: crate::Error| err.to_string())?;
24+
fn upgrade(self) -> Result<CompactPublicKey, Self::Error> {
25+
let parameters = self.parameters.try_into()?;
2926
Ok(CompactPublicKey {
3027
key: self.key,
3128
parameters,
3229
})
3330
}
31+
32+
type Error = crate::Error;
3433
}
3534

3635
#[derive(VersionsDispatch)]
@@ -57,16 +56,15 @@ pub struct CompressedCompactPublicKeyV0 {
5756
}
5857

5958
impl Upgrade<CompressedCompactPublicKey> for CompressedCompactPublicKeyV0 {
60-
fn upgrade(self) -> Result<CompressedCompactPublicKey, String> {
61-
let parameters = self
62-
.parameters
63-
.try_into()
64-
.map_err(|err: crate::Error| err.to_string())?;
59+
fn upgrade(self) -> Result<CompressedCompactPublicKey, Self::Error> {
60+
let parameters = self.parameters.try_into()?;
6561
Ok(CompressedCompactPublicKey {
6662
key: self.key,
6763
parameters,
6864
})
6965
}
66+
67+
type Error = crate::Error;
7068
}
7169

7270
#[derive(VersionsDispatch)]

utils/tfhe-versionable-derive/src/dispatch_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ impl DispatchType {
336336
value
337337
.upgrade()
338338
.map_err(|e|
339-
#error_ty::upgrade(#src_variant, #dest_variant, &e)
339+
#error_ty::upgrade(#src_variant, #dest_variant, e)
340340
)
341341
})
342342
}

utils/tfhe-versionable-derive/src/versionize_attribute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl VersionizeAttribute {
207207
} else if let Some(target) = &self.try_from {
208208
let target_name = format!("{}", target.to_token_stream());
209209
quote! { #target::unversionize(#arg_name).and_then(|value| TryInto::<Self>::try_into(value)
210-
.map_err(|e| #error::conversion(#target_name, &format!("{}", e))))
210+
.map_err(|e| #error::conversion(#target_name, e)))
211211
}
212212
} else {
213213
quote! { #arg_name.try_into() }

utils/tfhe-versionable/examples/failed_upgrade.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,33 @@ mod v1 {
3737
pub struct MyStruct(pub u32);
3838

3939
mod backward_compat {
40+
use std::error::Error;
41+
use std::fmt::Display;
42+
4043
use tfhe_versionable::{Upgrade, Version, VersionsDispatch};
4144

4245
use super::MyStruct;
4346

4447
#[derive(Version)]
4548
pub struct MyStructV0(pub Option<u32>);
4649

50+
#[derive(Debug, Clone)]
51+
pub struct EmptyValueError;
52+
53+
impl Display for EmptyValueError {
54+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55+
write!(f, "Value is empty")
56+
}
57+
}
58+
59+
impl Error for EmptyValueError {}
60+
4761
impl Upgrade<MyStruct> for MyStructV0 {
48-
fn upgrade(self) -> Result<MyStruct, String> {
62+
type Error = EmptyValueError;
63+
fn upgrade(self) -> Result<MyStruct, Self::Error> {
4964
match self.0 {
5065
Some(val) => Ok(MyStruct(val)),
51-
None => Err("Cannot convert from empty \"MyStructV0\"".to_string()),
66+
None => Err(EmptyValueError),
5267
}
5368
}
5469
}

0 commit comments

Comments
 (0)