mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-08 22:28:01 -05:00
chore: impl Versionize for MetaParameters
This commit is contained in:
committed by
tmontaigu
parent
11579bd3d0
commit
be1de6ef2b
@@ -8,9 +8,10 @@ use crate::core_crypto::commons::parameters::{
|
|||||||
DecompositionBaseLog, DecompositionLevelCount, DynamicDistribution, GlweDimension,
|
DecompositionBaseLog, DecompositionLevelCount, DynamicDistribution, GlweDimension,
|
||||||
LweDimension, PolynomialSize,
|
LweDimension, PolynomialSize,
|
||||||
};
|
};
|
||||||
|
use crate::shortint::parameters::meta::{DedicatedCompactPublicKeyParameters, MetaParameters};
|
||||||
use crate::shortint::parameters::{
|
use crate::shortint::parameters::{
|
||||||
CiphertextModulus32, ModulusSwitchNoiseReductionParams, ModulusSwitchType,
|
Backend, CiphertextModulus32, MetaNoiseSquashingParameters, ModulusSwitchNoiseReductionParams,
|
||||||
ShortintParameterSetInner, SupportedCompactPkeZkScheme,
|
ModulusSwitchType, ShortintParameterSetInner, SupportedCompactPkeZkScheme,
|
||||||
};
|
};
|
||||||
use crate::shortint::*;
|
use crate::shortint::*;
|
||||||
use parameters::KeySwitch32PBSParameters;
|
use parameters::KeySwitch32PBSParameters;
|
||||||
@@ -27,6 +28,11 @@ pub enum CarryModulusVersions {
|
|||||||
V0(CarryModulus),
|
V0(CarryModulus),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(VersionsDispatch)]
|
||||||
|
pub enum BackendVersions {
|
||||||
|
V0(Backend),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Version)]
|
#[derive(Version)]
|
||||||
pub struct ClassicPBSParametersV0 {
|
pub struct ClassicPBSParametersV0 {
|
||||||
pub lwe_dimension: LweDimension,
|
pub lwe_dimension: LweDimension,
|
||||||
@@ -261,3 +267,18 @@ pub enum KeySwitch32PBSParametersVersions {
|
|||||||
pub enum ModulusSwitchTypeVersions {
|
pub enum ModulusSwitchTypeVersions {
|
||||||
V0(ModulusSwitchType),
|
V0(ModulusSwitchType),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(VersionsDispatch)]
|
||||||
|
pub enum MetaNoiseSquashingParametersVersions {
|
||||||
|
V0(MetaNoiseSquashingParameters),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(VersionsDispatch)]
|
||||||
|
pub enum DedicatedCompactPublicKeyParametersVersions {
|
||||||
|
V0(DedicatedCompactPublicKeyParameters),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(VersionsDispatch)]
|
||||||
|
pub enum MetaParametersVersions {
|
||||||
|
V0(MetaParameters),
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tfhe_versionable::Versionize;
|
||||||
|
|
||||||
|
use crate::conformance::EnumSet;
|
||||||
|
use crate::core_crypto::prelude::{CastInto, UnsignedInteger};
|
||||||
|
use crate::named::Named;
|
||||||
|
use crate::shortint::backward_compatibility::parameters::{
|
||||||
|
DedicatedCompactPublicKeyParametersVersions, MetaParametersVersions,
|
||||||
|
};
|
||||||
use crate::shortint::parameters::{
|
use crate::shortint::parameters::{
|
||||||
Backend, CompactPublicKeyEncryptionParameters, CompressionParameters,
|
Backend, CompactPublicKeyEncryptionParameters, CompressionParameters,
|
||||||
MetaNoiseSquashingParameters, ShortintKeySwitchingParameters,
|
MetaNoiseSquashingParameters, ShortintKeySwitchingParameters,
|
||||||
};
|
};
|
||||||
use crate::shortint::AtomicPatternParameters;
|
use crate::shortint::AtomicPatternParameters;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Versionize)]
|
||||||
|
#[versionize(DedicatedCompactPublicKeyParametersVersions)]
|
||||||
pub struct DedicatedCompactPublicKeyParameters {
|
pub struct DedicatedCompactPublicKeyParameters {
|
||||||
/// Parameters used by the dedicated compact public key
|
/// Parameters used by the dedicated compact public key
|
||||||
pub pke_params: CompactPublicKeyEncryptionParameters,
|
pub pke_params: CompactPublicKeyEncryptionParameters,
|
||||||
@@ -16,7 +28,8 @@ pub struct DedicatedCompactPublicKeyParameters {
|
|||||||
pub re_randomization_parameters: Option<ShortintKeySwitchingParameters>,
|
pub re_randomization_parameters: Option<ShortintKeySwitchingParameters>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Versionize)]
|
||||||
|
#[versionize(MetaParametersVersions)]
|
||||||
pub struct MetaParameters {
|
pub struct MetaParameters {
|
||||||
pub backend: Backend,
|
pub backend: Backend,
|
||||||
/// The parameters used by ciphertext when doing computations
|
/// The parameters used by ciphertext when doing computations
|
||||||
@@ -29,3 +42,879 @@ pub struct MetaParameters {
|
|||||||
/// Parameters for noise squashing
|
/// Parameters for noise squashing
|
||||||
pub noise_squashing_parameters: Option<MetaNoiseSquashingParameters>,
|
pub noise_squashing_parameters: Option<MetaNoiseSquashingParameters>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Named for MetaParameters {
|
||||||
|
const NAME: &str = "shortint::MetaParameters";
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MetaParameters {
|
||||||
|
pub fn noise_distribution_kind(&self) -> NoiseDistributionKind {
|
||||||
|
match self.compute_parameters {
|
||||||
|
AtomicPatternParameters::Standard(pbsparameters) => match pbsparameters {
|
||||||
|
PBSParameters::PBS(pbs) => pbs.lwe_noise_distribution.kind(),
|
||||||
|
PBSParameters::MultiBitPBS(multi_bit_pbs) => {
|
||||||
|
multi_bit_pbs.lwe_noise_distribution.kind()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AtomicPatternParameters::KeySwitch32(key_switch32_pbsparameters) => {
|
||||||
|
key_switch32_pbsparameters.lwe_noise_distribution.kind()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn failure_probability(&self) -> Log2PFail {
|
||||||
|
Log2PFail(self.compute_parameters.log2_p_fail())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents the type of noise distribution used in cryptographic operations.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum NoiseDistributionKind {
|
||||||
|
Gaussian = 0,
|
||||||
|
TUniform = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CastInto<usize> for NoiseDistributionKind {
|
||||||
|
fn cast_into(self) -> usize {
|
||||||
|
self as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Struct to express the allowed noise distribution kinds for parameter selection.
|
||||||
|
///
|
||||||
|
/// This struct is used to specify which [`NoiseDistributionKind`]s are acceptable
|
||||||
|
/// when searching for compatible cryptographic parameters.
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct NoiseDistributionChoice(EnumSet<NoiseDistributionKind>);
|
||||||
|
|
||||||
|
impl NoiseDistributionChoice {
|
||||||
|
/// Creates a new empty choice, i.e. no distributions are allowed.
|
||||||
|
///
|
||||||
|
/// Starting point for building a custom choice by then [Self::allow] noise distributions.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(EnumSet::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates new choice that allows all noise distributions.
|
||||||
|
pub fn allow_all() -> Self {
|
||||||
|
Self::new()
|
||||||
|
.allow(NoiseDistributionKind::Gaussian)
|
||||||
|
.allow(NoiseDistributionKind::TUniform)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a noise distribution kind to the choice.
|
||||||
|
///
|
||||||
|
/// `kind` will be allowed
|
||||||
|
pub fn allow(mut self, kind: NoiseDistributionKind) -> Self {
|
||||||
|
self.0.insert(kind);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes a noise distribution kind from the choice.
|
||||||
|
///
|
||||||
|
/// `kind` won't be allowed
|
||||||
|
pub fn deny(mut self, kind: NoiseDistributionKind) -> Self {
|
||||||
|
self.0.remove(kind);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_compatible(&self, params: &MetaParameters) -> bool {
|
||||||
|
self.0.contains(params.noise_distribution_kind())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NoiseDistributionChoice {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: UnsignedInteger> super::DynamicDistribution<T> {
|
||||||
|
fn kind(&self) -> NoiseDistributionKind {
|
||||||
|
match self {
|
||||||
|
Self::Gaussian(_) => NoiseDistributionKind::Gaussian,
|
||||||
|
Self::TUniform(_) => NoiseDistributionKind::TUniform,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a constraint on a value
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Constraint<T> {
|
||||||
|
/// The value must be less than (<) the specified constraint
|
||||||
|
LessThan(T),
|
||||||
|
/// The value must be less than or equal (<=) tothe specified constraint
|
||||||
|
LessThanOrEqual(T),
|
||||||
|
/// The value must be greater than (>) the specified constraint
|
||||||
|
GreaterThan(T),
|
||||||
|
/// The value must be greater than or equal (>=) tothe specified constraint
|
||||||
|
GreaterThanOrEqual(T),
|
||||||
|
/// The value must be equal to the specified constraint
|
||||||
|
Equal(T),
|
||||||
|
/// The value must be within the given range (min..=max)
|
||||||
|
Within(RangeInclusive<T>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Constraint<T>
|
||||||
|
where
|
||||||
|
T: PartialOrd + PartialEq,
|
||||||
|
{
|
||||||
|
fn is_compatible(&self, value: &T) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::LessThan(v) => value < v,
|
||||||
|
Self::LessThanOrEqual(v) => value <= v,
|
||||||
|
Self::GreaterThan(v) => value > v,
|
||||||
|
Self::GreaterThanOrEqual(v) => value >= v,
|
||||||
|
Self::Equal(v) => value == v,
|
||||||
|
Self::Within(range) => range.contains(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents the failure probability in logarithmic scale.
|
||||||
|
///
|
||||||
|
/// Log2PFail(-x) = failure probability of 2^-128
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
|
pub struct Log2PFail(pub f64);
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Version(pub u8, pub u8);
|
||||||
|
|
||||||
|
impl Version {
|
||||||
|
pub fn major(self) -> u8 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
pub fn minor(self) -> u8 {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current() -> Self {
|
||||||
|
let major = env!("CARGO_PKG_VERSION_MAJOR")
|
||||||
|
.parse::<u8>()
|
||||||
|
.expect("Failed to parse major version");
|
||||||
|
let minor = env!("CARGO_PKG_VERSION_MINOR")
|
||||||
|
.parse::<u8>()
|
||||||
|
.expect("Failed to parse minor version");
|
||||||
|
Self(major, minor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Version {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Version {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
let major_cmp = self.major().cmp(&other.major());
|
||||||
|
|
||||||
|
if major_cmp != std::cmp::Ordering::Equal {
|
||||||
|
return major_cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.minor().cmp(&other.minor())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allows specification of constraints for the multi-bit PBS
|
||||||
|
pub struct MultiBitPBSChoice {
|
||||||
|
pub(crate) grouping_factor: Constraint<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MultiBitPBSChoice {
|
||||||
|
/// Creates a new choice with the given `grouping_factor`
|
||||||
|
pub fn new(grouping_factor: Constraint<usize>) -> Self {
|
||||||
|
Self { grouping_factor }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_compatible(&self, params: &MultiBitPBSParameters) -> bool {
|
||||||
|
self.grouping_factor
|
||||||
|
.is_compatible(¶ms.grouping_factor.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Choices for the AtomicPattern
|
||||||
|
///
|
||||||
|
/// 3 Atomic Patterns are available
|
||||||
|
///
|
||||||
|
/// * Classic PBS
|
||||||
|
/// * Multi-Bit PBS
|
||||||
|
/// * Keyswitch 32-bit
|
||||||
|
pub struct AtomicPatternChoice {
|
||||||
|
classical: bool,
|
||||||
|
multibit: Option<MultiBitPBSChoice>,
|
||||||
|
keyswitch32: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AtomicPatternChoice {
|
||||||
|
/// Creates a choice which will not allow any atomic pattern
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
classical: false,
|
||||||
|
multibit: None,
|
||||||
|
keyswitch32: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the possible choice for classic PBS
|
||||||
|
pub fn classic_pbs(mut self, allowed: bool) -> Self {
|
||||||
|
self.classical = allowed;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the possible choice for multi-bit PBS
|
||||||
|
pub fn multi_bit_pbs(mut self, constraints: Option<MultiBitPBSChoice>) -> Self {
|
||||||
|
self.multibit = constraints;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the choice for Keyswitch32
|
||||||
|
pub fn keyswitch32(mut self, allowed: bool) -> Self {
|
||||||
|
self.keyswitch32 = allowed;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_compatible(&self, ap: &AtomicPatternParameters) -> bool {
|
||||||
|
match ap {
|
||||||
|
AtomicPatternParameters::Standard(pbs_params) => match pbs_params {
|
||||||
|
PBSParameters::PBS(_) => self.classical,
|
||||||
|
PBSParameters::MultiBitPBS(multi_bit_params) => self
|
||||||
|
.multibit
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|constraints| constraints.is_compatible(multi_bit_params)),
|
||||||
|
},
|
||||||
|
AtomicPatternParameters::KeySwitch32(_) => self.keyswitch32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_for_device(device: Backend) -> Self {
|
||||||
|
match device {
|
||||||
|
Backend::Cpu => Self::default_cpu(),
|
||||||
|
Backend::CudaGpu => Self::default_gpu(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_cpu() -> Self {
|
||||||
|
Self {
|
||||||
|
classical: true,
|
||||||
|
multibit: None,
|
||||||
|
keyswitch32: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_gpu() -> Self {
|
||||||
|
Self {
|
||||||
|
classical: false,
|
||||||
|
multibit: Some(MultiBitPBSChoice::new(Constraint::LessThanOrEqual(4))),
|
||||||
|
keyswitch32: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AtomicPatternChoice {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constraints for the Zero-Knowledge proofs used within Compact Public Encryption
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct CompactPkeZkSchemeChoice(EnumSet<SupportedCompactPkeZkScheme>);
|
||||||
|
|
||||||
|
impl CastInto<usize> for SupportedCompactPkeZkScheme {
|
||||||
|
fn cast_into(self) -> usize {
|
||||||
|
self as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompactPkeZkSchemeChoice {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(EnumSet::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn not_used() -> Self {
|
||||||
|
Self::new().allow(SupportedCompactPkeZkScheme::ZkNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allow_all() -> Self {
|
||||||
|
Self::new()
|
||||||
|
.allow(SupportedCompactPkeZkScheme::V1)
|
||||||
|
.allow(SupportedCompactPkeZkScheme::V2)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allow(mut self, v: SupportedCompactPkeZkScheme) -> Self {
|
||||||
|
self.0.insert(v);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deny(mut self, v: SupportedCompactPkeZkScheme) -> Self {
|
||||||
|
self.0.remove(v);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_compatible(&self, v: SupportedCompactPkeZkScheme) -> bool {
|
||||||
|
if self.0.contains(SupportedCompactPkeZkScheme::ZkNotSupported) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
self.0.contains(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CompactPkeZkSchemeChoice {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct PkeSwitchChoice(EnumSet<EncryptionKeyChoice>);
|
||||||
|
|
||||||
|
impl CastInto<usize> for EncryptionKeyChoice {
|
||||||
|
fn cast_into(self) -> usize {
|
||||||
|
self as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PkeSwitchChoice {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(EnumSet::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allow_all() -> Self {
|
||||||
|
Self::new()
|
||||||
|
.allow(EncryptionKeyChoice::Big)
|
||||||
|
.allow(EncryptionKeyChoice::Small)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allow(mut self, v: EncryptionKeyChoice) -> Self {
|
||||||
|
self.0.insert(v);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deny(mut self, v: EncryptionKeyChoice) -> Self {
|
||||||
|
self.0.remove(v);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_compatible(&self, v: EncryptionKeyChoice) -> bool {
|
||||||
|
self.0.contains(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PkeSwitchChoice {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constraints for the dedicated compact public key
|
||||||
|
pub struct DedicatedPublicKeyChoice {
|
||||||
|
zk_scheme: CompactPkeZkSchemeChoice,
|
||||||
|
pke_switch: PkeSwitchChoice,
|
||||||
|
require_re_rand: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DedicatedPublicKeyChoice {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the Zero-Knowledge scheme constraints
|
||||||
|
pub fn with_zk_scheme(mut self, zk_scheme: CompactPkeZkSchemeChoice) -> Self {
|
||||||
|
self.zk_scheme = zk_scheme;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the keyswitch constraints scheme constraints
|
||||||
|
pub fn with_pke_switch(mut self, pke_switch: PkeSwitchChoice) -> Self {
|
||||||
|
self.pke_switch = pke_switch;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_re_randomization(mut self, required: bool) -> Self {
|
||||||
|
self.require_re_rand = required;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_compatible(&self, dedicated_pk_params: &DedicatedCompactPublicKeyParameters) -> bool {
|
||||||
|
if self.require_re_rand && dedicated_pk_params.re_randomization_parameters.is_none() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pke_switch
|
||||||
|
.is_compatible(dedicated_pk_params.ksk_params.destination_key)
|
||||||
|
&& self
|
||||||
|
.zk_scheme
|
||||||
|
.is_compatible(dedicated_pk_params.pke_params.zk_scheme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DedicatedPublicKeyChoice {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
zk_scheme: CompactPkeZkSchemeChoice::allow_all(),
|
||||||
|
pke_switch: PkeSwitchChoice::allow_all(),
|
||||||
|
require_re_rand: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Choices for the noise squashing
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum NoiseSquashingChoice {
|
||||||
|
/// Noise squashing required, with or without compression
|
||||||
|
Yes { with_compression: bool },
|
||||||
|
/// No noise squashing required
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoiseSquashingChoice {
|
||||||
|
fn is_compatible(self, params: Option<&MetaNoiseSquashingParameters>) -> bool {
|
||||||
|
match (self, params) {
|
||||||
|
(Self::Yes { .. }, None) => false,
|
||||||
|
(Self::Yes { with_compression }, Some(params)) => {
|
||||||
|
params.compression_parameters.is_some() == with_compression
|
||||||
|
}
|
||||||
|
(Self::No, None | Some(_)) => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const KNOWN_PARAMETERS: [(Version, &[(&MetaParameters, &str)]); 2] = [
|
||||||
|
(Version(1, 4), &super::v1_4::VEC_ALL_META_PARAMETERS),
|
||||||
|
(Version(1, 5), &super::v1_5::VEC_ALL_META_PARAMETERS),
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Struct that allows to search for known parameters of TFHE-RS given some
|
||||||
|
/// constraints/choices.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// Only parameters starting from version 1.4 can be found
|
||||||
|
pub struct MetaParametersFinder {
|
||||||
|
msg_modulus: MessageModulus,
|
||||||
|
carry_modulus: CarryModulus,
|
||||||
|
failure_probability: Constraint<Log2PFail>,
|
||||||
|
version: Version,
|
||||||
|
backend: Backend,
|
||||||
|
atomic_pattern_choice: AtomicPatternChoice,
|
||||||
|
noise_distribution: NoiseDistributionChoice,
|
||||||
|
dedicated_compact_public_key_choice: Option<DedicatedPublicKeyChoice>,
|
||||||
|
use_compression: bool,
|
||||||
|
noise_squashing_choice: NoiseSquashingChoice,
|
||||||
|
use_re_randomization: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MetaParametersFinder {
|
||||||
|
/// Creates a finder with the given pfail constraint, version and target backend
|
||||||
|
///
|
||||||
|
/// * The default message and carry modulus are both 2^2
|
||||||
|
/// * The atomic pattern constraints depends on the `backend`
|
||||||
|
/// * No other extra 'features' like compression, dedicated public key encryption, noise
|
||||||
|
/// squashing are 'enabled'
|
||||||
|
pub fn new(pfail: Constraint<Log2PFail>, backend: Backend) -> Self {
|
||||||
|
Self {
|
||||||
|
msg_modulus: MessageModulus(4),
|
||||||
|
carry_modulus: CarryModulus(4),
|
||||||
|
failure_probability: pfail,
|
||||||
|
version: Version::current(),
|
||||||
|
backend,
|
||||||
|
atomic_pattern_choice: AtomicPatternChoice::default_for_device(backend),
|
||||||
|
dedicated_compact_public_key_choice: None,
|
||||||
|
use_compression: false,
|
||||||
|
noise_squashing_choice: NoiseSquashingChoice::No,
|
||||||
|
noise_distribution: NoiseDistributionChoice::allow_all(),
|
||||||
|
use_re_randomization: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_version(mut self, version: Version) -> Self {
|
||||||
|
self.version = version;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the noise distribution choice
|
||||||
|
pub const fn with_noise_distribution(
|
||||||
|
mut self,
|
||||||
|
noise_distribution: NoiseDistributionChoice,
|
||||||
|
) -> Self {
|
||||||
|
self.noise_distribution = noise_distribution;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the atomic pattern choice
|
||||||
|
pub const fn with_atomic_pattern(mut self, atomic_pattern_choice: AtomicPatternChoice) -> Self {
|
||||||
|
self.atomic_pattern_choice = atomic_pattern_choice;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the dedicated compact public key choice
|
||||||
|
pub const fn with_dedicated_compact_public_key(
|
||||||
|
mut self,
|
||||||
|
choice: Option<DedicatedPublicKeyChoice>,
|
||||||
|
) -> Self {
|
||||||
|
self.dedicated_compact_public_key_choice = choice;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets whether compression is desired
|
||||||
|
pub const fn with_compression(mut self, enabled: bool) -> Self {
|
||||||
|
self.use_compression = enabled;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the noise squashing choice
|
||||||
|
pub const fn with_noise_squashing(mut self, choice: NoiseSquashingChoice) -> Self {
|
||||||
|
self.noise_squashing_choice = choice;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the block moduluses (MessageModulus, CarryModulus)
|
||||||
|
///
|
||||||
|
/// Only MessageModulus is required as MessageModulus == CarryModulus is forced
|
||||||
|
pub const fn with_block_modulus(mut self, message_modulus: MessageModulus) -> Self {
|
||||||
|
self.msg_modulus = message_modulus;
|
||||||
|
self.carry_modulus = CarryModulus(message_modulus.0);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn with_re_randomization(mut self, enabled: bool) -> Self {
|
||||||
|
self.use_re_randomization = enabled;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the meta parameter is compatible with the choices of the finder
|
||||||
|
///
|
||||||
|
/// A parameter that has more capabilities (e.g. compression), when the user did not ask for
|
||||||
|
/// compression is deemed compatible because we can remove the compression params from the
|
||||||
|
/// struct.
|
||||||
|
fn is_compatible(&self, parameters: &MetaParameters) -> bool {
|
||||||
|
if self.backend != parameters.backend {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.msg_modulus != parameters.compute_parameters.message_modulus()
|
||||||
|
|| self.carry_modulus != parameters.compute_parameters.carry_modulus()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self
|
||||||
|
.failure_probability
|
||||||
|
.is_compatible(¶meters.failure_probability())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.noise_distribution.is_compatible(parameters) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self
|
||||||
|
.atomic_pattern_choice
|
||||||
|
.is_compatible(¶meters.compute_parameters)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match (
|
||||||
|
self.dedicated_compact_public_key_choice.as_ref(),
|
||||||
|
¶meters.dedicated_compact_public_key_parameters,
|
||||||
|
) {
|
||||||
|
(None, None | Some(_)) => {}
|
||||||
|
(Some(_), None) => return false,
|
||||||
|
(Some(choice), Some(params)) => {
|
||||||
|
if !choice.is_compatible(params) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.use_compression && parameters.compression_parameters.is_none() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self
|
||||||
|
.noise_squashing_choice
|
||||||
|
.is_compatible(parameters.noise_squashing_parameters.as_ref())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns None if the parameters are not compatible
|
||||||
|
/// Returns Some(_) if the parameters are compatible
|
||||||
|
/// The returned params may come from more 'capable' parameters
|
||||||
|
/// where unnecessary params were removed
|
||||||
|
fn fit(&self, parameters: &MetaParameters) -> Option<MetaParameters> {
|
||||||
|
if self.is_compatible(parameters) {
|
||||||
|
let mut result = *parameters;
|
||||||
|
if self.dedicated_compact_public_key_choice.is_none() {
|
||||||
|
result.dedicated_compact_public_key_parameters = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dedicated_pke_choice) = self.dedicated_compact_public_key_choice.as_ref() {
|
||||||
|
if !dedicated_pke_choice.require_re_rand {
|
||||||
|
if let Some(pke_params) =
|
||||||
|
result.dedicated_compact_public_key_parameters.as_mut()
|
||||||
|
{
|
||||||
|
pke_params.re_randomization_parameters = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.dedicated_compact_public_key_parameters = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.use_compression {
|
||||||
|
result.compression_parameters = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.noise_squashing_choice {
|
||||||
|
NoiseSquashingChoice::Yes { with_compression } => {
|
||||||
|
if !with_compression {
|
||||||
|
if let Some(ns_params) = result.noise_squashing_parameters.as_mut() {
|
||||||
|
ns_params.compression_parameters.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NoiseSquashingChoice::No => result.noise_squashing_parameters = None,
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(result)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all known meta parameter that satisfy the choices
|
||||||
|
pub fn find_all(&self) -> Vec<MetaParameters> {
|
||||||
|
self.named_find_all().into_iter().map(|(p, _)| p).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to find parameters that matches the constraints/choices
|
||||||
|
///
|
||||||
|
/// Returns Some(_) if at least 1 compatible parameter was found,
|
||||||
|
/// None otherwise
|
||||||
|
///
|
||||||
|
/// If more than one parameter is found, this function will apply its
|
||||||
|
/// own set of rule to select one of them:
|
||||||
|
/// * The parameter with highest pfail is prioritized
|
||||||
|
/// * CPU will favor classical PBS
|
||||||
|
/// * GPU will favor multi-bit PBS
|
||||||
|
pub fn find(&self) -> Option<MetaParameters> {
|
||||||
|
let mut candidates = self.named_find_all();
|
||||||
|
|
||||||
|
if candidates.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if candidates.len() == 1 {
|
||||||
|
return candidates.pop().map(|(param, _)| param);
|
||||||
|
}
|
||||||
|
|
||||||
|
// highest failure probability is the last element,
|
||||||
|
// and higher failure probability means better performance
|
||||||
|
//
|
||||||
|
// Since pfails are negative e.g: -128, -40 for 2^-128 and 2^-40
|
||||||
|
// the closest pfail the constraint is the last one
|
||||||
|
candidates.sort_by(|(a, _), (b, _)| {
|
||||||
|
a.failure_probability()
|
||||||
|
.partial_cmp(&b.failure_probability())
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
match self.backend {
|
||||||
|
// On CPU we prefer Classical PBS with TUniform
|
||||||
|
Backend::Cpu => candidates
|
||||||
|
.iter()
|
||||||
|
.rfind(|(params, _)| {
|
||||||
|
matches!(
|
||||||
|
params.compute_parameters,
|
||||||
|
AtomicPatternParameters::Standard(PBSParameters::PBS(_))
|
||||||
|
) && params.noise_distribution_kind() == NoiseDistributionKind::TUniform
|
||||||
|
})
|
||||||
|
.copied()
|
||||||
|
.or_else(|| candidates.pop())
|
||||||
|
.map(|(param, _)| param),
|
||||||
|
// On GPU we prefer MultiBit PBS with TUniform
|
||||||
|
Backend::CudaGpu => candidates
|
||||||
|
.iter()
|
||||||
|
.rfind(|(params, _)| {
|
||||||
|
matches!(
|
||||||
|
params.compute_parameters,
|
||||||
|
AtomicPatternParameters::Standard(PBSParameters::MultiBitPBS(_))
|
||||||
|
) && params.noise_distribution_kind() == NoiseDistributionKind::TUniform
|
||||||
|
})
|
||||||
|
.copied()
|
||||||
|
.or_else(|| candidates.pop())
|
||||||
|
.map(|(param, _)| param),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all known meta parameter that satisfy the choices
|
||||||
|
///
|
||||||
|
/// This also returns the name of the original params, as it could help to make
|
||||||
|
/// debugging easier
|
||||||
|
fn named_find_all(&self) -> Vec<(MetaParameters, &'static str)> {
|
||||||
|
let mut candidates = Vec::new();
|
||||||
|
|
||||||
|
for (version, parameter_list) in KNOWN_PARAMETERS.iter() {
|
||||||
|
if *version != self.version {
|
||||||
|
continue; // Skip parameters from different versions
|
||||||
|
}
|
||||||
|
|
||||||
|
for (parameters, name) in *parameter_list {
|
||||||
|
if let Some(params) = self.fit(parameters) {
|
||||||
|
candidates.push((params, *name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parameter_finder() {
|
||||||
|
{
|
||||||
|
let finder = MetaParametersFinder::new(
|
||||||
|
Constraint::LessThanOrEqual(Log2PFail(-64.0)),
|
||||||
|
Backend::Cpu,
|
||||||
|
)
|
||||||
|
.with_compression(true)
|
||||||
|
.with_noise_squashing(NoiseSquashingChoice::Yes {
|
||||||
|
with_compression: true,
|
||||||
|
})
|
||||||
|
.with_version(Version(1, 4));
|
||||||
|
|
||||||
|
let params = finder.find();
|
||||||
|
|
||||||
|
let mut expected =
|
||||||
|
super::super::v1_4::meta::cpu::V1_4_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_BIG_ZKV1_TUNIFORM_2M128;
|
||||||
|
expected.dedicated_compact_public_key_parameters = None;
|
||||||
|
assert_eq!(params, Some(expected));
|
||||||
|
|
||||||
|
let finder = MetaParametersFinder::new(
|
||||||
|
Constraint::LessThanOrEqual(Log2PFail(-64.0)),
|
||||||
|
Backend::Cpu,
|
||||||
|
)
|
||||||
|
.with_version(Version(1, 4))
|
||||||
|
.with_atomic_pattern(AtomicPatternChoice::new().classic_pbs(true))
|
||||||
|
.with_compression(true)
|
||||||
|
.with_noise_squashing(NoiseSquashingChoice::Yes {
|
||||||
|
with_compression: true,
|
||||||
|
});
|
||||||
|
let params = finder.find();
|
||||||
|
assert_eq!(params.unwrap(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Try to find multi-bit params for CPU
|
||||||
|
let finder = MetaParametersFinder::new(
|
||||||
|
Constraint::LessThanOrEqual(Log2PFail(-40.0)),
|
||||||
|
Backend::Cpu,
|
||||||
|
)
|
||||||
|
.with_version(Version(1, 4))
|
||||||
|
.with_atomic_pattern(
|
||||||
|
AtomicPatternChoice::new()
|
||||||
|
.multi_bit_pbs(Some(MultiBitPBSChoice::new(Constraint::LessThanOrEqual(4)))),
|
||||||
|
);
|
||||||
|
let params = finder.find();
|
||||||
|
assert_eq!(
|
||||||
|
params,
|
||||||
|
Some(super::super::v1_4::meta::cpu::V1_4_META_PARAM_CPU_2_2_MULTI_BIT_GROUP_4_KS_PBS_GAUSSIAN_2M40)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try to find multi-bit params for GPU
|
||||||
|
let finder = MetaParametersFinder::new(
|
||||||
|
Constraint::LessThanOrEqual(Log2PFail(-40.0)),
|
||||||
|
Backend::CudaGpu,
|
||||||
|
)
|
||||||
|
.with_version(Version(1, 4))
|
||||||
|
.with_atomic_pattern(
|
||||||
|
AtomicPatternChoice::new()
|
||||||
|
.multi_bit_pbs(Some(MultiBitPBSChoice::new(Constraint::LessThanOrEqual(4)))),
|
||||||
|
);
|
||||||
|
let params = finder.find();
|
||||||
|
|
||||||
|
let mut expected =
|
||||||
|
super::super::v1_4::meta::gpu::V1_4_META_PARAM_GPU_2_2_MULTI_BIT_GROUP_3_KS_PBS_TUNIFORM_2M40;
|
||||||
|
expected.dedicated_compact_public_key_parameters = None;
|
||||||
|
|
||||||
|
assert_eq!(params, Some(expected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_parameter_finder_dedicated_pke() {
|
||||||
|
{
|
||||||
|
// Select BIG, and dont care about ZK
|
||||||
|
let finder = MetaParametersFinder::new(
|
||||||
|
Constraint::LessThanOrEqual(Log2PFail(-64.0)),
|
||||||
|
Backend::Cpu,
|
||||||
|
)
|
||||||
|
.with_version(Version(1, 4))
|
||||||
|
.with_dedicated_compact_public_key(Some(
|
||||||
|
DedicatedPublicKeyChoice::new()
|
||||||
|
.with_zk_scheme(CompactPkeZkSchemeChoice::not_used())
|
||||||
|
.with_pke_switch(PkeSwitchChoice::new().allow(EncryptionKeyChoice::Big)),
|
||||||
|
));
|
||||||
|
|
||||||
|
let params = finder.find();
|
||||||
|
|
||||||
|
let mut expected =
|
||||||
|
super::super::v1_4::meta::cpu::V1_4_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_BIG_ZKV1_TUNIFORM_2M128;
|
||||||
|
expected.compression_parameters = None;
|
||||||
|
expected.noise_squashing_parameters = None;
|
||||||
|
expected
|
||||||
|
.dedicated_compact_public_key_parameters
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.re_randomization_parameters = None;
|
||||||
|
assert_eq!(params, Some(expected));
|
||||||
|
|
||||||
|
// Select SMALL, and dont care about ZK
|
||||||
|
let finder = MetaParametersFinder::new(
|
||||||
|
Constraint::LessThanOrEqual(Log2PFail(-64.0)),
|
||||||
|
Backend::Cpu,
|
||||||
|
)
|
||||||
|
.with_version(Version(1, 4))
|
||||||
|
.with_dedicated_compact_public_key(Some(
|
||||||
|
DedicatedPublicKeyChoice::new()
|
||||||
|
.with_zk_scheme(CompactPkeZkSchemeChoice::not_used())
|
||||||
|
.with_pke_switch(PkeSwitchChoice::new().allow(EncryptionKeyChoice::Small))
|
||||||
|
.with_re_randomization(true),
|
||||||
|
));
|
||||||
|
|
||||||
|
let params = finder.find();
|
||||||
|
|
||||||
|
let mut expected =
|
||||||
|
super::super::v1_4::meta::cpu::V1_4_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV1_TUNIFORM_2M128;
|
||||||
|
expected.compression_parameters = None;
|
||||||
|
expected.noise_squashing_parameters = None;
|
||||||
|
assert_eq!(params, Some(expected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parameter_finder_ks32() {
|
||||||
|
let finder =
|
||||||
|
MetaParametersFinder::new(Constraint::LessThanOrEqual(Log2PFail(-64.0)), Backend::Cpu)
|
||||||
|
.with_version(Version(1, 4))
|
||||||
|
.with_atomic_pattern(AtomicPatternChoice::new().keyswitch32(true));
|
||||||
|
|
||||||
|
let params = finder.find();
|
||||||
|
|
||||||
|
let expected =
|
||||||
|
super::super::v1_4::meta::cpu::V1_4_META_PARAM_CPU_2_2_KS32_PBS_TUNIFORM_2M128;
|
||||||
|
|
||||||
|
assert_eq!(params, Some(expected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ pub use parameters_wopbs::*;
|
|||||||
pub use test_params::TestParameters;
|
pub use test_params::TestParameters;
|
||||||
|
|
||||||
/// Backend supported by tfhe-rs
|
/// Backend supported by tfhe-rs
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Versionize)]
|
||||||
|
#[versionize(BackendVersions)]
|
||||||
pub enum Backend {
|
pub enum Backend {
|
||||||
Cpu,
|
Cpu,
|
||||||
CudaGpu,
|
CudaGpu,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::core_crypto::prelude::LweBskGroupingFactor;
|
use crate::core_crypto::prelude::LweBskGroupingFactor;
|
||||||
use crate::shortint::backward_compatibility::parameters::noise_squashing::*;
|
use crate::shortint::backward_compatibility::parameters::noise_squashing::*;
|
||||||
|
use crate::shortint::backward_compatibility::parameters::MetaNoiseSquashingParametersVersions;
|
||||||
use crate::shortint::parameters::{
|
use crate::shortint::parameters::{
|
||||||
CarryModulus, CoreCiphertextModulus, DecompositionBaseLog, DecompositionLevelCount,
|
CarryModulus, CoreCiphertextModulus, DecompositionBaseLog, DecompositionLevelCount,
|
||||||
DynamicDistribution, GlweDimension, LweCiphertextCount, MessageModulus, ModulusSwitchType,
|
DynamicDistribution, GlweDimension, LweCiphertextCount, MessageModulus, ModulusSwitchType,
|
||||||
@@ -143,7 +144,8 @@ pub struct NoiseSquashingCompressionParameters {
|
|||||||
pub ciphertext_modulus: CoreCiphertextModulus<u128>,
|
pub ciphertext_modulus: CoreCiphertextModulus<u128>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, serde::Serialize, serde::Deserialize, Versionize)]
|
||||||
|
#[versionize(MetaNoiseSquashingParametersVersions)]
|
||||||
pub struct MetaNoiseSquashingParameters {
|
pub struct MetaNoiseSquashingParameters {
|
||||||
/// Parameters to do the actual noise squashing
|
/// Parameters to do the actual noise squashing
|
||||||
pub parameters: NoiseSquashingParameters,
|
pub parameters: NoiseSquashingParameters,
|
||||||
|
|||||||
Reference in New Issue
Block a user