mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-10 07:08:03 -05:00
feat(hlapi): add CompressedSquashedNoiseCiphertextList
This commit is contained in:
@@ -2,9 +2,10 @@ use serde::{Deserialize, Serialize};
|
||||
use tfhe_versionable::{Upgrade, Version, VersionsDispatch};
|
||||
|
||||
use crate::high_level_api::booleans::{
|
||||
InnerBoolean, InnerBooleanVersionOwned, InnerCompressedFheBool,
|
||||
InnerBoolean, InnerBooleanVersionOwned, InnerCompressedFheBool, InnerSquashedNoiseBoolean,
|
||||
InnerSquashedNoiseBooleanVersionOwned, SquashedNoiseFheBool,
|
||||
};
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use crate::{CompressedFheBool, FheBool, Tag};
|
||||
use std::convert::Infallible;
|
||||
|
||||
@@ -72,8 +73,27 @@ pub(crate) enum InnerSquashedNoiseBooleanVersionedOwned {
|
||||
V0(InnerSquashedNoiseBooleanVersionOwned),
|
||||
}
|
||||
|
||||
#[derive(Version)]
|
||||
pub struct SquashedNoiseFheBoolV0 {
|
||||
pub(in crate::high_level_api) inner: InnerSquashedNoiseBoolean,
|
||||
pub(in crate::high_level_api) tag: Tag,
|
||||
}
|
||||
|
||||
impl Upgrade<SquashedNoiseFheBool> for SquashedNoiseFheBoolV0 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<SquashedNoiseFheBool, Self::Error> {
|
||||
Ok(SquashedNoiseFheBool::new(
|
||||
self.inner,
|
||||
SquashedNoiseCiphertextState::Normal,
|
||||
self.tag,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Squashed Noise
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum SquashedNoiseFheBoolVersions {
|
||||
V0(SquashedNoiseFheBool),
|
||||
V0(SquashedNoiseFheBoolV0),
|
||||
V1(SquashedNoiseFheBool),
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use std::convert::Infallible;
|
||||
use tfhe_versionable::{Upgrade, Version, VersionsDispatch};
|
||||
|
||||
use crate::{CompressedCiphertextList, Tag};
|
||||
use crate::{CompressedCiphertextList, CompressedSquashedNoiseCiphertextList, Tag};
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
#[allow(unused)]
|
||||
pub(crate) enum SquashedNoiseCiphertextStateVersions {
|
||||
V0(SquashedNoiseCiphertextState),
|
||||
}
|
||||
|
||||
#[derive(Version)]
|
||||
pub struct CompressedCiphertextListV0(crate::integer::ciphertext::CompressedCiphertextList);
|
||||
@@ -40,3 +47,8 @@ pub enum CompressedCiphertextListVersions {
|
||||
V1(CompressedCiphertextListV1),
|
||||
V2(CompressedCiphertextList),
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum CompressedSquashedNoiseCiphertextListVersions {
|
||||
V0(CompressedSquashedNoiseCiphertextList),
|
||||
}
|
||||
|
||||
@@ -3,8 +3,13 @@ use std::convert::Infallible;
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use tfhe_versionable::{Upgrade, Version, VersionsDispatch};
|
||||
|
||||
use self::signed::SignedRadixCiphertext;
|
||||
use self::unsigned::RadixCiphertext as UnsignedRadixCiphertext;
|
||||
use crate::high_level_api::global_state::with_cpu_internal_keys;
|
||||
use crate::high_level_api::integers::signed::InnerSquashedNoiseSignedRadixCiphertext;
|
||||
use crate::high_level_api::integers::unsigned::InnerSquashedNoiseRadixCiphertext;
|
||||
use crate::high_level_api::integers::*;
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use crate::integer::backward_compatibility::ciphertext::{
|
||||
CompressedModulusSwitchedRadixCiphertextTFHE06,
|
||||
CompressedModulusSwitchedSignedRadixCiphertextTFHE06,
|
||||
@@ -19,9 +24,6 @@ use crate::shortint::{Ciphertext, ServerKey};
|
||||
use crate::Tag;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use self::signed::SignedRadixCiphertext;
|
||||
use self::unsigned::RadixCiphertext as UnsignedRadixCiphertext;
|
||||
|
||||
// Manual impl
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub(crate) enum SignedRadixCiphertextVersionedOwned {
|
||||
@@ -228,9 +230,28 @@ pub(crate) enum InnerSquashedNoiseRadixCiphertextVersionedOwned {
|
||||
V0(InnerSquashedNoiseRadixCiphertextVersionOwned),
|
||||
}
|
||||
|
||||
#[derive(Version)]
|
||||
pub struct SquashedNoiseFheUintV0 {
|
||||
pub(in crate::high_level_api) inner: InnerSquashedNoiseRadixCiphertext,
|
||||
pub(in crate::high_level_api) tag: Tag,
|
||||
}
|
||||
|
||||
impl Upgrade<SquashedNoiseFheUint> for SquashedNoiseFheUintV0 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<SquashedNoiseFheUint, Self::Error> {
|
||||
Ok(SquashedNoiseFheUint::new(
|
||||
self.inner,
|
||||
SquashedNoiseCiphertextState::Normal,
|
||||
self.tag,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum SquashedNoiseFheUintVersions {
|
||||
V0(SquashedNoiseFheUint),
|
||||
V0(SquashedNoiseFheUintV0),
|
||||
V1(SquashedNoiseFheUint),
|
||||
}
|
||||
|
||||
// Manual impl
|
||||
@@ -239,7 +260,26 @@ pub(crate) enum InnerSquashedNoiseSignedRadixCiphertextVersionedOwned {
|
||||
V0(InnerSquashedNoiseSignedRadixCiphertextVersionOwned),
|
||||
}
|
||||
|
||||
#[derive(Version)]
|
||||
pub struct SquashedNoiseFheIntV0 {
|
||||
pub(in crate::high_level_api) inner: InnerSquashedNoiseSignedRadixCiphertext,
|
||||
pub(in crate::high_level_api) tag: Tag,
|
||||
}
|
||||
|
||||
impl Upgrade<SquashedNoiseFheInt> for SquashedNoiseFheIntV0 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<SquashedNoiseFheInt, Self::Error> {
|
||||
Ok(SquashedNoiseFheInt::new(
|
||||
self.inner,
|
||||
SquashedNoiseCiphertextState::Normal,
|
||||
self.tag,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum SquashedNoiseFheIntVersions {
|
||||
V0(SquashedNoiseFheInt),
|
||||
V0(SquashedNoiseFheIntV0),
|
||||
V1(SquashedNoiseFheInt),
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ use crate::high_level_api::keys::*;
|
||||
use crate::integer::compression_keys::{
|
||||
CompressedCompressionKey, CompressedDecompressionKey, CompressionKey, DecompressionKey,
|
||||
};
|
||||
use crate::integer::noise_squashing::{
|
||||
CompressedNoiseSquashingKey, NoiseSquashingKey, NoiseSquashingPrivateKey,
|
||||
};
|
||||
use crate::Tag;
|
||||
use std::convert::Infallible;
|
||||
use tfhe_versionable::deprecation::{Deprecable, Deprecated};
|
||||
@@ -182,17 +185,17 @@ pub(crate) struct IntegerClientKeyV3 {
|
||||
pub(crate) compression_key: Option<crate::integer::compression_keys::CompressionPrivateKeys>,
|
||||
}
|
||||
|
||||
impl Upgrade<IntegerClientKey> for IntegerClientKeyV3 {
|
||||
impl Upgrade<IntegerClientKeyV4> for IntegerClientKeyV3 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<IntegerClientKey, Self::Error> {
|
||||
fn upgrade(self) -> Result<IntegerClientKeyV4, Self::Error> {
|
||||
let Self {
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
} = self;
|
||||
|
||||
Ok(IntegerClientKey {
|
||||
Ok(IntegerClientKeyV4 {
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
@@ -201,6 +204,14 @@ impl Upgrade<IntegerClientKey> for IntegerClientKeyV3 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Version)]
|
||||
pub(crate) struct IntegerClientKeyV4 {
|
||||
pub(crate) key: crate::integer::ClientKey,
|
||||
pub(crate) dedicated_compact_private_key: Option<CompactPrivateKey>,
|
||||
pub(crate) compression_key: Option<crate::integer::compression_keys::CompressionPrivateKeys>,
|
||||
pub(crate) noise_squashing_private_key: Option<NoiseSquashingPrivateKey>,
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
#[allow(unused)]
|
||||
pub(crate) enum IntegerClientKeyVersions {
|
||||
@@ -208,7 +219,29 @@ pub(crate) enum IntegerClientKeyVersions {
|
||||
V1(Deprecated<IntegerClientKey>),
|
||||
V2(IntegerClientKeyV2),
|
||||
V3(IntegerClientKeyV3),
|
||||
V4(IntegerClientKey),
|
||||
V4(IntegerClientKeyV4),
|
||||
V5(IntegerClientKey),
|
||||
}
|
||||
|
||||
impl Upgrade<IntegerClientKey> for IntegerClientKeyV4 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<IntegerClientKey, Self::Error> {
|
||||
let Self {
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_private_key,
|
||||
} = self;
|
||||
|
||||
Ok(IntegerClientKey {
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_private_key,
|
||||
noise_squashing_compression_private_key: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Deprecable for IntegerServerKey {
|
||||
@@ -225,7 +258,38 @@ pub struct IntegerServerKeyV4 {
|
||||
pub(crate) decompression_key: Option<DecompressionKey>,
|
||||
}
|
||||
|
||||
impl Upgrade<IntegerServerKey> for IntegerServerKeyV4 {
|
||||
impl Upgrade<IntegerServerKeyV5> for IntegerServerKeyV4 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<IntegerServerKeyV5, Self::Error> {
|
||||
let Self {
|
||||
key,
|
||||
cpk_key_switching_key_material,
|
||||
compression_key,
|
||||
decompression_key,
|
||||
} = self;
|
||||
|
||||
Ok(IntegerServerKeyV5 {
|
||||
key,
|
||||
cpk_key_switching_key_material,
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Version)]
|
||||
pub struct IntegerServerKeyV5 {
|
||||
pub(crate) key: crate::integer::ServerKey,
|
||||
pub(crate) cpk_key_switching_key_material:
|
||||
Option<crate::integer::key_switching_key::KeySwitchingKeyMaterial>,
|
||||
pub(crate) compression_key: Option<CompressionKey>,
|
||||
pub(crate) decompression_key: Option<DecompressionKey>,
|
||||
pub(crate) noise_squashing_key: Option<NoiseSquashingKey>,
|
||||
}
|
||||
|
||||
impl Upgrade<IntegerServerKey> for IntegerServerKeyV5 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<IntegerServerKey, Self::Error> {
|
||||
@@ -234,6 +298,7 @@ impl Upgrade<IntegerServerKey> for IntegerServerKeyV4 {
|
||||
cpk_key_switching_key_material,
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
} = self;
|
||||
|
||||
Ok(IntegerServerKey {
|
||||
@@ -241,7 +306,8 @@ impl Upgrade<IntegerServerKey> for IntegerServerKeyV4 {
|
||||
cpk_key_switching_key_material,
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key: None,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -253,7 +319,8 @@ pub enum IntegerServerKeyVersions {
|
||||
V2(Deprecated<IntegerServerKey>),
|
||||
V3(Deprecated<IntegerServerKey>),
|
||||
V4(IntegerServerKeyV4),
|
||||
V5(IntegerServerKey),
|
||||
V5(IntegerServerKeyV5),
|
||||
V6(IntegerServerKey),
|
||||
}
|
||||
|
||||
impl Deprecable for IntegerCompressedServerKey {
|
||||
@@ -270,10 +337,10 @@ pub struct IntegerCompressedServerKeyV2 {
|
||||
pub(crate) decompression_key: Option<CompressedDecompressionKey>,
|
||||
}
|
||||
|
||||
impl Upgrade<IntegerCompressedServerKey> for IntegerCompressedServerKeyV2 {
|
||||
impl Upgrade<IntegerCompressedServerKeyV3> for IntegerCompressedServerKeyV2 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<IntegerCompressedServerKey, Self::Error> {
|
||||
fn upgrade(self) -> Result<IntegerCompressedServerKeyV3, Self::Error> {
|
||||
let Self {
|
||||
key,
|
||||
cpk_key_switching_key_material,
|
||||
@@ -281,7 +348,7 @@ impl Upgrade<IntegerCompressedServerKey> for IntegerCompressedServerKeyV2 {
|
||||
decompression_key,
|
||||
} = self;
|
||||
|
||||
Ok(IntegerCompressedServerKey {
|
||||
Ok(IntegerCompressedServerKeyV3 {
|
||||
key,
|
||||
cpk_key_switching_key_material,
|
||||
compression_key,
|
||||
@@ -291,12 +358,46 @@ impl Upgrade<IntegerCompressedServerKey> for IntegerCompressedServerKeyV2 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Version)]
|
||||
pub struct IntegerCompressedServerKeyV3 {
|
||||
pub(crate) key: crate::integer::CompressedServerKey,
|
||||
pub(crate) cpk_key_switching_key_material:
|
||||
Option<crate::integer::key_switching_key::CompressedKeySwitchingKeyMaterial>,
|
||||
pub(crate) compression_key: Option<CompressedCompressionKey>,
|
||||
pub(crate) decompression_key: Option<CompressedDecompressionKey>,
|
||||
pub(crate) noise_squashing_key: Option<CompressedNoiseSquashingKey>,
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
pub enum IntegerCompressedServerKeyVersions {
|
||||
V0(Deprecated<IntegerCompressedServerKey>),
|
||||
V1(Deprecated<IntegerCompressedServerKey>),
|
||||
V2(IntegerCompressedServerKeyV2),
|
||||
V3(IntegerCompressedServerKey),
|
||||
V3(IntegerCompressedServerKeyV3),
|
||||
V4(IntegerCompressedServerKey),
|
||||
}
|
||||
|
||||
impl Upgrade<IntegerCompressedServerKey> for IntegerCompressedServerKeyV3 {
|
||||
type Error = Infallible;
|
||||
|
||||
fn upgrade(self) -> Result<IntegerCompressedServerKey, Self::Error> {
|
||||
let Self {
|
||||
key,
|
||||
cpk_key_switching_key_material,
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
} = self;
|
||||
|
||||
Ok(IntegerCompressedServerKey {
|
||||
key,
|
||||
cpk_key_switching_key_material,
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(VersionsDispatch)]
|
||||
|
||||
@@ -4,7 +4,9 @@ pub use squashed_noise::SquashedNoiseFheBool;
|
||||
|
||||
pub(in crate::high_level_api) use compressed::InnerCompressedFheBool;
|
||||
pub(in crate::high_level_api) use inner::{InnerBoolean, InnerBooleanVersionOwned};
|
||||
pub(in crate::high_level_api) use squashed_noise::InnerSquashedNoiseBooleanVersionOwned;
|
||||
pub(in crate::high_level_api) use squashed_noise::{
|
||||
InnerSquashedNoiseBoolean, InnerSquashedNoiseBooleanVersionOwned,
|
||||
};
|
||||
|
||||
mod base;
|
||||
mod compressed;
|
||||
|
||||
@@ -6,7 +6,8 @@ use crate::high_level_api::details::MaybeCloned;
|
||||
use crate::high_level_api::errors::UninitializedNoiseSquashing;
|
||||
use crate::high_level_api::global_state::{self, with_internal_keys};
|
||||
use crate::high_level_api::keys::InternalServerKey;
|
||||
use crate::high_level_api::traits::{FheDecrypt, SquashNoise};
|
||||
use crate::high_level_api::traits::{FheDecrypt, SquashNoise, Tagged};
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use crate::integer::ciphertext::SquashedNoiseBooleanBlock;
|
||||
#[cfg(feature = "gpu")]
|
||||
use crate::integer::gpu::ciphertext::boolean_value::CudaBooleanBlock;
|
||||
@@ -125,10 +126,21 @@ impl InnerSquashedNoiseBoolean {
|
||||
#[derive(Clone, serde::Deserialize, serde::Serialize, Versionize)]
|
||||
#[versionize(SquashedNoiseFheBoolVersions)]
|
||||
pub struct SquashedNoiseFheBool {
|
||||
inner: InnerSquashedNoiseBoolean,
|
||||
pub(in crate::high_level_api) inner: InnerSquashedNoiseBoolean,
|
||||
pub(in crate::high_level_api) state: SquashedNoiseCiphertextState,
|
||||
tag: Tag,
|
||||
}
|
||||
|
||||
impl SquashedNoiseFheBool {
|
||||
pub(in crate::high_level_api) fn new(
|
||||
inner: InnerSquashedNoiseBoolean,
|
||||
state: SquashedNoiseCiphertextState,
|
||||
tag: Tag,
|
||||
) -> Self {
|
||||
Self { inner, state, tag }
|
||||
}
|
||||
}
|
||||
|
||||
impl Named for SquashedNoiseFheBool {
|
||||
const NAME: &'static str = "high_level_api::SquashedNoiseFheBool";
|
||||
}
|
||||
@@ -143,20 +155,23 @@ impl SquashedNoiseFheBool {
|
||||
|
||||
impl FheDecrypt<bool> for SquashedNoiseFheBool {
|
||||
fn decrypt(&self, key: &ClientKey) -> bool {
|
||||
key.key
|
||||
.noise_squashing_private_key
|
||||
.as_ref()
|
||||
.map(|noise_squashing_private_key| {
|
||||
noise_squashing_private_key.decrypt_bool(&self.inner.on_cpu())
|
||||
})
|
||||
.expect(
|
||||
"No noise squashing private key in your ClientKey, cannot decrypt. \
|
||||
Did you call `enable_noise_squashing` when creating your Config?",
|
||||
)
|
||||
let noise_squashing_private_key = key.private_noise_squashing_decryption_key(self.state);
|
||||
noise_squashing_private_key
|
||||
.decrypt_bool(&self.inner.on_cpu())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Tagged for SquashedNoiseFheBool {
|
||||
fn tag(&self) -> &Tag {
|
||||
&self.tag
|
||||
}
|
||||
|
||||
fn tag_mut(&mut self) -> &mut Tag {
|
||||
&mut self.tag
|
||||
}
|
||||
}
|
||||
|
||||
impl SquashNoise for FheBool {
|
||||
type Output = SquashedNoiseFheBool;
|
||||
|
||||
@@ -176,6 +191,7 @@ impl SquashNoise for FheBool {
|
||||
&self.ciphertext.on_cpu(),
|
||||
)?,
|
||||
),
|
||||
state: SquashedNoiseCiphertextState::Normal,
|
||||
tag: server_key.tag.clone(),
|
||||
})
|
||||
}
|
||||
@@ -211,6 +227,7 @@ impl SquashNoise for FheBool {
|
||||
|
||||
Ok(SquashedNoiseFheBool {
|
||||
inner: InnerSquashedNoiseBoolean::Cpu(cpu_squashed_block),
|
||||
state: SquashedNoiseCiphertextState::Normal,
|
||||
tag: cuda_key.tag.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
use crate::backward_compatibility::compressed_ciphertext_list::CompressedSquashedNoiseCiphertextListVersions;
|
||||
use crate::high_level_api::booleans::InnerSquashedNoiseBoolean;
|
||||
use crate::high_level_api::global_state::try_with_internal_keys;
|
||||
use crate::high_level_api::integers::signed::InnerSquashedNoiseSignedRadixCiphertext;
|
||||
use crate::high_level_api::integers::unsigned::InnerSquashedNoiseRadixCiphertext;
|
||||
use crate::high_level_api::keys::InternalServerKey;
|
||||
use crate::high_level_api::traits::Tagged;
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use crate::integer::ciphertext::{
|
||||
CompressedSquashedNoiseCiphertextList as IntegerCompressedSquashedNoiseCiphertextList,
|
||||
DataKind, SquashedNoiseBooleanBlock, SquashedNoiseExpandable, SquashedNoiseRadixCiphertext,
|
||||
SquashedNoiseSignedRadixCiphertext,
|
||||
};
|
||||
use crate::named::Named;
|
||||
use crate::shortint::ciphertext::SquashedNoiseCiphertext;
|
||||
use crate::{SquashedNoiseFheBool, SquashedNoiseFheInt, SquashedNoiseFheUint, Tag, Versionize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tfhe_versionable::{Unversionize, UnversionizeError, VersionizeOwned};
|
||||
|
||||
pub(in crate::high_level_api) enum InnerCompressedSquashedNoiseCiphertextList {
|
||||
Cpu(IntegerCompressedSquashedNoiseCiphertextList),
|
||||
}
|
||||
|
||||
impl Versionize for InnerCompressedSquashedNoiseCiphertextList {
|
||||
type Versioned<'vers>
|
||||
= <IntegerCompressedSquashedNoiseCiphertextList as Versionize>::Versioned<'vers>
|
||||
where
|
||||
Self: 'vers;
|
||||
|
||||
fn versionize(&self) -> Self::Versioned<'_> {
|
||||
self.on_cpu().versionize()
|
||||
}
|
||||
}
|
||||
|
||||
impl VersionizeOwned for InnerCompressedSquashedNoiseCiphertextList {
|
||||
type VersionedOwned =
|
||||
<IntegerCompressedSquashedNoiseCiphertextList as VersionizeOwned>::VersionedOwned;
|
||||
|
||||
fn versionize_owned(self) -> Self::VersionedOwned {
|
||||
self.into_cpu().versionize_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Unversionize for InnerCompressedSquashedNoiseCiphertextList {
|
||||
fn unversionize(versioned: Self::VersionedOwned) -> Result<Self, UnversionizeError> {
|
||||
IntegerCompressedSquashedNoiseCiphertextList::unversionize(versioned).map(Self::Cpu)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for InnerCompressedSquashedNoiseCiphertextList {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.on_cpu().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for InnerCompressedSquashedNoiseCiphertextList {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let mut new = IntegerCompressedSquashedNoiseCiphertextList::deserialize(deserializer)
|
||||
.map(Self::Cpu)?;
|
||||
|
||||
if let Some(device) = crate::high_level_api::global_state::device_of_internal_keys() {
|
||||
new.move_to_device(device)
|
||||
.map_err(serde::de::Error::custom)?;
|
||||
}
|
||||
|
||||
Ok(new)
|
||||
}
|
||||
}
|
||||
|
||||
impl InnerCompressedSquashedNoiseCiphertextList {
|
||||
fn on_cpu(&self) -> &IntegerCompressedSquashedNoiseCiphertextList {
|
||||
match self {
|
||||
Self::Cpu(inner) => inner,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_cpu(self) -> IntegerCompressedSquashedNoiseCiphertextList {
|
||||
match self {
|
||||
Self::Cpu(inner) => inner,
|
||||
}
|
||||
}
|
||||
|
||||
fn current_device(&self) -> crate::Device {
|
||||
match self {
|
||||
Self::Cpu(_) => crate::Device::Cpu,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::unnecessary_wraps, reason = "It depends on activated features")]
|
||||
fn move_to_device(&mut self, target_device: crate::Device) -> crate::Result<()> {
|
||||
let current_device = self.current_device();
|
||||
if current_device == target_device {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let cpu_ct = self.on_cpu();
|
||||
|
||||
match target_device {
|
||||
crate::Device::Cpu => {
|
||||
*self = Self::Cpu(cpu_ct.to_owned());
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
crate::Device::CudaGpu => Err(crate::error!(
|
||||
"Cuda does not support CompressedSquashedNoiseCiphertextList"
|
||||
)),
|
||||
#[cfg(feature = "hpu")]
|
||||
crate::Device::Hpu => Err(crate::error!(
|
||||
"Hpu does not support CompressedSquashedNoiseCiphertextList"
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Versionize)]
|
||||
#[versionize(CompressedSquashedNoiseCiphertextListVersions)]
|
||||
pub struct CompressedSquashedNoiseCiphertextList {
|
||||
pub(in crate::high_level_api) inner: InnerCompressedSquashedNoiseCiphertextList,
|
||||
pub(crate) tag: Tag,
|
||||
}
|
||||
|
||||
impl Named for CompressedSquashedNoiseCiphertextList {
|
||||
const NAME: &'static str = "high_level_api::CompressedSquashedNoiseCiphertextList";
|
||||
}
|
||||
|
||||
impl CompressedSquashedNoiseCiphertextList {
|
||||
pub fn builder() -> CompressedSquashedNoiseCiphertextListBuilder {
|
||||
CompressedSquashedNoiseCiphertextListBuilder::new()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
match &self.inner {
|
||||
InnerCompressedSquashedNoiseCiphertextList::Cpu(inner) => inner.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn get<T>(&self, index: usize) -> crate::Result<Option<T>>
|
||||
where
|
||||
T: HlSquashedNoiseExpandable + Tagged,
|
||||
{
|
||||
let mut r = match &self.inner {
|
||||
InnerCompressedSquashedNoiseCiphertextList::Cpu(inner) => inner.get::<T>(index),
|
||||
};
|
||||
|
||||
if let Ok(Some(ct)) = &mut r {
|
||||
*ct.tag_mut() = self.tag.clone();
|
||||
}
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HlSquashedNoiseExpandable: SquashedNoiseExpandable {}
|
||||
|
||||
fn create_error_message(tried: DataKind, actual: DataKind) -> crate::Error {
|
||||
fn name(kind: DataKind) -> &'static str {
|
||||
match kind {
|
||||
DataKind::Unsigned(_) => "SquashedNoiseFheUint",
|
||||
DataKind::Signed(_) => "SquashedNoiseFheInt",
|
||||
DataKind::Boolean => "SquashedNoiseFheBool",
|
||||
DataKind::String { .. } => "SquashedNoiseFheString",
|
||||
}
|
||||
}
|
||||
crate::error!(
|
||||
"Tried to expand a {}, but a {} is stored in this slot",
|
||||
name(tried),
|
||||
name(actual)
|
||||
)
|
||||
}
|
||||
|
||||
impl SquashedNoiseExpandable for SquashedNoiseFheBool {
|
||||
fn from_expanded_blocks(
|
||||
blocks: Vec<SquashedNoiseCiphertext>,
|
||||
kind: DataKind,
|
||||
) -> crate::Result<Self> {
|
||||
if kind == DataKind::Boolean {
|
||||
SquashedNoiseBooleanBlock::from_expanded_blocks(blocks, kind).map(|v| {
|
||||
Self::new(
|
||||
InnerSquashedNoiseBoolean::Cpu(v),
|
||||
SquashedNoiseCiphertextState::PostDecompression,
|
||||
Tag::default(),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
Err(create_error_message(DataKind::Boolean, kind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SquashedNoiseExpandable for SquashedNoiseFheUint {
|
||||
fn from_expanded_blocks(
|
||||
blocks: Vec<SquashedNoiseCiphertext>,
|
||||
kind: DataKind,
|
||||
) -> crate::Result<Self> {
|
||||
if matches!(kind, DataKind::Unsigned(_)) {
|
||||
SquashedNoiseRadixCiphertext::from_expanded_blocks(blocks, kind).map(|v| {
|
||||
Self::new(
|
||||
InnerSquashedNoiseRadixCiphertext::Cpu(v),
|
||||
SquashedNoiseCiphertextState::PostDecompression,
|
||||
Tag::default(),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
Err(create_error_message(DataKind::Unsigned(0), kind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SquashedNoiseExpandable for SquashedNoiseFheInt {
|
||||
fn from_expanded_blocks(
|
||||
blocks: Vec<SquashedNoiseCiphertext>,
|
||||
kind: DataKind,
|
||||
) -> crate::Result<Self> {
|
||||
if matches!(kind, DataKind::Signed(_)) {
|
||||
SquashedNoiseSignedRadixCiphertext::from_expanded_blocks(blocks, kind).map(|v| {
|
||||
Self::new(
|
||||
InnerSquashedNoiseSignedRadixCiphertext::Cpu(v),
|
||||
SquashedNoiseCiphertextState::PostDecompression,
|
||||
Tag::default(),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
Err(create_error_message(DataKind::Signed(0), kind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HlSquashedNoiseExpandable for SquashedNoiseFheBool {}
|
||||
impl HlSquashedNoiseExpandable for SquashedNoiseFheUint {}
|
||||
impl HlSquashedNoiseExpandable for SquashedNoiseFheInt {}
|
||||
|
||||
mod private {
|
||||
use crate::shortint::ciphertext::SquashedNoiseCiphertext;
|
||||
|
||||
pub enum SquashedNoiseToBeCompressed {
|
||||
Cpu(Vec<SquashedNoiseCiphertext>),
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HlSquashedNoiseCompressible {
|
||||
fn compress_into(self, messages: &mut Vec<(private::SquashedNoiseToBeCompressed, DataKind)>);
|
||||
}
|
||||
|
||||
impl HlSquashedNoiseCompressible for SquashedNoiseFheBool {
|
||||
fn compress_into(self, messages: &mut Vec<(private::SquashedNoiseToBeCompressed, DataKind)>) {
|
||||
let kind = DataKind::Boolean;
|
||||
match self.inner {
|
||||
InnerSquashedNoiseBoolean::Cpu(cpu_ct) => messages.push((
|
||||
private::SquashedNoiseToBeCompressed::Cpu(vec![cpu_ct.ciphertext]),
|
||||
kind,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HlSquashedNoiseCompressible for SquashedNoiseFheUint {
|
||||
fn compress_into(self, messages: &mut Vec<(private::SquashedNoiseToBeCompressed, DataKind)>) {
|
||||
match self.inner {
|
||||
InnerSquashedNoiseRadixCiphertext::Cpu(cpu_ct) => {
|
||||
let kind = DataKind::Unsigned(cpu_ct.original_block_count);
|
||||
messages.push((
|
||||
private::SquashedNoiseToBeCompressed::Cpu(cpu_ct.packed_blocks),
|
||||
kind,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HlSquashedNoiseCompressible for SquashedNoiseFheInt {
|
||||
fn compress_into(self, messages: &mut Vec<(private::SquashedNoiseToBeCompressed, DataKind)>) {
|
||||
match self.inner {
|
||||
InnerSquashedNoiseSignedRadixCiphertext::Cpu(cpu_ct) => {
|
||||
let kind = DataKind::Signed(cpu_ct.original_block_count);
|
||||
messages.push((
|
||||
private::SquashedNoiseToBeCompressed::Cpu(cpu_ct.packed_blocks),
|
||||
kind,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CompressedSquashedNoiseCiphertextListBuilder {
|
||||
inner: Vec<(private::SquashedNoiseToBeCompressed, DataKind)>,
|
||||
}
|
||||
|
||||
impl Default for CompressedSquashedNoiseCiphertextListBuilder {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CompressedSquashedNoiseCiphertextListBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self { inner: vec![] }
|
||||
}
|
||||
|
||||
pub fn push<T>(&mut self, value: T) -> &mut Self
|
||||
where
|
||||
T: HlSquashedNoiseCompressible,
|
||||
{
|
||||
value.compress_into(&mut self.inner);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(&self) -> crate::Result<CompressedSquashedNoiseCiphertextList> {
|
||||
try_with_internal_keys(|keys| match keys {
|
||||
Some(InternalServerKey::Cpu(cpu_key)) => {
|
||||
let mut flat_cpu_blocks = vec![];
|
||||
for (element, _) in &self.inner {
|
||||
match element {
|
||||
private::SquashedNoiseToBeCompressed::Cpu(cpu_blocks) => {
|
||||
flat_cpu_blocks.extend_from_slice(cpu_blocks.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
cpu_key
|
||||
.key
|
||||
.noise_squashing_compression_key
|
||||
.as_ref()
|
||||
.ok_or_else(|| {
|
||||
crate::Error::new(
|
||||
"Compression key for squashed noise data not set in server key"
|
||||
.to_owned(),
|
||||
)
|
||||
})
|
||||
.map(|compression_key| {
|
||||
let compressed_list = compression_key
|
||||
.key
|
||||
.compress_noise_squashed_ciphertexts_into_list(&flat_cpu_blocks);
|
||||
let info = self.inner.iter().map(|(_, kind)| *kind).collect();
|
||||
|
||||
CompressedSquashedNoiseCiphertextList {
|
||||
inner: InnerCompressedSquashedNoiseCiphertextList::Cpu(
|
||||
IntegerCompressedSquashedNoiseCiphertextList {
|
||||
list: compressed_list,
|
||||
info,
|
||||
},
|
||||
),
|
||||
tag: cpu_key.tag.clone(),
|
||||
}
|
||||
})
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
Some(InternalServerKey::Cuda(_)) => Err(crate::error!(
|
||||
"Cuda GPU does not support compression of squashed noise ciphertexts"
|
||||
)),
|
||||
#[cfg(feature = "hpu")]
|
||||
Some(InternalServerKey::Hpu(_)) => Err(crate::error!(
|
||||
"HPU does not support compression of squashed noise ciphertexts"
|
||||
)),
|
||||
None => Err(crate::high_level_api::errors::UninitializedServerKey.into()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
use crate::safe_serialization::{safe_deserialize, safe_serialize};
|
||||
use crate::shortint::parameters::current_params::*;
|
||||
use crate::{generate_keys, set_server_key, ConfigBuilder, FheBool, FheInt32, FheUint32};
|
||||
use rand::Rng;
|
||||
|
||||
#[test]
|
||||
fn test_compressed_squashed_noise_ciphertext_list() {
|
||||
let params = V1_3_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let noise_squashing_params =
|
||||
V1_3_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let noise_squashing_compression_params =
|
||||
V1_3_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let config = ConfigBuilder::with_custom_parameters(params)
|
||||
.enable_noise_squashing(noise_squashing_params)
|
||||
.enable_noise_squashing_compression(noise_squashing_compression_params)
|
||||
.build();
|
||||
|
||||
let (cks, sks) = generate_keys(config);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let clear_a = rng.gen::<i32>();
|
||||
let clear_b = rng.gen::<u32>();
|
||||
let clear_c = rng.gen_bool(0.5);
|
||||
|
||||
let a = FheInt32::encrypt(clear_a, &cks);
|
||||
let b = FheUint32::encrypt(clear_b, &cks);
|
||||
let c = FheBool::encrypt(clear_c, &cks);
|
||||
|
||||
set_server_key(sks);
|
||||
|
||||
let ns_a = a.squash_noise().unwrap();
|
||||
let ns_b = b.squash_noise().unwrap();
|
||||
let ns_c = c.squash_noise().unwrap();
|
||||
|
||||
let list = CompressedSquashedNoiseCiphertextList::builder()
|
||||
.push(ns_a)
|
||||
.push(ns_b)
|
||||
.push(ns_c)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut serialized_list = vec![];
|
||||
safe_serialize(&list, &mut serialized_list, 1 << 24).unwrap();
|
||||
let list: CompressedSquashedNoiseCiphertextList =
|
||||
safe_deserialize(serialized_list.as_slice(), 1 << 24).unwrap();
|
||||
|
||||
let ns_a: SquashedNoiseFheInt = list.get(0).unwrap().unwrap();
|
||||
let ns_b: SquashedNoiseFheUint = list.get(1).unwrap().unwrap();
|
||||
let ns_c: SquashedNoiseFheBool = list.get(2).unwrap().unwrap();
|
||||
|
||||
let decrypted: i32 = ns_a.decrypt(&cks);
|
||||
assert_eq!(decrypted, clear_a);
|
||||
|
||||
let decrypted: u32 = ns_b.decrypt(&cks);
|
||||
assert_eq!(decrypted, clear_b);
|
||||
|
||||
let decrypted: bool = ns_c.decrypt(&cks);
|
||||
assert_eq!(decrypted, clear_c);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ use tfhe_versionable::Versionize;
|
||||
use crate::backward_compatibility::config::ConfigVersions;
|
||||
use crate::high_level_api::keys::IntegerConfig;
|
||||
use crate::shortint::parameters::list_compression::CompressionParameters;
|
||||
use crate::shortint::parameters::NoiseSquashingParameters;
|
||||
use crate::shortint::parameters::{NoiseSquashingCompressionParameters, NoiseSquashingParameters};
|
||||
|
||||
/// The config type
|
||||
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize, Versionize)]
|
||||
@@ -67,6 +67,20 @@ impl ConfigBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn enable_noise_squashing_compression(
|
||||
mut self,
|
||||
compression_parameters: NoiseSquashingCompressionParameters,
|
||||
) -> Self {
|
||||
assert_ne!(
|
||||
self.config.inner.noise_squashing_parameters, None,
|
||||
"Noise squashing must be enabled first"
|
||||
);
|
||||
self.config
|
||||
.inner
|
||||
.enable_noise_squashing_compression(compression_parameters);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_parameters<P>(block_parameters: P) -> Self
|
||||
where
|
||||
P: Into<crate::shortint::atomic_pattern::AtomicPatternParameters>,
|
||||
|
||||
@@ -17,8 +17,10 @@ pub(in crate::high_level_api) use compressed::CompressedSignedRadixCiphertext;
|
||||
pub(in crate::high_level_api) use inner::{
|
||||
SignedRadixCiphertext, SignedRadixCiphertextVersionOwned,
|
||||
};
|
||||
pub(in crate::high_level_api) use squashed_noise::InnerSquashedNoiseSignedRadixCiphertextVersionOwned;
|
||||
pub use squashed_noise::SquashedNoiseFheInt;
|
||||
pub(in crate::high_level_api) use squashed_noise::{
|
||||
InnerSquashedNoiseSignedRadixCiphertext, InnerSquashedNoiseSignedRadixCiphertextVersionOwned,
|
||||
};
|
||||
|
||||
expand_pub_use_fhe_type!(
|
||||
pub use static_{
|
||||
|
||||
@@ -7,8 +7,10 @@ use crate::high_level_api::errors::UninitializedNoiseSquashing;
|
||||
use crate::high_level_api::global_state::{self, with_internal_keys};
|
||||
use crate::high_level_api::keys::InternalServerKey;
|
||||
use crate::high_level_api::traits::{FheDecrypt, SquashNoise};
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use crate::integer::block_decomposition::{RecomposableFrom, SignExtendable};
|
||||
use crate::named::Named;
|
||||
use crate::prelude::Tagged;
|
||||
use crate::{ClientKey, Device, Tag};
|
||||
use serde::{Deserializer, Serializer};
|
||||
use tfhe_versionable::{Unversionize, UnversionizeError, Versionize, VersionizeOwned};
|
||||
@@ -129,7 +131,8 @@ impl InnerSquashedNoiseSignedRadixCiphertext {
|
||||
#[derive(Clone, serde::Deserialize, serde::Serialize, Versionize)]
|
||||
#[versionize(SquashedNoiseFheIntVersions)]
|
||||
pub struct SquashedNoiseFheInt {
|
||||
inner: InnerSquashedNoiseSignedRadixCiphertext,
|
||||
pub(in crate::high_level_api) inner: InnerSquashedNoiseSignedRadixCiphertext,
|
||||
pub(in crate::high_level_api) state: SquashedNoiseCiphertextState,
|
||||
tag: Tag,
|
||||
}
|
||||
|
||||
@@ -138,6 +141,14 @@ impl Named for SquashedNoiseFheInt {
|
||||
}
|
||||
|
||||
impl SquashedNoiseFheInt {
|
||||
pub(in crate::high_level_api) fn new(
|
||||
inner: InnerSquashedNoiseSignedRadixCiphertext,
|
||||
state: SquashedNoiseCiphertextState,
|
||||
tag: Tag,
|
||||
) -> Self {
|
||||
Self { inner, state, tag }
|
||||
}
|
||||
|
||||
pub fn underlying_squashed_noise_ciphertext(
|
||||
&self,
|
||||
) -> MaybeCloned<'_, crate::integer::ciphertext::SquashedNoiseSignedRadixCiphertext> {
|
||||
@@ -158,20 +169,24 @@ where
|
||||
Clear: RecomposableFrom<u128> + SignExtendable,
|
||||
{
|
||||
fn decrypt(&self, key: &ClientKey) -> Clear {
|
||||
key.key
|
||||
.noise_squashing_private_key
|
||||
.as_ref()
|
||||
.map(|noise_squashing_private_key| {
|
||||
noise_squashing_private_key.decrypt_signed_radix(&self.inner.on_cpu())
|
||||
})
|
||||
.expect(
|
||||
"No noise squashing private key in your ClientKey, cannot decrypt. \
|
||||
Did you call `enable_noise_squashing` when creating your Config?",
|
||||
)
|
||||
let noise_squashing_private_key = key.private_noise_squashing_decryption_key(self.state);
|
||||
|
||||
noise_squashing_private_key
|
||||
.decrypt_signed_radix(&self.inner.on_cpu())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Tagged for SquashedNoiseFheInt {
|
||||
fn tag(&self) -> &Tag {
|
||||
&self.tag
|
||||
}
|
||||
|
||||
fn tag_mut(&mut self) -> &mut Tag {
|
||||
&mut self.tag
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheIntId> SquashNoise for FheInt<Id> {
|
||||
type Output = SquashedNoiseFheInt;
|
||||
|
||||
@@ -191,6 +206,7 @@ impl<Id: FheIntId> SquashNoise for FheInt<Id> {
|
||||
&self.ciphertext.on_cpu(),
|
||||
)?,
|
||||
),
|
||||
state: SquashedNoiseCiphertextState::Normal,
|
||||
tag: server_key.tag.clone(),
|
||||
})
|
||||
}
|
||||
@@ -213,6 +229,7 @@ impl<Id: FheIntId> SquashNoise for FheInt<Id> {
|
||||
cuda_squashed_ct.to_squashed_noise_signed_radix_ciphertext(streams);
|
||||
Ok(SquashedNoiseFheInt {
|
||||
inner: InnerSquashedNoiseSignedRadixCiphertext::Cpu(cpu_squashed_ct),
|
||||
state: SquashedNoiseCiphertextState::Normal,
|
||||
tag: cuda_key.tag.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ pub use squashed_noise::SquashedNoiseFheUint;
|
||||
|
||||
pub(in crate::high_level_api) use compressed::CompressedRadixCiphertext;
|
||||
pub(in crate::high_level_api) use inner::{RadixCiphertext, RadixCiphertextVersionOwned};
|
||||
pub(in crate::high_level_api) use squashed_noise::InnerSquashedNoiseRadixCiphertextVersionOwned;
|
||||
pub(in crate::high_level_api) use squashed_noise::{
|
||||
InnerSquashedNoiseRadixCiphertext, InnerSquashedNoiseRadixCiphertextVersionOwned,
|
||||
};
|
||||
|
||||
mod base;
|
||||
mod compressed;
|
||||
|
||||
@@ -7,7 +7,8 @@ use crate::high_level_api::details::MaybeCloned;
|
||||
use crate::high_level_api::errors::UninitializedNoiseSquashing;
|
||||
use crate::high_level_api::global_state::{self, with_internal_keys};
|
||||
use crate::high_level_api::keys::InternalServerKey;
|
||||
use crate::high_level_api::traits::{FheDecrypt, SquashNoise};
|
||||
use crate::high_level_api::traits::{FheDecrypt, SquashNoise, Tagged};
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use crate::integer::block_decomposition::RecomposableFrom;
|
||||
use crate::named::Named;
|
||||
use crate::{ClientKey, Device, Tag};
|
||||
@@ -124,7 +125,8 @@ impl InnerSquashedNoiseRadixCiphertext {
|
||||
#[derive(Clone, serde::Deserialize, serde::Serialize, Versionize)]
|
||||
#[versionize(SquashedNoiseFheUintVersions)]
|
||||
pub struct SquashedNoiseFheUint {
|
||||
inner: InnerSquashedNoiseRadixCiphertext,
|
||||
pub(in crate::high_level_api) inner: InnerSquashedNoiseRadixCiphertext,
|
||||
pub(in crate::high_level_api) state: SquashedNoiseCiphertextState,
|
||||
tag: Tag,
|
||||
}
|
||||
|
||||
@@ -133,6 +135,14 @@ impl Named for SquashedNoiseFheUint {
|
||||
}
|
||||
|
||||
impl SquashedNoiseFheUint {
|
||||
pub(in crate::high_level_api) fn new(
|
||||
inner: InnerSquashedNoiseRadixCiphertext,
|
||||
state: SquashedNoiseCiphertextState,
|
||||
tag: Tag,
|
||||
) -> Self {
|
||||
Self { inner, state, tag }
|
||||
}
|
||||
|
||||
pub fn underlying_squashed_noise_ciphertext(
|
||||
&self,
|
||||
) -> MaybeCloned<'_, crate::integer::ciphertext::SquashedNoiseRadixCiphertext> {
|
||||
@@ -153,20 +163,23 @@ where
|
||||
Clear: RecomposableFrom<u128> + UnsignedNumeric,
|
||||
{
|
||||
fn decrypt(&self, key: &ClientKey) -> Clear {
|
||||
key.key
|
||||
.noise_squashing_private_key
|
||||
.as_ref()
|
||||
.map(|noise_squashing_private_key| {
|
||||
noise_squashing_private_key.decrypt_radix(&self.inner.on_cpu())
|
||||
})
|
||||
.expect(
|
||||
"No noise squashing private key in your ClientKey, cannot decrypt. \
|
||||
Did you call `enable_noise_squashing` when creating your Config?",
|
||||
)
|
||||
let noise_squashing_private_key = key.private_noise_squashing_decryption_key(self.state);
|
||||
noise_squashing_private_key
|
||||
.decrypt_radix(&self.inner.on_cpu())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Tagged for SquashedNoiseFheUint {
|
||||
fn tag(&self) -> &Tag {
|
||||
&self.tag
|
||||
}
|
||||
|
||||
fn tag_mut(&mut self) -> &mut Tag {
|
||||
&mut self.tag
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id: FheUintId> SquashNoise for FheUint<Id> {
|
||||
type Output = SquashedNoiseFheUint;
|
||||
|
||||
@@ -186,6 +199,7 @@ impl<Id: FheUintId> SquashNoise for FheUint<Id> {
|
||||
&self.ciphertext.on_cpu(),
|
||||
)?,
|
||||
),
|
||||
state: SquashedNoiseCiphertextState::Normal,
|
||||
tag: server_key.tag.clone(),
|
||||
})
|
||||
}
|
||||
@@ -207,6 +221,7 @@ impl<Id: FheUintId> SquashNoise for FheUint<Id> {
|
||||
let squashed_ct = cuda_squashed_ct.to_squashed_noise_radix_ciphertext(streams);
|
||||
Ok(SquashedNoiseFheUint {
|
||||
inner: InnerSquashedNoiseRadixCiphertext::Cpu(squashed_ct),
|
||||
state: SquashedNoiseCiphertextState::Normal,
|
||||
tag: cuda_key.tag.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ use super::{CompressedServerKey, ServerKey};
|
||||
use crate::high_level_api::backward_compatibility::keys::ClientKeyVersions;
|
||||
use crate::high_level_api::config::Config;
|
||||
use crate::high_level_api::keys::{CompactPrivateKey, IntegerClientKey};
|
||||
use crate::high_level_api::SquashedNoiseCiphertextState;
|
||||
use crate::integer::ciphertext::NoiseSquashingCompressionPrivateKey;
|
||||
use crate::integer::compression_keys::CompressionPrivateKeys;
|
||||
use crate::integer::noise_squashing::NoiseSquashingPrivateKey;
|
||||
use crate::integer::noise_squashing::{NoiseSquashingPrivateKey, NoiseSquashingPrivateKeyView};
|
||||
use crate::named::Named;
|
||||
use crate::prelude::Tagged;
|
||||
use crate::shortint::MessageModulus;
|
||||
@@ -82,10 +84,11 @@ impl ClientKey {
|
||||
Option<CompactPrivateKey>,
|
||||
Option<CompressionPrivateKeys>,
|
||||
Option<NoiseSquashingPrivateKey>,
|
||||
Option<NoiseSquashingCompressionPrivateKey>,
|
||||
Tag,
|
||||
) {
|
||||
let (cks, cpk, cppk, nsk) = self.key.into_raw_parts();
|
||||
(cks, cpk, cppk, nsk, self.tag)
|
||||
let (cks, cpk, cppk, nsk, nscpk) = self.key.into_raw_parts();
|
||||
(cks, cpk, cppk, nsk, nscpk, self.tag)
|
||||
}
|
||||
|
||||
pub fn from_raw_parts(
|
||||
@@ -96,6 +99,7 @@ impl ClientKey {
|
||||
)>,
|
||||
compression_key: Option<CompressionPrivateKeys>,
|
||||
noise_squashing_key: Option<NoiseSquashingPrivateKey>,
|
||||
noise_squashing_compression_key: Option<NoiseSquashingCompressionPrivateKey>,
|
||||
tag: Tag,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -104,6 +108,7 @@ impl ClientKey {
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
),
|
||||
tag,
|
||||
}
|
||||
@@ -125,6 +130,38 @@ impl ClientKey {
|
||||
pub(crate) fn message_modulus(&self) -> MessageModulus {
|
||||
self.key.block_parameters().message_modulus()
|
||||
}
|
||||
|
||||
/// Returns a view of the private key to be used to decrypt a squashed noise
|
||||
/// ciphertext depending on its state
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the key supposed to be used for the given state cannot be found
|
||||
pub(crate) fn private_noise_squashing_decryption_key(
|
||||
&self,
|
||||
state: SquashedNoiseCiphertextState,
|
||||
) -> NoiseSquashingPrivateKeyView<'_> {
|
||||
match state {
|
||||
SquashedNoiseCiphertextState::Normal => self
|
||||
.key
|
||||
.noise_squashing_private_key
|
||||
.as_ref()
|
||||
.map(|key| key.as_view())
|
||||
.expect(
|
||||
"No noise squashing private key in your ClientKey, cannot decrypt. \
|
||||
Did you call `enable_noise_squashing` when creating your Config?",
|
||||
),
|
||||
SquashedNoiseCiphertextState::PostDecompression => self
|
||||
.key
|
||||
.noise_squashing_compression_private_key
|
||||
.as_ref()
|
||||
.map(|key| key.private_key_view())
|
||||
.expect(
|
||||
"No noise squashing private key in your ClientKey, cannot decrypt. \
|
||||
Did you call `enable_noise_squashing_compression` when creating your Config?",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tagged for ClientKey {
|
||||
|
||||
@@ -2,6 +2,10 @@ use crate::conformance::ParameterSetConformant;
|
||||
use crate::core_crypto::commons::generators::DeterministicSeeder;
|
||||
use crate::core_crypto::prelude::{DefaultRandomGenerator, LweKeyswitchKeyConformanceParams};
|
||||
use crate::high_level_api::backward_compatibility::keys::*;
|
||||
use crate::integer::ciphertext::{
|
||||
CompressedNoiseSquashingCompressionKey, NoiseSquashingCompressionKey,
|
||||
NoiseSquashingCompressionPrivateKey,
|
||||
};
|
||||
use crate::integer::compression_keys::{
|
||||
CompressedCompressionKey, CompressedDecompressionKey, CompressionKey, CompressionPrivateKeys,
|
||||
DecompressionKey,
|
||||
@@ -15,7 +19,8 @@ use crate::shortint::atomic_pattern::AtomicPatternParameters;
|
||||
use crate::shortint::key_switching_key::KeySwitchingKeyConformanceParams;
|
||||
use crate::shortint::parameters::list_compression::CompressionParameters;
|
||||
use crate::shortint::parameters::{
|
||||
CompactPublicKeyEncryptionParameters, NoiseSquashingParameters, ShortintKeySwitchingParameters,
|
||||
CompactPublicKeyEncryptionParameters, NoiseSquashingCompressionParameters,
|
||||
NoiseSquashingParameters, ShortintKeySwitchingParameters,
|
||||
};
|
||||
use crate::shortint::{EncryptionKeyChoice, MessageModulus};
|
||||
use crate::{Config, Error};
|
||||
@@ -33,6 +38,7 @@ pub(crate) struct IntegerConfig {
|
||||
)>,
|
||||
pub(crate) compression_parameters: Option<CompressionParameters>,
|
||||
pub(crate) noise_squashing_parameters: Option<NoiseSquashingParameters>,
|
||||
pub(crate) noise_squashing_compression_parameters: Option<NoiseSquashingCompressionParameters>,
|
||||
}
|
||||
|
||||
impl IntegerConfig {
|
||||
@@ -44,6 +50,7 @@ impl IntegerConfig {
|
||||
dedicated_compact_public_key_parameters: None,
|
||||
compression_parameters: None,
|
||||
noise_squashing_parameters: None,
|
||||
noise_squashing_compression_parameters: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +65,17 @@ impl IntegerConfig {
|
||||
self.noise_squashing_parameters = Some(compression_parameters);
|
||||
}
|
||||
|
||||
pub(crate) fn enable_noise_squashing_compression(
|
||||
&mut self,
|
||||
compression_parameters: NoiseSquashingCompressionParameters,
|
||||
) {
|
||||
assert_ne!(
|
||||
self.noise_squashing_parameters, None,
|
||||
"Noise squashing must be enabled first"
|
||||
);
|
||||
self.noise_squashing_compression_parameters = Some(compression_parameters);
|
||||
}
|
||||
|
||||
pub(crate) fn public_key_encryption_parameters(
|
||||
&self,
|
||||
) -> Result<crate::shortint::parameters::CompactPublicKeyEncryptionParameters, crate::Error>
|
||||
@@ -84,6 +102,7 @@ impl Default for IntegerConfig {
|
||||
dedicated_compact_public_key_parameters: None,
|
||||
compression_parameters: None,
|
||||
noise_squashing_parameters: None,
|
||||
noise_squashing_compression_parameters: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,6 +119,7 @@ pub(crate) struct IntegerClientKey {
|
||||
pub(crate) dedicated_compact_private_key: Option<CompactPrivateKey>,
|
||||
pub(crate) compression_key: Option<CompressionPrivateKeys>,
|
||||
pub(crate) noise_squashing_private_key: Option<NoiseSquashingPrivateKey>,
|
||||
pub(crate) noise_squashing_compression_private_key: Option<NoiseSquashingCompressionPrivateKey>,
|
||||
}
|
||||
|
||||
impl IntegerClientKey {
|
||||
@@ -126,11 +146,16 @@ impl IntegerClientKey {
|
||||
.noise_squashing_parameters
|
||||
.map(NoiseSquashingPrivateKey::new);
|
||||
|
||||
let noise_squashing_compression_private_key = config
|
||||
.noise_squashing_compression_parameters
|
||||
.map(NoiseSquashingCompressionPrivateKey::new);
|
||||
|
||||
Self {
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_private_key,
|
||||
noise_squashing_compression_private_key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,18 +167,21 @@ impl IntegerClientKey {
|
||||
Option<CompactPrivateKey>,
|
||||
Option<CompressionPrivateKeys>,
|
||||
Option<NoiseSquashingPrivateKey>,
|
||||
Option<NoiseSquashingCompressionPrivateKey>,
|
||||
) {
|
||||
let Self {
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_private_key,
|
||||
noise_squashing_compression_private_key,
|
||||
} = self;
|
||||
(
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_private_key,
|
||||
noise_squashing_compression_private_key,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -167,6 +195,7 @@ impl IntegerClientKey {
|
||||
dedicated_compact_private_key: Option<CompactPrivateKey>,
|
||||
compression_key: Option<CompressionPrivateKeys>,
|
||||
noise_squashing_private_key: Option<NoiseSquashingPrivateKey>,
|
||||
noise_squashing_compression_private_key: Option<NoiseSquashingCompressionPrivateKey>,
|
||||
) -> Self {
|
||||
let shortint_cks: &crate::shortint::ClientKey = key.as_ref();
|
||||
|
||||
@@ -194,6 +223,7 @@ impl IntegerClientKey {
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_private_key,
|
||||
noise_squashing_compression_private_key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,11 +253,16 @@ impl From<IntegerConfig> for IntegerClientKey {
|
||||
.noise_squashing_parameters
|
||||
.map(NoiseSquashingPrivateKey::new);
|
||||
|
||||
let noise_squashing_compression_private_key = config
|
||||
.noise_squashing_compression_parameters
|
||||
.map(NoiseSquashingCompressionPrivateKey::new);
|
||||
|
||||
Self {
|
||||
key,
|
||||
dedicated_compact_private_key,
|
||||
compression_key,
|
||||
noise_squashing_private_key,
|
||||
noise_squashing_compression_private_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,6 +280,7 @@ pub struct IntegerServerKey {
|
||||
pub(crate) compression_key: Option<CompressionKey>,
|
||||
pub(crate) decompression_key: Option<DecompressionKey>,
|
||||
pub(crate) noise_squashing_key: Option<NoiseSquashingKey>,
|
||||
pub(crate) noise_squashing_compression_key: Option<NoiseSquashingCompressionKey>,
|
||||
}
|
||||
|
||||
impl IntegerServerKey {
|
||||
@@ -277,10 +313,22 @@ impl IntegerServerKey {
|
||||
build_helper.into()
|
||||
});
|
||||
|
||||
let noise_squashing_key = client_key
|
||||
.noise_squashing_private_key
|
||||
.as_ref()
|
||||
.map(|key| NoiseSquashingKey::new(cks, key));
|
||||
let (noise_squashing_key, noise_squashing_compression_key) =
|
||||
client_key.noise_squashing_private_key.as_ref().map_or_else(
|
||||
|| (None, None),
|
||||
|noise_squashing_private_key| {
|
||||
let noise_squashing_key =
|
||||
NoiseSquashingKey::new(cks, noise_squashing_private_key);
|
||||
let noise_squashing_compression_key = client_key
|
||||
.noise_squashing_compression_private_key
|
||||
.as_ref()
|
||||
.map(|comp_private_key| {
|
||||
noise_squashing_private_key
|
||||
.new_noise_squashing_compression_key(comp_private_key)
|
||||
});
|
||||
(Some(noise_squashing_key), noise_squashing_compression_key)
|
||||
},
|
||||
);
|
||||
|
||||
Self {
|
||||
key: base_integer_key,
|
||||
@@ -288,6 +336,7 @@ impl IntegerServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,6 +384,7 @@ pub struct IntegerCompressedServerKey {
|
||||
pub(crate) compression_key: Option<CompressedCompressionKey>,
|
||||
pub(crate) decompression_key: Option<CompressedDecompressionKey>,
|
||||
pub(crate) noise_squashing_key: Option<CompressedNoiseSquashingKey>,
|
||||
pub(crate) noise_squashing_compression_key: Option<CompressedNoiseSquashingCompressionKey>,
|
||||
}
|
||||
|
||||
impl IntegerCompressedServerKey {
|
||||
@@ -370,13 +420,22 @@ impl IntegerCompressedServerKey {
|
||||
(Some(compression_keys), Some(decompression_keys))
|
||||
});
|
||||
|
||||
let noise_squashing_key =
|
||||
client_key
|
||||
.noise_squashing_private_key
|
||||
.as_ref()
|
||||
.map(|noise_squashing_private_key| {
|
||||
noise_squashing_private_key.new_compressed_noise_squashing_key(&client_key.key)
|
||||
});
|
||||
let (noise_squashing_key, noise_squashing_compression_key) = client_key
|
||||
.noise_squashing_private_key
|
||||
.as_ref()
|
||||
.map_or((None, None), |noise_squashing_private_key| {
|
||||
let noise_squashing_key =
|
||||
noise_squashing_private_key.new_compressed_noise_squashing_key(&client_key.key);
|
||||
|
||||
let noise_squashing_compression_key = client_key
|
||||
.noise_squashing_compression_private_key
|
||||
.as_ref()
|
||||
.map(|comp_private_key| {
|
||||
noise_squashing_private_key
|
||||
.new_compressed_noise_squashing_compression_key(comp_private_key)
|
||||
});
|
||||
(Some(noise_squashing_key), noise_squashing_compression_key)
|
||||
});
|
||||
|
||||
Self {
|
||||
key,
|
||||
@@ -384,6 +443,7 @@ impl IntegerCompressedServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,6 +471,7 @@ impl IntegerCompressedServerKey {
|
||||
compression_key: Option<CompressedCompressionKey>,
|
||||
decompression_key: Option<CompressedDecompressionKey>,
|
||||
noise_squashing_key: Option<CompressedNoiseSquashingKey>,
|
||||
noise_squashing_compression_key: Option<CompressedNoiseSquashingCompressionKey>,
|
||||
) -> Self {
|
||||
Self {
|
||||
key,
|
||||
@@ -418,6 +479,7 @@ impl IntegerCompressedServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,6 +499,11 @@ impl IntegerCompressedServerKey {
|
||||
.as_ref()
|
||||
.map(CompressedNoiseSquashingKey::decompress);
|
||||
|
||||
let noise_squashing_compression_key = self
|
||||
.noise_squashing_compression_key
|
||||
.as_ref()
|
||||
.map(CompressedNoiseSquashingCompressionKey::decompress);
|
||||
|
||||
IntegerServerKey {
|
||||
key: self.key.decompress(),
|
||||
cpk_key_switching_key_material: self.cpk_key_switching_key_material.as_ref().map(
|
||||
@@ -445,6 +512,7 @@ impl IntegerCompressedServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -533,6 +601,7 @@ pub struct IntegerServerKeyConformanceParams {
|
||||
)>,
|
||||
pub compression_param: Option<CompressionParameters>,
|
||||
pub noise_squashing_param: Option<NoiseSquashingParameters>,
|
||||
pub noise_squashing_compression_param: Option<NoiseSquashingCompressionParameters>,
|
||||
}
|
||||
|
||||
impl<C: Into<Config>> From<C> for IntegerServerKeyConformanceParams {
|
||||
@@ -543,6 +612,7 @@ impl<C: Into<Config>> From<C> for IntegerServerKeyConformanceParams {
|
||||
cpk_param: config.inner.dedicated_compact_public_key_parameters,
|
||||
compression_param: config.inner.compression_parameters,
|
||||
noise_squashing_param: config.inner.noise_squashing_parameters,
|
||||
noise_squashing_compression_param: config.inner.noise_squashing_compression_parameters,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -602,6 +672,7 @@ impl ParameterSetConformant for IntegerServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
} = self;
|
||||
|
||||
let cpk_key_switching_key_material_is_ok = match (
|
||||
@@ -652,10 +723,32 @@ impl ParameterSetConformant for IntegerServerKey {
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let noise_squashing_compression_key_is_ok = match (
|
||||
parameter_set.noise_squashing_param.as_ref(),
|
||||
parameter_set.noise_squashing_compression_param.as_ref(),
|
||||
noise_squashing_compression_key.as_ref(),
|
||||
) {
|
||||
(None, None, None) | (Some(_), None, None) => true,
|
||||
(
|
||||
Some(noise_squashing_parameters),
|
||||
Some(noise_squashing_compression_param),
|
||||
Some(noise_squashing_compression_key),
|
||||
) => {
|
||||
let noise_squashing_compression_param = (
|
||||
*noise_squashing_parameters,
|
||||
*noise_squashing_compression_param,
|
||||
)
|
||||
.into();
|
||||
noise_squashing_compression_key.is_conformant(&noise_squashing_compression_param)
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
key.is_conformant(¶meter_set.sk_param)
|
||||
&& cpk_key_switching_key_material_is_ok
|
||||
&& compression_is_ok
|
||||
&& noise_squashing_key_is_ok
|
||||
&& noise_squashing_compression_key_is_ok
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,6 +762,7 @@ impl ParameterSetConformant for IntegerCompressedServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
} = self;
|
||||
|
||||
let cpk_key_switching_key_material_is_ok = match (
|
||||
@@ -719,10 +813,32 @@ impl ParameterSetConformant for IntegerCompressedServerKey {
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let noise_squashing_compression_key_is_ok = match (
|
||||
parameter_set.noise_squashing_param.as_ref(),
|
||||
parameter_set.noise_squashing_compression_param.as_ref(),
|
||||
noise_squashing_compression_key.as_ref(),
|
||||
) {
|
||||
(None, None, None) | (Some(_), None, None) => true,
|
||||
(
|
||||
Some(noise_squashing_parameters),
|
||||
Some(noise_squashing_compression_param),
|
||||
Some(noise_squashing_compression_key),
|
||||
) => {
|
||||
let noise_squashing_compression_param = (
|
||||
*noise_squashing_parameters,
|
||||
*noise_squashing_compression_param,
|
||||
)
|
||||
.into();
|
||||
noise_squashing_compression_key.is_conformant(&noise_squashing_compression_param)
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
key.is_conformant(¶meter_set.sk_param)
|
||||
&& cpk_key_switching_key_material_is_ok
|
||||
&& compression_is_ok
|
||||
&& noise_squashing_key_is_ok
|
||||
&& noise_squashing_compression_key_is_ok
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
#[cfg(feature = "hpu")]
|
||||
pub(in crate::high_level_api) use hpu::HpuTaggedDevice;
|
||||
#[cfg(feature = "hpu")]
|
||||
use tfhe_hpu_backend::prelude::HpuDevice;
|
||||
use tfhe_versionable::Versionize;
|
||||
|
||||
use super::ClientKey;
|
||||
use crate::backward_compatibility::keys::{CompressedServerKeyVersions, ServerKeyVersions};
|
||||
use crate::conformance::ParameterSetConformant;
|
||||
@@ -14,6 +8,9 @@ use crate::core_crypto::gpu::{synchronize_devices, CudaStreams};
|
||||
#[cfg(feature = "gpu")]
|
||||
use crate::high_level_api::keys::inner::IntegerCudaServerKey;
|
||||
use crate::high_level_api::keys::{IntegerCompressedServerKey, IntegerServerKey};
|
||||
use crate::integer::ciphertext::{
|
||||
CompressedNoiseSquashingCompressionKey, NoiseSquashingCompressionKey,
|
||||
};
|
||||
use crate::integer::compression_keys::{
|
||||
CompressedCompressionKey, CompressedDecompressionKey, CompressionKey, DecompressionKey,
|
||||
};
|
||||
@@ -25,7 +22,12 @@ use crate::shortint::MessageModulus;
|
||||
#[cfg(feature = "gpu")]
|
||||
use crate::GpuIndex;
|
||||
use crate::{Device, Tag};
|
||||
#[cfg(feature = "hpu")]
|
||||
pub(in crate::high_level_api) use hpu::HpuTaggedDevice;
|
||||
use std::sync::Arc;
|
||||
#[cfg(feature = "hpu")]
|
||||
use tfhe_hpu_backend::prelude::HpuDevice;
|
||||
use tfhe_versionable::Versionize;
|
||||
|
||||
/// Key of the server
|
||||
///
|
||||
@@ -53,6 +55,7 @@ impl ServerKey {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn into_raw_parts(
|
||||
self,
|
||||
) -> (
|
||||
@@ -61,6 +64,7 @@ impl ServerKey {
|
||||
Option<CompressionKey>,
|
||||
Option<DecompressionKey>,
|
||||
Option<NoiseSquashingKey>,
|
||||
Option<NoiseSquashingCompressionKey>,
|
||||
Tag,
|
||||
) {
|
||||
let IntegerServerKey {
|
||||
@@ -69,6 +73,7 @@ impl ServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
} = (*self.key).clone();
|
||||
|
||||
(
|
||||
@@ -77,6 +82,7 @@ impl ServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
self.tag,
|
||||
)
|
||||
}
|
||||
@@ -89,6 +95,7 @@ impl ServerKey {
|
||||
compression_key: Option<CompressionKey>,
|
||||
decompression_key: Option<DecompressionKey>,
|
||||
noise_squashing_key: Option<NoiseSquashingKey>,
|
||||
noise_squashing_compression_key: Option<NoiseSquashingCompressionKey>,
|
||||
tag: Tag,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -98,6 +105,7 @@ impl ServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
}),
|
||||
tag,
|
||||
}
|
||||
@@ -258,6 +266,7 @@ impl CompressedServerKey {
|
||||
compression_key: Option<CompressedCompressionKey>,
|
||||
decompression_key: Option<CompressedDecompressionKey>,
|
||||
noise_squashing_key: Option<CompressedNoiseSquashingKey>,
|
||||
noise_squashing_compression_key: Option<CompressedNoiseSquashingCompressionKey>,
|
||||
tag: Tag,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -267,6 +276,7 @@ impl CompressedServerKey {
|
||||
compression_key,
|
||||
decompression_key,
|
||||
noise_squashing_key,
|
||||
noise_squashing_compression_key,
|
||||
),
|
||||
tag,
|
||||
}
|
||||
@@ -546,6 +556,7 @@ mod test {
|
||||
use crate::prelude::ParameterSetConformant;
|
||||
use crate::shortint::parameters::{
|
||||
COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
@@ -631,10 +642,14 @@ mod test {
|
||||
let noise_squashing_params =
|
||||
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let noise_squashing_compression_params =
|
||||
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let config = ConfigBuilder::with_custom_parameters(params)
|
||||
.use_dedicated_compact_public_key_parameters((cpk_params, casting_params))
|
||||
.enable_compression(comp_params)
|
||||
.enable_noise_squashing(noise_squashing_params)
|
||||
.enable_noise_squashing_compression(noise_squashing_compression_params)
|
||||
.build();
|
||||
|
||||
let ck = ClientKey::generate(config);
|
||||
@@ -676,6 +691,7 @@ mod test {
|
||||
cpk_param: None,
|
||||
compression_param: None,
|
||||
noise_squashing_param: None,
|
||||
noise_squashing_compression_param: None,
|
||||
};
|
||||
|
||||
assert!(!sk.is_conformant(&conformance_params));
|
||||
@@ -704,6 +720,7 @@ mod test {
|
||||
cpk_param: Some((cpk_params, casting_params)),
|
||||
compression_param: None,
|
||||
noise_squashing_param: None,
|
||||
noise_squashing_compression_param: None,
|
||||
};
|
||||
|
||||
assert!(!sk.is_conformant(&conformance_params));
|
||||
@@ -786,10 +803,14 @@ mod test {
|
||||
let noise_squashing_params =
|
||||
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let noise_squashing_compression_params =
|
||||
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let config = ConfigBuilder::with_custom_parameters(params)
|
||||
.use_dedicated_compact_public_key_parameters((cpk_params, casting_params))
|
||||
.enable_compression(comp_params)
|
||||
.enable_noise_squashing(noise_squashing_params)
|
||||
.enable_noise_squashing_compression(noise_squashing_compression_params)
|
||||
.build();
|
||||
|
||||
let ck = ClientKey::generate(config);
|
||||
@@ -831,6 +852,7 @@ mod test {
|
||||
cpk_param: None,
|
||||
compression_param: None,
|
||||
noise_squashing_param: None,
|
||||
noise_squashing_compression_param: None,
|
||||
};
|
||||
|
||||
assert!(!sk.is_conformant(&conformance_params));
|
||||
@@ -859,6 +881,7 @@ mod test {
|
||||
cpk_param: Some((cpk_params, casting_params)),
|
||||
compression_param: None,
|
||||
noise_squashing_param: None,
|
||||
noise_squashing_compression_param: None,
|
||||
};
|
||||
|
||||
assert!(!sk.is_conformant(&conformance_params));
|
||||
|
||||
@@ -48,7 +48,8 @@ macro_rules! export_concrete_array_types {
|
||||
|
||||
pub use crate::core_crypto::commons::math::random::Seed;
|
||||
pub use crate::integer::server_key::MatchValues;
|
||||
use crate::{error, Error};
|
||||
use crate::{error, Error, Versionize};
|
||||
use backward_compatibility::compressed_ciphertext_list::SquashedNoiseCiphertextStateVersions;
|
||||
pub use config::{Config, ConfigBuilder};
|
||||
#[cfg(feature = "gpu")]
|
||||
pub use global_state::CudaGpuChoice;
|
||||
@@ -124,6 +125,10 @@ pub use compact_list::{
|
||||
pub use compressed_ciphertext_list::{
|
||||
CompressedCiphertextList, CompressedCiphertextListBuilder, HlCompressible, HlExpandable,
|
||||
};
|
||||
pub use compressed_noise_squashed_ciphertext_list::{
|
||||
CompressedSquashedNoiseCiphertextList, CompressedSquashedNoiseCiphertextListBuilder,
|
||||
HlSquashedNoiseCompressible, HlSquashedNoiseExpandable,
|
||||
};
|
||||
#[cfg(feature = "strings")]
|
||||
pub use strings::ascii::{EncryptableString, FheAsciiString, FheStringIsEmpty, FheStringLen};
|
||||
pub use tag::Tag;
|
||||
@@ -152,6 +157,7 @@ mod tag;
|
||||
#[cfg(feature = "gpu")]
|
||||
pub use crate::core_crypto::gpu::vec::GpuIndex;
|
||||
|
||||
mod compressed_noise_squashed_ciphertext_list;
|
||||
pub(in crate::high_level_api) mod details;
|
||||
/// The tfhe prelude.
|
||||
pub mod prelude;
|
||||
@@ -271,3 +277,10 @@ impl TryFrom<i32> for FheTypes {
|
||||
Self::from_repr(value).ok_or_else(|| error!("Invalid value for FheTypes: {}", value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Copy, Clone, Versionize)]
|
||||
#[versionize(SquashedNoiseCiphertextStateVersions)]
|
||||
pub(crate) enum SquashedNoiseCiphertextState {
|
||||
Normal,
|
||||
PostDecompression,
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ fn test_try_from_single_lwe_encryption_key() {
|
||||
let shortint_key =
|
||||
crate::shortint::ClientKey::try_from_lwe_encryption_key(lwe_sk, parameters).unwrap();
|
||||
let client_key =
|
||||
ClientKey::from_raw_parts(shortint_key.into(), None, None, None, Tag::default());
|
||||
ClientKey::from_raw_parts(shortint_key.into(), None, None, None, None, Tag::default());
|
||||
let sks = ServerKey::new(&client_key);
|
||||
|
||||
let clear_a = 1344u32;
|
||||
|
||||
@@ -828,8 +828,8 @@ mod tests {
|
||||
// We need the private compression key to be common between GPU and CPU
|
||||
// for the rest of the test to work. This is the only way to do it
|
||||
// until a more convenient API is added
|
||||
let (cks, pk, _, cnsk, tag) = ck.into_raw_parts();
|
||||
let ck = ClientKey::from_raw_parts(cks, pk, common_cck, cnsk, tag);
|
||||
let (cks, pk, _, nsk, cnsk, tag) = ck.into_raw_parts();
|
||||
let ck = ClientKey::from_raw_parts(cks, pk, common_cck, nsk, cnsk, tag);
|
||||
|
||||
let sk = CompressedServerKey::new(&ck);
|
||||
assert_eq!(sk.tag().as_u64(), 0);
|
||||
|
||||
@@ -2,6 +2,7 @@ use super::{
|
||||
DataKind, SquashedNoiseBooleanBlock, SquashedNoiseRadixCiphertext,
|
||||
SquashedNoiseSignedRadixCiphertext,
|
||||
};
|
||||
use crate::conformance::ParameterSetConformant;
|
||||
use crate::core_crypto::commons::math::random::{Deserialize, Serialize};
|
||||
use crate::integer::backward_compatibility::list_compression::{
|
||||
CompressedNoiseSquashingCompressionKeyVersions, CompressedSquashedNoiseCiphertextListVersions,
|
||||
@@ -16,6 +17,7 @@ use crate::shortint::ciphertext::{
|
||||
use crate::shortint::list_compression::{
|
||||
CompressedNoiseSquashingCompressionKey as ShortintCompressedNoiseSquashingCompressionKey,
|
||||
NoiseSquashingCompressionKey as ShortintNoiseSquashingCompressionKey,
|
||||
NoiseSquashingCompressionKeyConformanceParams,
|
||||
NoiseSquashingCompressionPrivateKey as ShortintNoiseSquashingCompressionPrivateKey,
|
||||
};
|
||||
use crate::shortint::parameters::NoiseSquashingCompressionParameters;
|
||||
@@ -53,6 +55,15 @@ pub struct CompressedNoiseSquashingCompressionKey {
|
||||
pub(crate) key: ShortintCompressedNoiseSquashingCompressionKey,
|
||||
}
|
||||
|
||||
impl ParameterSetConformant for CompressedNoiseSquashingCompressionKey {
|
||||
type ParameterSet = NoiseSquashingCompressionKeyConformanceParams;
|
||||
|
||||
fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool {
|
||||
let Self { key } = self;
|
||||
key.is_conformant(parameter_set)
|
||||
}
|
||||
}
|
||||
|
||||
impl CompressedNoiseSquashingCompressionKey {
|
||||
pub fn decompress(&self) -> NoiseSquashingCompressionKey {
|
||||
let key = self.key.decompress();
|
||||
@@ -74,6 +85,15 @@ impl Named for NoiseSquashingCompressionKey {
|
||||
const NAME: &'static str = "integer::NoiseSquashingCompressionKey";
|
||||
}
|
||||
|
||||
impl ParameterSetConformant for NoiseSquashingCompressionKey {
|
||||
type ParameterSet = NoiseSquashingCompressionKeyConformanceParams;
|
||||
|
||||
fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool {
|
||||
let Self { key } = self;
|
||||
key.is_conformant(parameter_set)
|
||||
}
|
||||
}
|
||||
|
||||
impl NoiseSquashingPrivateKey {
|
||||
pub fn new_noise_squashing_compression_key(
|
||||
&self,
|
||||
@@ -102,8 +122,8 @@ impl NoiseSquashingPrivateKey {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Versionize)]
|
||||
#[versionize(CompressedSquashedNoiseCiphertextListVersions)]
|
||||
pub struct CompressedSquashedNoiseCiphertextList {
|
||||
list: ShortintCompressedSquashedNoiseCiphertextList,
|
||||
info: Vec<DataKind>,
|
||||
pub(crate) list: ShortintCompressedSquashedNoiseCiphertextList,
|
||||
pub(crate) info: Vec<DataKind>,
|
||||
}
|
||||
|
||||
impl Named for CompressedSquashedNoiseCiphertextList {
|
||||
@@ -175,6 +195,10 @@ mod sealed {
|
||||
impl Sealed for SquashedNoiseRadixCiphertext {}
|
||||
impl Sealed for SquashedNoiseSignedRadixCiphertext {}
|
||||
impl Sealed for SquashedNoiseBooleanBlock {}
|
||||
|
||||
impl Sealed for crate::SquashedNoiseFheBool {}
|
||||
impl Sealed for crate::SquashedNoiseFheUint {}
|
||||
impl Sealed for crate::SquashedNoiseFheInt {}
|
||||
}
|
||||
|
||||
pub trait SquashedNoiseCompressible: sealed::Sealed {
|
||||
|
||||
@@ -9,5 +9,6 @@ pub use compressed_server_keys::{
|
||||
};
|
||||
pub use private_key::{CompressionPrivateKeys, NoiseSquashingCompressionPrivateKey};
|
||||
pub use server_keys::{
|
||||
CompressionKey, CompressionKeyConformanceParams, DecompressionKey, NoiseSquashingCompressionKey,
|
||||
CompressionKey, CompressionKeyConformanceParams, DecompressionKey,
|
||||
NoiseSquashingCompressionKey, NoiseSquashingCompressionKeyConformanceParams,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user