chore(ci): add core_crypto layer to code coverage

This commit is contained in:
David Testé
2023-11-20 14:24:28 +01:00
committed by David Testé
parent e8cd55dee6
commit c2d7f1748c
33 changed files with 1790 additions and 1030 deletions

View File

@@ -38,6 +38,7 @@ jobs:
group: ${{ github.workflow }}_${{ github.ref }}_${{ inputs.instance_image_id }}_${{ inputs.instance_type }}
cancel-in-progress: true
runs-on: ${{ inputs.runner_name }}
timeout-minutes: 1080
steps:
# Step used for log purpose.
- name: Instance configuration used
@@ -79,6 +80,12 @@ jobs:
if: steps.changed-files.outputs.tfhe_any_changed == 'true'
run: |
make GEN_KEY_CACHE_COVERAGE_ONLY=TRUE gen_key_cache
make gen_key_cache_core_crypto
- name: Run coverage for core_crypto
if: steps.changed-files.outputs.tfhe_any_changed == 'true'
run: |
make test_core_crypto_cov AVX512_SUPPORT=ON
- name: Run coverage for boolean
if: steps.changed-files.outputs.tfhe_any_changed == 'true'
@@ -97,7 +104,7 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
directory: ./coverage/
fail_ci_if_error: true
files: shortint/cobertura.xml,boolean/cobertura.xml
files: shortint/cobertura.xml,boolean/cobertura.xml,core_crypto/cobertura.xml,core_crypto_avx512/cobertura.xml
- name: Slack Notification
if: ${{ failure() }}

View File

@@ -225,13 +225,6 @@ clippy_js_wasm_api clippy_tasks clippy_core clippy_concrete_csprng clippy_triviu
clippy_fast: clippy clippy_all_targets clippy_c_api clippy_js_wasm_api clippy_tasks clippy_core \
clippy_concrete_csprng
.PHONY: gen_key_cache # Run the script to generate keys and cache them for shortint tests
gen_key_cache: install_rs_build_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) run --profile $(CARGO_PROFILE) \
--example generates_test_keys \
--features=$(TARGET_ARCH_FEATURE),boolean,shortint,internal-keycache -- \
$(MULTI_BIT_ONLY) $(COVERAGE_ONLY)
.PHONY: build_core # Build core_crypto without experimental features
build_core: install_rs_build_toolchain install_rs_check_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) build --profile $(CARGO_PROFILE) \
@@ -319,6 +312,21 @@ test_core_crypto: install_rs_build_toolchain install_rs_check_toolchain
--features=$(TARGET_ARCH_FEATURE),experimental,$(AVX512_FEATURE) -p $(TFHE_SPEC) -- core_crypto::; \
fi
.PHONY: test_core_crypto_cov # Run the tests of the core_crypto module with code coverage
test_core_crypto_cov: install_rs_build_toolchain install_rs_check_toolchain install_tarpaulin
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) tarpaulin --profile $(CARGO_PROFILE) \
--out xml --output-dir coverage/core_crypto --line --engine llvm --timeout 500 \
--implicit-test-threads $(COVERAGE_EXCLUDED_FILES) \
--features=$(TARGET_ARCH_FEATURE),experimental,internal-keycache,__coverage \
-p tfhe -- core_crypto::
@if [[ "$(AVX512_SUPPORT)" == "ON" ]]; then \
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_CHECK_TOOLCHAIN) tarpaulin --profile $(CARGO_PROFILE) \
--out xml --output-dir coverage/core_crypto_avx512 --line --engine llvm --timeout 500 \
--implicit-test-threads $(COVERAGE_EXCLUDED_FILES) \
--features=$(TARGET_ARCH_FEATURE),experimental,internal-keycache,__coverage,$(AVX512_FEATURE) \
-p tfhe -- core_crypto::; \
fi
.PHONY: test_boolean # Run the tests of the boolean module
test_boolean: install_rs_build_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) test --profile $(CARGO_PROFILE) \
@@ -627,6 +635,18 @@ ci_bench_web_js_api_parallel: build_web_js_api_parallel
#
# Utility tools
#
.PHONY: gen_key_cache # Run the script to generate keys and cache them for shortint tests
gen_key_cache: install_rs_build_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) run --profile $(CARGO_PROFILE) \
--example generates_test_keys \
--features=$(TARGET_ARCH_FEATURE),boolean,shortint,internal-keycache -- \
$(MULTI_BIT_ONLY) $(COVERAGE_ONLY)
.PHONY: gen_key_cache_core_crypto # Run function to generate keys and cache them for core_crypto tests
gen_key_cache_core_crypto: install_rs_build_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) test --tests --profile $(CARGO_PROFILE) \
--features=$(TARGET_ARCH_FEATURE),experimental,internal-keycache -p tfhe -- --nocapture \
core_crypto::keycache::generate_keys
.PHONY: measure_hlapi_compact_pk_ct_sizes # Measure sizes of public keys and ciphertext for high-level API
measure_hlapi_compact_pk_ct_sizes: install_rs_check_toolchain

View File

@@ -44,7 +44,7 @@ pub mod seeded_lwe_public_key_decompression;
pub mod slice_algorithms;
#[cfg(test)]
mod test;
pub(crate) mod test;
// No pub use for slice and polynomial algorithms which would not interest higher level users
// They can still be used via `use crate::core_crypto::algorithms::slice_algorithms::*;`

View File

@@ -6,6 +6,11 @@ use crate::core_crypto::commons::generators::{
use crate::core_crypto::commons::math::random::{ActivatedRandomGenerator, CompressionSeed};
use crate::core_crypto::commons::test_tools;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_parallel_and_seeded_ggsw_encryption_equivalence<Scalar>(
ciphertext_modulus: CiphertextModulus<Scalar>,
) where
@@ -27,8 +32,6 @@ fn test_parallel_and_seeded_ggsw_encryption_equivalence<Scalar>(
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
const NB_TESTS: usize = 10;
for _ in 0..NB_TESTS {
// Create the GlweSecretKey
let glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
@@ -174,7 +177,7 @@ fn test_parallel_and_seeded_ggsw_encryption_equivalence_u64_custom_mod() {
);
}
fn ggsw_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn ggsw_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -184,8 +187,6 @@ fn ggsw_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Sca
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let mut msg = Scalar::ONE << decomposition_base_log.0;
while msg != Scalar::ZERO {
@@ -232,13 +233,18 @@ fn ggsw_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Sca
assert!(decoded.0 == msg);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(ggsw_encrypt_decrypt_custom_mod);
fn ggsw_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -249,8 +255,6 @@ fn ggsw_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let mut msg = Scalar::ONE << decomposition_base_log.0;
while msg != Scalar::ZERO {
@@ -297,12 +301,19 @@ fn ggsw_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
assert!(decoded.0 == msg);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(ggsw_par_encrypt_decrypt_custom_mod);
fn ggsw_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn ggsw_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -312,8 +323,6 @@ fn ggsw_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let mut msg = Scalar::ONE << decomposition_base_log.0;
while msg != Scalar::ZERO {
@@ -363,13 +372,18 @@ fn ggsw_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
assert!(decoded.0 == msg);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(ggsw_seeded_encrypt_decrypt_custom_mod);
fn ggsw_seeded_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync + Send>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -380,8 +394,6 @@ fn ggsw_seeded_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync + Sen
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let mut msg = Scalar::ONE << decomposition_base_log.0;
while msg != Scalar::ZERO {
@@ -431,6 +443,11 @@ fn ggsw_seeded_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync + Sen
assert!(decoded.0 == msg);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -1,6 +1,13 @@
use super::*;
fn glwe_encrypt_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn glwe_encrypt_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -10,7 +17,6 @@ fn glwe_encrypt_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -57,12 +63,17 @@ fn glwe_encrypt_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_assign_decrypt_custom_mod);
fn glwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -72,7 +83,6 @@ fn glwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Sca
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -123,12 +133,17 @@ fn glwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Sca
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_decrypt_custom_mod);
fn glwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -139,7 +154,6 @@ fn glwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParam
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -195,12 +209,19 @@ fn glwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParam
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_list_encrypt_decrypt_custom_mod);
fn glwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -209,7 +230,6 @@ fn glwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPa
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -254,13 +274,18 @@ fn glwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPa
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_trivial_encrypt_decrypt_custom_mod);
fn glwe_allocate_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -270,7 +295,6 @@ fn glwe_allocate_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -308,12 +332,19 @@ fn glwe_allocate_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert!(output_plaintext_list.iter().all(|x| *x.0 == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_allocate_trivial_encrypt_decrypt_custom_mod);
fn glwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -323,7 +354,6 @@ fn glwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -384,12 +414,19 @@ fn glwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_seeded_encrypt_decrypt_custom_mod);
fn glwe_seeded_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_seeded_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -400,7 +437,6 @@ fn glwe_seeded_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Te
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -459,6 +495,11 @@ fn glwe_seeded_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Te
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -1,6 +1,13 @@
use super::*;
fn glwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn glwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -10,7 +17,6 @@ fn glwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Tes
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -70,12 +76,17 @@ fn glwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Tes
assert!(decoded.iter().all(|&x| x == (msg + msg) % msg_modulus));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_add_assign_decrypt_custom_mod);
fn glwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -85,7 +96,6 @@ fn glwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -147,13 +157,18 @@ fn glwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams
assert!(decoded.iter().all(|&x| x == (msg + msg) % msg_modulus));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_add_decrypt_custom_mod);
fn glwe_encrypt_plaintext_list_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -164,7 +179,6 @@ fn glwe_encrypt_plaintext_list_add_assign_decrypt_custom_mod<Scalar: UnsignedTor
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -222,13 +236,18 @@ fn glwe_encrypt_plaintext_list_add_assign_decrypt_custom_mod<Scalar: UnsignedTor
assert!(decoded.iter().all(|&x| x == (msg + msg) % msg_modulus));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_plaintext_list_add_assign_decrypt_custom_mod);
fn glwe_encrypt_plaintext_list_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -239,7 +258,6 @@ fn glwe_encrypt_plaintext_list_sub_assign_decrypt_custom_mod<Scalar: UnsignedTor
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -297,13 +315,18 @@ fn glwe_encrypt_plaintext_list_sub_assign_decrypt_custom_mod<Scalar: UnsignedTor
assert!(decoded.iter().all(|&x| x == Scalar::ZERO));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_plaintext_list_sub_assign_decrypt_custom_mod);
fn glwe_encrypt_plaintext_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -314,7 +337,6 @@ fn glwe_encrypt_plaintext_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -373,13 +395,18 @@ fn glwe_encrypt_plaintext_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert!(decoded.iter().all(|&x| x == (msg + msg) % msg_modulus));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_plaintext_add_assign_decrypt_custom_mod);
fn glwe_encrypt_plaintext_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -390,7 +417,6 @@ fn glwe_encrypt_plaintext_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -449,13 +475,18 @@ fn glwe_encrypt_plaintext_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert!(decoded.iter().all(|&x| x == Scalar::ZERO));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_plaintext_sub_assign_decrypt_custom_mod);
fn glwe_encrypt_opposite_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -466,7 +497,6 @@ fn glwe_encrypt_opposite_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -526,13 +556,18 @@ fn glwe_encrypt_opposite_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
.iter()
.all(|&x| x == msg.wrapping_neg() % msg_modulus));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_opposite_assign_decrypt_custom_mod);
fn glwe_encrypt_cleartext_mul_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -543,7 +578,6 @@ fn glwe_encrypt_cleartext_mul_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -604,13 +638,18 @@ fn glwe_encrypt_cleartext_mul_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
.iter()
.all(|&x| x == (msg * cleartext.0) % msg_modulus));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_cleartext_mul_assign_decrypt_custom_mod);
fn glwe_encrypt_cleartext_mul_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -621,7 +660,6 @@ fn glwe_encrypt_cleartext_mul_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -684,12 +722,19 @@ fn glwe_encrypt_cleartext_mul_decrypt_custom_mod<Scalar: UnsignedTorus>(
.iter()
.all(|&x| x == (msg * cleartext.0) % msg_modulus));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_cleartext_mul_decrypt_custom_mod);
fn glwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -699,7 +744,6 @@ fn glwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Tes
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -759,12 +803,17 @@ fn glwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Tes
assert!(decoded.iter().all(|&x| x == Scalar::ZERO));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(glwe_encrypt_sub_assign_decrypt_custom_mod);
fn glwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn glwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -774,7 +823,6 @@ fn glwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -836,6 +884,11 @@ fn glwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams
assert!(decoded.iter().all(|&x| x == Scalar::ZERO));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -1,7 +1,11 @@
use super::*;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn glwe_encrypt_sample_extract_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
@@ -12,7 +16,6 @@ fn glwe_encrypt_sample_extract_decrypt_custom_mod<Scalar: UnsignedTorus + Send +
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -107,6 +110,11 @@ fn glwe_encrypt_sample_extract_decrypt_custom_mod<Scalar: UnsignedTorus + Send +
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -10,10 +10,15 @@ use crate::core_crypto::commons::parameters::{
use crate::core_crypto::commons::test_tools::new_secret_random_generator;
use crate::core_crypto::entities::*;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_parallel_and_seeded_bsk_gen_equivalence<T: UnsignedTorus + Sync + Send>(
ciphertext_modulus: CiphertextModulus<T>,
) {
for _ in 0..10 {
for _ in 0..NB_TESTS {
let lwe_dim =
LweDimension(crate::core_crypto::commons::test_tools::random_usize_between(5..10));
let glwe_dim =

View File

@@ -5,6 +5,11 @@ use crate::core_crypto::commons::generators::{
};
use crate::core_crypto::commons::math::random::ActivatedRandomGenerator;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_seeded_lwe_cpk_gen_equivalence<Scalar: UnsignedTorus>(
ciphertext_modulus: CiphertextModulus<Scalar>,
) {
@@ -22,9 +27,7 @@ fn test_seeded_lwe_cpk_gen_equivalence<Scalar: UnsignedTorus>(
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
const NB_TEST: usize = 10;
for _ in 0..NB_TEST {
for _ in 0..NB_TESTS {
// Create the LweSecretKey
let input_lwe_secret_key =
allocate_and_generate_new_binary_lwe_secret_key(lwe_dimension, &mut secret_generator);

View File

@@ -2,8 +2,13 @@ use super::*;
use crate::core_crypto::commons::generators::DeterministicSeeder;
use crate::core_crypto::commons::test_tools;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_parallel_and_seeded_lwe_list_encryption_equivalence<Scalar: UnsignedTorus + Sync + Send>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
// DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
// computations
@@ -21,8 +26,6 @@ fn test_parallel_and_seeded_lwe_list_encryption_equivalence<Scalar: UnsignedToru
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
const NB_TESTS: usize = 10;
for _ in 0..NB_TESTS {
// Create the LweSecretKey
let lwe_secret_key =
@@ -148,7 +151,7 @@ fn test_parallel_and_seeded_lwe_list_encryption_equivalence_non_native_power_of_
test_parallel_and_seeded_lwe_list_encryption_equivalence(DUMMY_31_U32);
}
fn lwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -157,7 +160,6 @@ fn lwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scal
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -197,12 +199,19 @@ fn lwe_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scal
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_decrypt_custom_mod);
fn lwe_allocate_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_allocate_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -211,7 +220,6 @@ fn lwe_allocate_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPa
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -245,12 +253,19 @@ fn lwe_allocate_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPa
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_allocate_encrypt_decrypt_custom_mod);
fn lwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
@@ -258,7 +273,6 @@ fn lwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -292,12 +306,17 @@ fn lwe_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPar
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_trivial_encrypt_decrypt_custom_mod);
fn lwe_allocate_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -306,7 +325,6 @@ fn lwe_allocate_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -338,12 +356,17 @@ fn lwe_allocate_trivial_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_allocate_trivial_encrypt_decrypt_custom_mod);
fn lwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -353,7 +376,6 @@ fn lwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -403,13 +425,18 @@ fn lwe_list_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_list_encrypt_decrypt_custom_mod);
fn lwe_list_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync + Send>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -420,7 +447,6 @@ fn lwe_list_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync + Send>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -470,12 +496,17 @@ fn lwe_list_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync + Send>(
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_list_par_encrypt_decrypt_custom_mod);
fn lwe_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -485,7 +516,6 @@ fn lwe_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPara
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -532,12 +562,19 @@ fn lwe_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPara
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_public_encrypt_decrypt_custom_mod);
fn lwe_seeded_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_seeded_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -547,7 +584,6 @@ fn lwe_seeded_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: T
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -601,13 +637,18 @@ fn lwe_seeded_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: T
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_seeded_public_encrypt_decrypt_custom_mod);
fn lwe_seeded_list_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync + Send>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -618,7 +659,6 @@ fn lwe_seeded_list_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync +
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -680,12 +720,17 @@ fn lwe_seeded_list_par_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus + Sync +
assert!(decoded.iter().all(|&x| x == msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_seeded_list_par_encrypt_decrypt_custom_mod);
fn lwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -694,7 +739,6 @@ fn lwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPara
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -742,13 +786,18 @@ fn lwe_seeded_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestPara
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_seeded_encrypt_decrypt_custom_mod);
fn lwe_seeded_allocate_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -758,7 +807,6 @@ fn lwe_seeded_allocate_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -799,6 +847,11 @@ fn lwe_seeded_allocate_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
@@ -820,7 +873,6 @@ fn test_u128_encryption() {
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
const NB_TESTS: usize = 10;
const MSG_BITS: u32 = 4;
for _ in 0..NB_TESTS {
@@ -870,7 +922,7 @@ fn test_u128_encryption() {
}
fn lwe_compact_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = LweDimension(params.polynomial_size.0);
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -880,7 +932,6 @@ fn lwe_compact_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -929,6 +980,11 @@ fn lwe_compact_public_encrypt_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -1,7 +1,12 @@
use super::*;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn lwe_encrypt_ks_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -15,7 +20,6 @@ fn lwe_encrypt_ks_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -94,6 +98,11 @@ fn lwe_encrypt_ks_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -5,6 +5,11 @@ use crate::core_crypto::commons::generators::{
};
use crate::core_crypto::commons::math::random::ActivatedRandomGenerator;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_seeded_lwe_ksk_gen_equivalence<Scalar: UnsignedTorus + Send + Sync>(
ciphertext_modulus: CiphertextModulus<Scalar>,
) {
@@ -25,9 +30,7 @@ fn test_seeded_lwe_ksk_gen_equivalence<Scalar: UnsignedTorus + Send + Sync>(
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
const NB_TEST: usize = 10;
for _ in 0..NB_TEST {
for _ in 0..NB_TESTS {
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,

View File

@@ -1,6 +1,13 @@
use super::*;
fn lwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn lwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -9,7 +16,6 @@ fn lwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Test
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -58,12 +64,17 @@ fn lwe_encrypt_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Test
assert_eq!((msg + msg) % msg_modulus, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_add_assign_decrypt_custom_mod);
fn lwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -72,7 +83,6 @@ fn lwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -121,13 +131,18 @@ fn lwe_encrypt_add_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<
assert_eq!((msg + msg) % msg_modulus, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_add_decrypt_custom_mod);
fn lwe_encrypt_plaintext_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -137,7 +152,6 @@ fn lwe_encrypt_plaintext_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -184,13 +198,18 @@ fn lwe_encrypt_plaintext_add_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert_eq!((msg + msg) % msg_modulus, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_plaintext_add_assign_decrypt_custom_mod);
fn lwe_encrypt_plaintext_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -200,7 +219,6 @@ fn lwe_encrypt_plaintext_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -247,13 +265,18 @@ fn lwe_encrypt_plaintext_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert_eq!(Scalar::ZERO, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_plaintext_sub_assign_decrypt_custom_mod);
fn lwe_encrypt_opposite_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -263,7 +286,6 @@ fn lwe_encrypt_opposite_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -310,13 +332,18 @@ fn lwe_encrypt_opposite_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
assert_eq!(msg.wrapping_neg() % msg_modulus, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_opposite_assign_decrypt_custom_mod);
fn lwe_encrypt_ciphertext_cleartext_mul_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -326,7 +353,6 @@ fn lwe_encrypt_ciphertext_cleartext_mul_assign_decrypt_custom_mod<Scalar: Unsign
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -374,12 +400,19 @@ fn lwe_encrypt_ciphertext_cleartext_mul_assign_decrypt_custom_mod<Scalar: Unsign
assert_eq!(msg * cleartext.0 % msg_modulus, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_ciphertext_cleartext_mul_assign_decrypt_custom_mod);
fn lwe_encrypt_cleartext_mul_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_encrypt_cleartext_mul_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -388,7 +421,6 @@ fn lwe_encrypt_cleartext_mul_decrypt_custom_mod<Scalar: UnsignedTorus>(params: T
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -438,12 +470,19 @@ fn lwe_encrypt_cleartext_mul_decrypt_custom_mod<Scalar: UnsignedTorus>(params: T
assert_eq!((msg * cleartext.0) % msg_modulus, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_cleartext_mul_decrypt_custom_mod);
fn lwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -452,7 +491,6 @@ fn lwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Test
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -521,12 +559,17 @@ fn lwe_encrypt_sub_assign_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Test
assert_eq!(Scalar::ONE, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_sub_assign_decrypt_custom_mod);
fn lwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
fn lwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: ClassicTestParams<Scalar>) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
@@ -535,7 +578,6 @@ fn lwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -606,6 +648,11 @@ fn lwe_encrypt_sub_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<
assert_eq!(Scalar::ONE, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -11,12 +11,17 @@ use crate::core_crypto::commons::test_tools::new_secret_random_generator;
use crate::core_crypto::entities::*;
use crate::core_crypto::prelude::CastFrom;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_parallel_and_seeded_multi_bit_bsk_gen_equivalence<
T: UnsignedTorus + CastFrom<usize> + Sync + Send,
>(
ciphertext_modulus: CiphertextModulus<T>,
) {
for _ in 0..10 {
for _ in 0..NB_TESTS {
let mut lwe_dim =
LweDimension(crate::core_crypto::commons::test_tools::random_usize_between(5..10));
let glwe_dim =

View File

@@ -1,36 +1,94 @@
use super::*;
use crate::core_crypto::keycache::KeyCacheAccess;
use serde::de::DeserializeOwned;
use serde::Serialize;
pub struct MultiBitParams<Scalar: UnsignedInteger> {
pub input_lwe_dimension: LweDimension,
pub lwe_modular_std_dev: StandardDev,
pub decomp_base_log: DecompositionBaseLog,
pub decomp_level_count: DecompositionLevelCount,
pub glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub glwe_modular_std_dev: StandardDev,
pub message_modulus_log: CiphertextModulusLog,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
pub grouping_factor: LweBskGroupingFactor,
pub thread_count: ThreadCount,
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(not(feature = "__coverage"))]
// Divided by two compared to other tests, we are running the algorithm twice for determinism
const NB_TESTS_LIGHT: usize = 5;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
#[cfg(feature = "__coverage")]
const NB_TESTS_LIGHT: usize = 1;
pub fn generate_keys<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize> + Serialize + DeserializeOwned,
>(
params: MultiBitTestParams<Scalar>,
rsc: &mut TestResources,
) -> MultiBitBootstrapKeys<Scalar> {
// Keygen is a bit slow on this one so we keep it out of the testing loop
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
params.input_lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
params.glwe_dimension,
params.polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut bsk = LweMultiBitBootstrapKey::new(
Scalar::ZERO,
params.glwe_dimension.to_glwe_size(),
params.polynomial_size,
params.decomp_base_log,
params.decomp_level_count,
params.input_lwe_dimension,
params.grouping_factor,
params.ciphertext_modulus,
);
par_generate_lwe_multi_bit_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
params.glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
let mut fbsk = FourierLweMultiBitBootstrapKey::new(
params.input_lwe_dimension,
params.glwe_dimension.to_glwe_size(),
params.polynomial_size,
params.decomp_base_log,
params.decomp_level_count,
params.grouping_factor,
);
par_convert_standard_lwe_multi_bit_bootstrap_key_to_fourier(&bsk, &mut fbsk);
MultiBitBootstrapKeys {
small_lwe_sk: input_lwe_secret_key,
big_lwe_sk: output_lwe_secret_key,
bsk,
fbsk,
}
}
fn lwe_encrypt_multi_bit_pbs_decrypt_custom_mod<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize>,
>(
params: MultiBitParams<Scalar>,
) {
let input_lwe_dimension = params.input_lwe_dimension;
fn lwe_encrypt_multi_bit_pbs_decrypt_custom_mod<Scalar>(params: MultiBitTestParams<Scalar>)
where
Scalar: UnsignedTorus
+ Sync
+ Send
+ CastFrom<usize>
+ CastInto<usize>
+ Serialize
+ DeserializeOwned,
MultiBitTestParams<Scalar>: KeyCacheAccess<Keys = MultiBitBootstrapKeys<Scalar>>,
{
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let decomp_base_log = params.decomp_base_log;
let decomp_level_count = params.decomp_level_count;
let grouping_factor = params.grouping_factor;
let thread_count = params.thread_count;
let mut rsc = TestResources::new();
@@ -43,7 +101,6 @@ fn lwe_encrypt_multi_bit_pbs_decrypt_custom_mod<
let delta: Scalar = encoding_with_padding / msg_modulus;
let mut msg = msg_modulus;
const NB_TESTS: usize = 10;
let accumulator = generate_accumulator(
polynomial_size,
@@ -59,56 +116,17 @@ fn lwe_encrypt_multi_bit_pbs_decrypt_custom_mod<
ciphertext_modulus
));
// Keygen is a bit slow on this one so we keep it out of the testing loop
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let mut bsk = LweMultiBitBootstrapKey::new(
Scalar::ZERO,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
input_lwe_dimension,
grouping_factor,
ciphertext_modulus,
);
par_generate_lwe_multi_bit_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (input_lwe_secret_key, output_lwe_secret_key, bsk, fbsk) =
(keys.small_lwe_sk, keys.big_lwe_sk, keys.bsk, keys.fbsk);
assert!(check_encrypted_content_respects_mod(
&*bsk,
ciphertext_modulus
));
let mut fbsk = FourierLweMultiBitBootstrapKey::new(
input_lwe_dimension,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
grouping_factor,
);
par_convert_standard_lwe_multi_bit_bootstrap_key_to_fourier(&bsk, &mut fbsk);
drop(bsk);
while msg != Scalar::ZERO {
msg = msg.wrapping_sub(Scalar::ONE);
for _ in 0..NB_TESTS {
@@ -152,26 +170,33 @@ fn lwe_encrypt_multi_bit_pbs_decrypt_custom_mod<
assert_eq!(decoded, f(msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
fn lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize>,
>(
params: MultiBitParams<Scalar>,
) {
let input_lwe_dimension = params.input_lwe_dimension;
fn lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<Scalar>(
params: MultiBitTestParams<Scalar>,
) where
Scalar: UnsignedTorus
+ Sync
+ Send
+ CastFrom<usize>
+ CastInto<usize>
+ Serialize
+ DeserializeOwned,
MultiBitTestParams<Scalar>: KeyCacheAccess<Keys = MultiBitBootstrapKeys<Scalar>>,
{
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let decomp_base_log = params.decomp_base_log;
let decomp_level_count = params.decomp_level_count;
let grouping_factor = params.grouping_factor;
let thread_count = params.thread_count;
let mut rsc = TestResources::new();
@@ -184,8 +209,6 @@ fn lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
let delta: Scalar = encoding_with_padding / msg_modulus;
let mut msg = msg_modulus;
// Divided by two compared to other tests, we are running the algorithm twice for determinism
const NB_TESTS: usize = 5;
let accumulator = generate_accumulator(
polynomial_size,
@@ -201,59 +224,20 @@ fn lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
ciphertext_modulus
));
// Keygen is a bit slow on this one so we keep it out of the testing loop
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let mut bsk = LweMultiBitBootstrapKey::new(
Scalar::ZERO,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
input_lwe_dimension,
grouping_factor,
ciphertext_modulus,
);
par_generate_lwe_multi_bit_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (input_lwe_secret_key, output_lwe_secret_key, bsk, fbsk) =
(keys.small_lwe_sk, keys.big_lwe_sk, keys.bsk, keys.fbsk);
assert!(check_encrypted_content_respects_mod(
&*bsk,
ciphertext_modulus
));
let mut fbsk = FourierLweMultiBitBootstrapKey::new(
input_lwe_dimension,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
grouping_factor,
);
par_convert_standard_lwe_multi_bit_bootstrap_key_to_fourier(&bsk, &mut fbsk);
drop(bsk);
while msg != Scalar::ZERO {
msg = msg.wrapping_sub(Scalar::ONE);
for _ in 0..NB_TESTS {
for _ in 0..NB_TESTS_LIGHT {
let plaintext = Plaintext(msg * delta);
let lwe_ciphertext_in = allocate_and_encrypt_new_lwe_ciphertext(
@@ -318,26 +302,32 @@ fn lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
assert_eq!(out_pbs_ct_other, out_pbs_ct);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
fn lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize>,
>(
params: MultiBitParams<Scalar>,
) {
let input_lwe_dimension = params.input_lwe_dimension;
fn lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod<Scalar>(params: MultiBitTestParams<Scalar>)
where
Scalar: UnsignedTorus
+ Sync
+ Send
+ CastFrom<usize>
+ CastInto<usize>
+ Serialize
+ DeserializeOwned,
MultiBitTestParams<Scalar>: KeyCacheAccess<Keys = MultiBitBootstrapKeys<Scalar>>,
{
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let decomp_base_log = params.decomp_base_log;
let decomp_level_count = params.decomp_level_count;
let grouping_factor = params.grouping_factor;
let thread_count = params.thread_count;
let mut rsc = TestResources::new();
@@ -350,7 +340,6 @@ fn lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod<
let delta: Scalar = encoding_with_padding / msg_modulus;
let mut msg = msg_modulus;
const NB_TESTS: usize = 10;
let accumulator = generate_accumulator(
polynomial_size,
@@ -366,37 +355,11 @@ fn lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod<
ciphertext_modulus
));
// Keygen is a bit slow on this one so we keep it out of the testing loop
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let mut bsk = LweMultiBitBootstrapKey::new(
Scalar::ZERO,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
input_lwe_dimension,
grouping_factor,
ciphertext_modulus,
);
par_generate_lwe_multi_bit_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (input_lwe_secret_key, output_lwe_secret_key, bsk) =
(keys.small_lwe_sk, keys.big_lwe_sk, keys.bsk);
assert!(check_encrypted_content_respects_mod(
&*bsk,
@@ -446,26 +409,33 @@ fn lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod<
assert_eq!(decoded, f(msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
fn std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize>,
>(
params: MultiBitParams<Scalar>,
) {
let input_lwe_dimension = params.input_lwe_dimension;
fn std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<Scalar>(
params: MultiBitTestParams<Scalar>,
) where
Scalar: UnsignedTorus
+ Sync
+ Send
+ CastFrom<usize>
+ CastInto<usize>
+ Serialize
+ DeserializeOwned,
MultiBitTestParams<Scalar>: KeyCacheAccess<Keys = MultiBitBootstrapKeys<Scalar>>,
{
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let decomp_base_log = params.decomp_base_log;
let decomp_level_count = params.decomp_level_count;
let grouping_factor = params.grouping_factor;
let thread_count = params.thread_count;
let mut rsc = TestResources::new();
@@ -478,8 +448,6 @@ fn std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
let delta: Scalar = encoding_with_padding / msg_modulus;
let mut msg = msg_modulus;
// Divided by two compared to other tests, we are running the algorithm twice for determinism
const NB_TESTS: usize = 5;
let accumulator = generate_accumulator(
polynomial_size,
@@ -495,37 +463,11 @@ fn std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
ciphertext_modulus
));
// Keygen is a bit slow on this one so we keep it out of the testing loop
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let mut bsk = LweMultiBitBootstrapKey::new(
Scalar::ZERO,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
input_lwe_dimension,
grouping_factor,
ciphertext_modulus,
);
par_generate_lwe_multi_bit_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (input_lwe_secret_key, output_lwe_secret_key, bsk) =
(keys.small_lwe_sk, keys.big_lwe_sk, keys.bsk);
assert!(check_encrypted_content_respects_mod(
&*bsk,
@@ -599,179 +541,98 @@ fn std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod<
assert_eq!(out_pbs_ct_other, out_pbs_ct);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
// DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield
// correct computations
const MULTI_BIT_2_2_2_PARAMS: MultiBitParams<u64> = MultiBitParams {
input_lwe_dimension: LweDimension(818),
lwe_modular_std_dev: StandardDev(0.000002226459789930014),
decomp_base_log: DecompositionBaseLog(22),
decomp_level_count: DecompositionLevelCount(1),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
glwe_modular_std_dev: StandardDev(0.0000000000000003152931493498455),
message_modulus_log: CiphertextModulusLog(4),
ciphertext_modulus: CiphertextModulus::new_native(),
grouping_factor: LweBskGroupingFactor(2),
thread_count: ThreadCount(5),
};
const MULTI_BIT_2_2_3_PARAMS: MultiBitParams<u64> = MultiBitParams {
input_lwe_dimension: LweDimension(888),
lwe_modular_std_dev: StandardDev(0.0000006125031601933181),
decomp_base_log: DecompositionBaseLog(21),
decomp_level_count: DecompositionLevelCount(1),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
glwe_modular_std_dev: StandardDev(0.0000000000000003152931493498455),
message_modulus_log: CiphertextModulusLog(4),
ciphertext_modulus: CiphertextModulus::new_native(),
grouping_factor: LweBskGroupingFactor(3),
thread_count: ThreadCount(12),
};
#[test]
pub fn test_lwe_encrypt_multi_bit_pbs_decrypt_factor_2_thread_5_native_mod() {
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
..MULTI_BIT_2_2_2_PARAMS
});
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_2_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_multi_bit_pbs_decrypt_factor_3_thread_12_native_mod() {
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
..MULTI_BIT_2_2_3_PARAMS
});
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_3_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_multi_bit_pbs_decrypt_factor_2_thread_5_custom_mod() {
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_2_PARAMS
});
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_2_CUSTOM_MOD_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_multi_bit_pbs_decrypt_factor_3_thread_12_custom_mod() {
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_3_PARAMS
});
lwe_encrypt_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_3_CUSTOM_MOD_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_2_thread_5_native_mod() {
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
..MULTI_BIT_2_2_2_PARAMS
});
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_2_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_3_thread_12_native_mod() {
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
..MULTI_BIT_2_2_3_PARAMS
});
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_3_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_2_thread_5_custom_mod() {
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_2_PARAMS
});
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(
MULTI_BIT_2_2_2_CUSTOM_MOD_PARAMS,
);
}
#[test]
pub fn test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_3_thread_12_custom_mod() {
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_3_PARAMS
});
lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(
MULTI_BIT_2_2_3_CUSTOM_MOD_PARAMS,
);
}
#[test]
pub fn test_lwe_encrypt_std_multi_bit_pbs_decrypt_factor_2_thread_5_native_mod() {
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
..MULTI_BIT_2_2_2_PARAMS
});
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_2_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_std_multi_bit_pbs_decrypt_factor_3_thread_12_native_mod() {
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
..MULTI_BIT_2_2_3_PARAMS
});
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_3_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_std_multi_bit_pbs_decrypt_factor_2_thread_5_custom_mod() {
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_2_PARAMS
});
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_2_CUSTOM_MOD_PARAMS);
}
#[test]
pub fn test_lwe_encrypt_std_multi_bit_pbs_decrypt_factor_3_thread_12_custom_mod() {
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_3_PARAMS
});
lwe_encrypt_std_multi_bit_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_3_CUSTOM_MOD_PARAMS);
}
#[test]
pub fn std_test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_2_thread_5_native_mod() {
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
..MULTI_BIT_2_2_2_PARAMS
});
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_2_PARAMS);
}
#[test]
pub fn std_test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_3_thread_12_native_mod() {
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
..MULTI_BIT_2_2_3_PARAMS
});
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MULTI_BIT_2_2_3_PARAMS);
}
#[test]
pub fn std_test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_2_thread_5_custom_mod() {
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(5),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_2_PARAMS
});
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(
MULTI_BIT_2_2_2_CUSTOM_MOD_PARAMS,
);
}
#[test]
pub fn std_test_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_factor_3_thread_12_custom_mod() {
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(MultiBitParams {
thread_count: ThreadCount(12),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::try_new_power_of_2(63).unwrap(),
..MULTI_BIT_2_2_3_PARAMS
});
std_lwe_encrypt_multi_bit_deterministic_pbs_decrypt_custom_mod::<u64>(
MULTI_BIT_2_2_3_CUSTOM_MOD_PARAMS,
);
}

View File

@@ -1,20 +1,64 @@
use super::*;
use crate::core_crypto::keycache::KeyCacheAccess;
use serde::de::DeserializeOwned;
use serde::Serialize;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn generate_keys<Scalar: UnsignedTorus + Sync + Send + Serialize + DeserializeOwned>(
params: PackingKeySwitchTestParams<Scalar>,
rsc: &mut TestResources,
) -> PackingKeySwitchKeys<Scalar> {
let lwe_sk = allocate_and_generate_new_binary_lwe_secret_key(
params.lwe_dimension,
&mut rsc.secret_random_generator,
);
let glwe_sk = allocate_and_generate_new_binary_glwe_secret_key(
params.glwe_dimension,
params.polynomial_size,
&mut rsc.secret_random_generator,
);
let pksk = allocate_and_generate_new_lwe_packing_keyswitch_key(
&lwe_sk,
&glwe_sk,
params.pbs_base_log,
params.pbs_level,
params.glwe_modular_std_dev,
params.ciphertext_modulus,
&mut rsc.encryption_random_generator,
);
assert!(check_encrypted_content_respects_mod(
&pksk,
params.ciphertext_modulus
));
PackingKeySwitchKeys {
lwe_sk,
glwe_sk,
pksk,
}
}
fn lwe_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar, P>(params: P)
where
Scalar: UnsignedTorus + Serialize + DeserializeOwned,
P: Into<PackingKeySwitchTestParams<Scalar>>,
PackingKeySwitchTestParams<Scalar>: KeyCacheAccess<Keys = PackingKeySwitchKeys<Scalar>>,
{
let params = params.into();
fn lwe_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar: UnsignedTorus>(params: TestParams<Scalar>) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let decomp_base_log = params.pbs_base_log;
let decomp_level_count = params.pbs_level;
let mut rsc = TestResources::new();
const NB_TESTS: usize = 10;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -22,31 +66,9 @@ fn lwe_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Tes
while msg != Scalar::ZERO {
msg = msg.wrapping_sub(Scalar::ONE);
for _ in 0..NB_TESTS {
let lwe_sk = allocate_and_generate_new_binary_lwe_secret_key(
lwe_dimension,
&mut rsc.secret_random_generator,
);
let glwe_sk = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let pksk = allocate_and_generate_new_lwe_packing_keyswitch_key(
&lwe_sk,
&glwe_sk,
decomp_base_log,
decomp_level_count,
glwe_modular_std_dev,
ciphertext_modulus,
&mut rsc.encryption_random_generator,
);
assert!(check_encrypted_content_respects_mod(
&pksk,
ciphertext_modulus
));
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (pksk, lwe_sk, glwe_sk) = (keys.pksk, keys.lwe_sk, keys.glwe_sk);
let plaintext = Plaintext(msg * delta);
@@ -86,29 +108,31 @@ fn lwe_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar: UnsignedTorus>(params: Tes
assert_eq!(msg, decoded);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_pks_to_glwe_decrypt_custom_mod);
fn lwe_list_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar: UnsignedTorus + Send + Sync>(
params: TestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
fn lwe_list_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar, P>(params: P)
where
Scalar: UnsignedTorus + Serialize + DeserializeOwned,
P: Into<PackingKeySwitchTestParams<Scalar>>,
PackingKeySwitchTestParams<Scalar>: KeyCacheAccess<Keys = PackingKeySwitchKeys<Scalar>>,
{
let params = params.into();
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let decomp_base_log = params.pbs_base_log;
let decomp_level_count = params.pbs_level;
let mut rsc = TestResources::new();
// These tests are pretty heavy, cut down a bit
const NB_TESTS: usize = 5;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let mut msg = msg_modulus;
let delta: Scalar = encoding_with_padding / msg_modulus;
@@ -116,31 +140,9 @@ fn lwe_list_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar: UnsignedTorus + Send
while msg != Scalar::ZERO {
msg = msg.wrapping_sub(Scalar::ONE);
for _ in 0..NB_TESTS {
let lwe_sk = allocate_and_generate_new_binary_lwe_secret_key(
lwe_dimension,
&mut rsc.secret_random_generator,
);
let glwe_sk = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let pksk = allocate_and_generate_new_lwe_packing_keyswitch_key(
&lwe_sk,
&glwe_sk,
decomp_base_log,
decomp_level_count,
glwe_modular_std_dev,
ciphertext_modulus,
&mut rsc.encryption_random_generator,
);
assert!(check_encrypted_content_respects_mod(
&pksk,
ciphertext_modulus
));
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (pksk, lwe_sk, glwe_sk) = (keys.pksk, keys.lwe_sk, keys.glwe_sk);
let mut input_lwe_list = LweCiphertextList::new(
Scalar::ZERO,
@@ -212,6 +214,11 @@ fn lwe_list_encrypt_pks_to_glwe_decrypt_custom_mod<Scalar: UnsignedTorus + Send
assert_eq!(decrypted_plaintext_list, input_plaintext_list);
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -5,6 +5,11 @@ use crate::core_crypto::commons::generators::{
};
use crate::core_crypto::commons::math::random::ActivatedRandomGenerator;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_seeded_lwe_pksk_gen_equivalence<Scalar: UnsignedTorus>(
ciphertext_modulus: CiphertextModulus<Scalar>,
) {
@@ -26,9 +31,7 @@ fn test_seeded_lwe_pksk_gen_equivalence<Scalar: UnsignedTorus>(
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
const NB_TEST: usize = 10;
for _ in 0..NB_TEST {
for _ in 0..NB_TESTS {
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,

View File

@@ -1,5 +1,10 @@
use super::*;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
fn test_parallel_pfpks_equivalence<Scalar: UnsignedTorus + Send + Sync>(
ciphertext_modulus: CiphertextModulus<Scalar>,
) {
@@ -26,7 +31,7 @@ fn test_parallel_pfpks_equivalence<Scalar: UnsignedTorus + Send + Sync>(
ciphertext_modulus,
);
for _ in 0..10 {
for _ in 0..NB_TESTS {
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_key_lwe_dimension,
&mut rsc.secret_random_generator,
@@ -98,7 +103,7 @@ fn test_parallel_pfpks_equivalence<Scalar: UnsignedTorus + Send + Sync>(
// Small sizes
{
for _ in 0..10 {
for _ in 0..NB_TESTS {
let decomp_base_log = DecompositionBaseLog(
crate::core_crypto::commons::test_tools::random_usize_between(2..5),
);
@@ -128,7 +133,7 @@ fn test_parallel_pfpks_equivalence<Scalar: UnsignedTorus + Send + Sync>(
ciphertext_modulus,
);
for _ in 0..10 {
for _ in 0..NB_TESTS {
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_key_lwe_dimension,
&mut rsc.secret_random_generator,

View File

@@ -1,21 +1,90 @@
use super::*;
use crate::core_crypto::keycache::KeyCacheAccess;
use serde::de::DeserializeOwned;
use serde::Serialize;
fn lwe_encrypt_pbs_decrypt_custom_mod<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize>,
#[cfg(not(feature = "__coverage"))]
const NB_TESTS: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
pub fn generate_keys<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize> + Serialize + DeserializeOwned,
>(
params: TestParams<Scalar>,
) {
let input_lwe_dimension = params.lwe_dimension;
params: ClassicTestParams<Scalar>,
rsc: &mut TestResources,
) -> ClassicBootstrapKeys<Scalar> {
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
params.lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
params.glwe_dimension,
params.polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut bsk = LweBootstrapKey::new(
Scalar::ZERO,
params.glwe_dimension.to_glwe_size(),
params.polynomial_size,
params.pbs_base_log,
params.pbs_level,
params.lwe_dimension,
params.ciphertext_modulus,
);
par_generate_lwe_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
params.glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
assert!(check_encrypted_content_respects_mod(
&*bsk,
params.ciphertext_modulus
));
let mut fbsk = FourierLweBootstrapKey::new(
params.lwe_dimension,
params.glwe_dimension.to_glwe_size(),
params.polynomial_size,
params.pbs_base_log,
params.pbs_level,
);
par_convert_standard_lwe_bootstrap_key_to_fourier(&bsk, &mut fbsk);
ClassicBootstrapKeys {
small_lwe_sk: input_lwe_secret_key,
big_lwe_sk: output_lwe_secret_key,
bsk,
fbsk,
}
}
fn lwe_encrypt_pbs_decrypt_custom_mod<Scalar>(params: ClassicTestParams<Scalar>)
where
Scalar: UnsignedTorus
+ Sync
+ Send
+ CastFrom<usize>
+ CastInto<usize>
+ Serialize
+ DeserializeOwned,
ClassicTestParams<Scalar>: KeyCacheAccess<Keys = ClassicBootstrapKeys<Scalar>>,
{
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let decomp_base_log = params.pbs_base_log;
let decomp_level_count = params.pbs_level;
let mut rsc = TestResources::new();
@@ -27,7 +96,6 @@ fn lwe_encrypt_pbs_decrypt_custom_mod<
let delta: Scalar = encoding_with_padding / msg_modulus;
let mut msg = msg_modulus;
const NB_TESTS: usize = 10;
let accumulator = generate_accumulator(
polynomial_size,
@@ -45,52 +113,11 @@ fn lwe_encrypt_pbs_decrypt_custom_mod<
while msg != Scalar::ZERO {
msg = msg.wrapping_sub(Scalar::ONE);
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut bsk = LweBootstrapKey::new(
Scalar::ZERO,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
input_lwe_dimension,
ciphertext_modulus,
);
par_generate_lwe_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
assert!(check_encrypted_content_respects_mod(
&*bsk,
ciphertext_modulus
));
let mut fbsk = FourierLweBootstrapKey::new(
input_lwe_dimension,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
);
par_convert_standard_lwe_bootstrap_key_to_fourier(&bsk, &mut fbsk);
drop(bsk);
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (input_lwe_secret_key, output_lwe_secret_key, fbsk) =
(keys.small_lwe_sk, keys.big_lwe_sk, keys.fbsk);
for _ in 0..NB_TESTS {
let plaintext = Plaintext(msg * delta);
@@ -132,13 +159,18 @@ fn lwe_encrypt_pbs_decrypt_custom_mod<
assert_eq!(decoded, f(msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}
create_parametrized_test!(lwe_encrypt_pbs_decrypt_custom_mod);
// DISCLAIMER: all parameters here are not guaranteed to be secure or yield correct computations
pub const TEST_PARAMS_4_BITS_NATIVE_U128: TestParams<u128> = TestParams {
pub const TEST_PARAMS_4_BITS_NATIVE_U128: ClassicTestParams<u128> = ClassicTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
@@ -157,7 +189,7 @@ pub const TEST_PARAMS_4_BITS_NATIVE_U128: TestParams<u128> = TestParams {
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const TEST_PARAMS_3_BITS_127_U128: TestParams<u128> = TestParams {
pub const TEST_PARAMS_3_BITS_127_U128: ClassicTestParams<u128> = ClassicTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
@@ -176,14 +208,19 @@ pub const TEST_PARAMS_3_BITS_127_U128: TestParams<u128> = TestParams {
ciphertext_modulus: CiphertextModulus::new(1 << 127),
};
fn lwe_encrypt_pbs_f128_decrypt_custom_mod<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize>,
>(
params: TestParams<Scalar>,
) {
fn lwe_encrypt_pbs_f128_decrypt_custom_mod<Scalar>(params: ClassicTestParams<Scalar>)
where
Scalar: UnsignedTorus
+ Sync
+ Send
+ CastFrom<usize>
+ CastInto<usize>
+ Serialize
+ DeserializeOwned,
ClassicTestParams<Scalar>: KeyCacheAccess<Keys = ClassicBootstrapKeys<Scalar>>,
{
let input_lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_modular_std_dev = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;
let message_modulus_log = params.message_modulus_log;
let msg_modulus = Scalar::ONE.shl(message_modulus_log.0);
@@ -203,7 +240,6 @@ fn lwe_encrypt_pbs_f128_decrypt_custom_mod<
let delta: Scalar = encoding_with_padding / msg_modulus;
let mut msg = msg_modulus;
const NB_TESTS: usize = 10;
let accumulator = generate_accumulator(
polynomial_size,
@@ -221,40 +257,12 @@ fn lwe_encrypt_pbs_f128_decrypt_custom_mod<
while msg != Scalar::ZERO {
msg = msg.wrapping_sub(Scalar::ONE);
// Create the LweSecretKey
let input_lwe_secret_key = allocate_and_generate_new_binary_lwe_secret_key(
input_lwe_dimension,
&mut rsc.secret_random_generator,
);
let output_glwe_secret_key = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut rsc.secret_random_generator,
);
let output_lwe_secret_key = output_glwe_secret_key.clone().into_lwe_secret_key();
let mut bsk = LweBootstrapKey::new(
Scalar::ZERO,
glwe_dimension.to_glwe_size(),
polynomial_size,
decomp_base_log,
decomp_level_count,
input_lwe_dimension,
ciphertext_modulus,
);
let mut keys_gen = |params| generate_keys(params, &mut rsc);
par_generate_lwe_bootstrap_key(
&input_lwe_secret_key,
&output_glwe_secret_key,
&mut bsk,
glwe_modular_std_dev,
&mut rsc.encryption_random_generator,
);
assert!(check_encrypted_content_respects_mod(
&*bsk,
ciphertext_modulus
));
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (input_lwe_secret_key, output_lwe_secret_key, bsk) =
(keys.small_lwe_sk, keys.big_lwe_sk, keys.bsk);
let mut fbsk = Fourier128LweBootstrapKey::new(
input_lwe_dimension,
@@ -308,6 +316,11 @@ fn lwe_encrypt_pbs_f128_decrypt_custom_mod<
assert_eq!(decoded, f(msg));
}
// In coverage, we break after one while loop iteration, changing message values does not
// yield higher coverage
#[cfg(feature = "__coverage")]
break;
}
}

View File

@@ -1,6 +1,11 @@
pub mod params;
pub(crate) use params::*;
pub use super::misc::check_encrypted_content_respects_mod;
use crate::core_crypto::keycache::KeyCacheAccess;
use crate::core_crypto::prelude::*;
use paste::paste;
use std::fmt::Debug;
mod ggsw_encryption;
mod glwe_encryption;
@@ -13,11 +18,11 @@ mod lwe_keyswitch;
mod lwe_keyswitch_key_generation;
mod lwe_linear_algebra;
mod lwe_multi_bit_bootstrap_key_generation;
mod lwe_multi_bit_programmable_bootstrapping;
pub(crate) mod lwe_multi_bit_programmable_bootstrapping;
mod lwe_packing_keyswitch;
mod lwe_packing_keyswitch_key_generation;
mod lwe_private_functional_packing_keyswitch;
mod lwe_programmable_bootstrapping;
pub(crate) mod lwe_programmable_bootstrapping;
mod noise_distribution;
pub struct TestResources {
@@ -40,28 +45,14 @@ impl TestResources {
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct TestParams<Scalar: UnsignedTorus> {
pub lwe_dimension: LweDimension,
pub glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub lwe_modular_std_dev: StandardDev,
pub glwe_modular_std_dev: StandardDev,
pub pbs_base_log: DecompositionBaseLog,
pub pbs_level: DecompositionLevelCount,
pub ks_base_log: DecompositionBaseLog,
pub ks_level: DecompositionLevelCount,
pub pfks_level: DecompositionLevelCount,
pub pfks_base_log: DecompositionBaseLog,
pub pfks_modular_std_dev: StandardDev,
pub cbs_level: DecompositionLevelCount,
pub cbs_base_log: DecompositionBaseLog,
pub message_modulus_log: CiphertextModulusLog,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
impl Default for TestResources {
fn default() -> Self {
Self::new()
}
}
// DISCLAIMER: all parameters here are not guaranteed to be secure or yield correct computations
pub const TEST_PARAMS_4_BITS_NATIVE_U64: TestParams<u64> = TestParams {
pub const TEST_PARAMS_4_BITS_NATIVE_U64: ClassicTestParams<u64> = ClassicTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
@@ -80,7 +71,7 @@ pub const TEST_PARAMS_4_BITS_NATIVE_U64: TestParams<u64> = TestParams {
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const TEST_PARAMS_3_BITS_63_U64: TestParams<u64> = TestParams {
pub const TEST_PARAMS_3_BITS_63_U64: ClassicTestParams<u64> = ClassicTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
@@ -99,7 +90,26 @@ pub const TEST_PARAMS_3_BITS_63_U64: TestParams<u64> = TestParams {
ciphertext_modulus: CiphertextModulus::new(1 << 63),
};
pub const DUMMY_NATIVE_U32: TestParams<u32> = TestParams {
pub const TEST_PARAMS_3_BITS_SOLINAS_U64: ClassicTestParams<u64> = ClassicTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
lwe_modular_std_dev: StandardDev(0.000007069849454709433),
glwe_modular_std_dev: StandardDev(0.00000000000000029403601535432533),
pbs_base_log: DecompositionBaseLog(23),
pbs_level: DecompositionLevelCount(1),
ks_level: DecompositionLevelCount(5),
ks_base_log: DecompositionBaseLog(3),
pfks_level: DecompositionLevelCount(1),
pfks_base_log: DecompositionBaseLog(23),
pfks_modular_std_dev: StandardDev(0.00000000000000029403601535432533),
cbs_level: DecompositionLevelCount(0),
cbs_base_log: DecompositionBaseLog(0),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::new((1 << 64) - (1 << 32) + 1),
};
pub const DUMMY_NATIVE_U32: ClassicTestParams<u32> = ClassicTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
@@ -118,7 +128,7 @@ pub const DUMMY_NATIVE_U32: TestParams<u32> = TestParams {
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const DUMMY_31_U32: TestParams<u32> = TestParams {
pub const DUMMY_31_U32: ClassicTestParams<u32> = ClassicTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
@@ -137,23 +147,173 @@ pub const DUMMY_31_U32: TestParams<u32> = TestParams {
ciphertext_modulus: CiphertextModulus::new(1 << 31),
};
pub const TEST_PARAMS_3_BITS_SOLINAS_U64: TestParams<u64> = TestParams {
pub const MULTI_BIT_2_2_2_PARAMS: MultiBitTestParams<u64> = MultiBitTestParams {
input_lwe_dimension: LweDimension(818),
lwe_modular_std_dev: StandardDev(0.000002226459789930014),
decomp_base_log: DecompositionBaseLog(22),
decomp_level_count: DecompositionLevelCount(1),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
glwe_modular_std_dev: StandardDev(0.0000000000000003152931493498455),
message_modulus_log: CiphertextModulusLog(4),
ciphertext_modulus: CiphertextModulus::new_native(),
grouping_factor: LweBskGroupingFactor(2),
thread_count: ThreadCount(5),
};
pub const MULTI_BIT_2_2_2_CUSTOM_MOD_PARAMS: MultiBitTestParams<u64> = MultiBitTestParams {
input_lwe_dimension: LweDimension(818),
lwe_modular_std_dev: StandardDev(0.000002226459789930014),
decomp_base_log: DecompositionBaseLog(22),
decomp_level_count: DecompositionLevelCount(1),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
glwe_modular_std_dev: StandardDev(0.0000000000000003152931493498455),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::new(1 << 63),
grouping_factor: LweBskGroupingFactor(2),
thread_count: ThreadCount(5),
};
pub const MULTI_BIT_2_2_3_PARAMS: MultiBitTestParams<u64> = MultiBitTestParams {
input_lwe_dimension: LweDimension(888),
lwe_modular_std_dev: StandardDev(0.0000006125031601933181),
decomp_base_log: DecompositionBaseLog(21),
decomp_level_count: DecompositionLevelCount(1),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
glwe_modular_std_dev: StandardDev(0.0000000000000003152931493498455),
message_modulus_log: CiphertextModulusLog(4),
ciphertext_modulus: CiphertextModulus::new_native(),
grouping_factor: LweBskGroupingFactor(3),
thread_count: ThreadCount(12),
};
pub const MULTI_BIT_2_2_3_CUSTOM_MOD_PARAMS: MultiBitTestParams<u64> = MultiBitTestParams {
input_lwe_dimension: LweDimension(888),
lwe_modular_std_dev: StandardDev(0.0000006125031601933181),
decomp_base_log: DecompositionBaseLog(21),
decomp_level_count: DecompositionLevelCount(1),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
glwe_modular_std_dev: StandardDev(0.0000000000000003152931493498455),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::new(1 << 63),
grouping_factor: LweBskGroupingFactor(3),
thread_count: ThreadCount(12),
};
// DISCLAIMER: example parameters tailored for FFT implementation tests. There are not guaranteed
// to be secure or yield correct computations.
// Define the parameters for a 4 bits message able to hold the doubled 2 bits message.
pub const FFT_U32_PARAMS: FftTestParams<u32> = FftTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
lwe_modular_std_dev: StandardDev(0.000007069849454709433),
glwe_modular_std_dev: StandardDev(0.00000000000000029403601535432533),
lwe_modular_std_dev: StandardDev(0.00000000004998277131225527),
glwe_modular_std_dev: StandardDev(0.00000000000000000000000000000008645717832544903),
pbs_base_log: DecompositionBaseLog(23),
pbs_level: DecompositionLevelCount(1),
ks_level: DecompositionLevelCount(5),
ks_base_log: DecompositionBaseLog(3),
pfks_level: DecompositionLevelCount(1),
pfks_base_log: DecompositionBaseLog(23),
pfks_modular_std_dev: StandardDev(0.00000000000000029403601535432533),
cbs_level: DecompositionLevelCount(0),
cbs_base_log: DecompositionBaseLog(0),
message_modulus_log: CiphertextModulusLog(3),
ciphertext_modulus: CiphertextModulus::new((1 << 64) - (1 << 32) + 1),
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const FFT_U64_PARAMS: FftTestParams<u64> = FftTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
lwe_modular_std_dev: StandardDev(0.00000000004998277131225527),
glwe_modular_std_dev: StandardDev(0.00000000000000000000000000000008645717832544903),
pbs_base_log: DecompositionBaseLog(23),
pbs_level: DecompositionLevelCount(1),
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const FFT_U128_PARAMS: FftTestParams<u128> = FftTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
lwe_modular_std_dev: StandardDev(0.00000000004998277131225527),
glwe_modular_std_dev: StandardDev(0.00000000000000000000000000000008645717832544903),
pbs_base_log: DecompositionBaseLog(23),
pbs_level: DecompositionLevelCount(1),
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const FFT128_U128_PARAMS: FftTestParams<u128> = FftTestParams {
lwe_dimension: LweDimension(742),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(2048),
lwe_modular_std_dev: StandardDev(0.12345),
glwe_modular_std_dev: StandardDev(0.00000000000000000000000000000008645717832544903),
pbs_base_log: DecompositionBaseLog(23),
pbs_level: DecompositionLevelCount(1),
ciphertext_modulus: CiphertextModulus::<u128>::new_native(),
};
pub const FFT_WOPBS_PARAMS: FftWopPbsTestParams<u64> = FftWopPbsTestParams {
lwe_dimension: LweDimension(481),
glwe_dimension: GlweDimension(1),
polynomial_size: PolynomialSize(1024),
// Value was 0.000_000_000_000_000_221_486_881_160_055_68_513645324585951
// But rust indicates it gets truncated anyways to
// 0.000_000_000_000_000_221_486_881_160_055_68
lwe_modular_std_dev: StandardDev(0.000_000_000_000_000_221_486_881_160_055_68),
// Value was 0.000_061_200_133_780_220_371_345
// But rust indicates it gets truncated anyways to
// 0.000_061_200_133_780_220_36
glwe_modular_std_dev: StandardDev(0.000_061_200_133_780_220_36),
pbs_base_log: DecompositionBaseLog(4),
pbs_level: DecompositionLevelCount(9),
pfks_level: DecompositionLevelCount(9),
pfks_base_log: DecompositionBaseLog(4),
cbs_level: DecompositionLevelCount(4),
cbs_base_log: DecompositionBaseLog(6),
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const FFT_WOPBS_N512_PARAMS: FftWopPbsTestParams<u64> = FftWopPbsTestParams {
lwe_dimension: LweDimension(4),
glwe_dimension: GlweDimension(2),
polynomial_size: PolynomialSize(512),
lwe_modular_std_dev: StandardDev(0.000_000_000_000_000_221_486_881_160_055_68),
glwe_modular_std_dev: StandardDev(0.000_061_200_133_780_220_36),
pbs_base_log: DecompositionBaseLog(9),
pbs_level: DecompositionLevelCount(4),
pfks_level: DecompositionLevelCount(2),
pfks_base_log: DecompositionBaseLog(15),
cbs_level: DecompositionLevelCount(4),
cbs_base_log: DecompositionBaseLog(6),
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const FFT_WOPBS_N1024_PARAMS: FftWopPbsTestParams<u64> = FftWopPbsTestParams {
lwe_dimension: LweDimension(4),
glwe_dimension: GlweDimension(2),
polynomial_size: PolynomialSize(1024),
lwe_modular_std_dev: StandardDev(0.000_000_000_000_000_221_486_881_160_055_68),
glwe_modular_std_dev: StandardDev(0.000_061_200_133_780_220_36),
pbs_base_log: DecompositionBaseLog(9),
pbs_level: DecompositionLevelCount(4),
pfks_level: DecompositionLevelCount(2),
pfks_base_log: DecompositionBaseLog(15),
cbs_level: DecompositionLevelCount(4),
cbs_base_log: DecompositionBaseLog(6),
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub const FFT_WOPBS_N2048_PARAMS: FftWopPbsTestParams<u64> = FftWopPbsTestParams {
lwe_dimension: LweDimension(4),
glwe_dimension: GlweDimension(2),
polynomial_size: PolynomialSize(2048),
lwe_modular_std_dev: StandardDev(0.000_000_000_000_000_221_486_881_160_055_68),
glwe_modular_std_dev: StandardDev(0.000_061_200_133_780_220_36),
pbs_base_log: DecompositionBaseLog(9),
pbs_level: DecompositionLevelCount(4),
pfks_level: DecompositionLevelCount(2),
pfks_base_log: DecompositionBaseLog(15),
cbs_level: DecompositionLevelCount(4),
cbs_base_log: DecompositionBaseLog(6),
ciphertext_modulus: CiphertextModulus::new_native(),
};
pub fn get_encoding_with_padding<Scalar: UnsignedInteger>(
@@ -223,6 +383,23 @@ where
)
}
pub(crate) fn gen_keys_or_get_from_cache_if_enabled<
P: Debug + KeyCacheAccess<Keys = K> + serde::Serialize + serde::de::DeserializeOwned,
K: serde::de::DeserializeOwned + serde::Serialize + Clone,
>(
params: P,
keygen_func: &mut dyn FnMut(P) -> K,
) -> K {
#[cfg(feature = "internal-keycache")]
{
crate::core_crypto::keycache::KEY_CACHE.get_key_with_closure(params, keygen_func)
}
#[cfg(not(feature = "internal-keycache"))]
{
keygen_func(params)
}
}
// Macro to generate tests for all parameter sets
macro_rules! create_parametrized_test{
($name:ident { $($param:ident),* }) => {

View File

@@ -9,7 +9,7 @@ use crate::core_crypto::commons::test_tools::{
const RELATIVE_TOLERANCE: f64 = 0.0625;
fn lwe_encrypt_decrypt_noise_distribution_custom_mod<Scalar: UnsignedTorus + CastInto<usize>>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = params.lwe_dimension;
let lwe_modular_std_dev = params.lwe_modular_std_dev;
@@ -109,7 +109,7 @@ fn test_variance_increase_cpk_formula() {
fn lwe_compact_public_encrypt_noise_distribution_custom_mod<
Scalar: UnsignedTorus + CastInto<usize>,
>(
params: TestParams<Scalar>,
params: ClassicTestParams<Scalar>,
) {
let lwe_dimension = LweDimension(params.polynomial_size.0);
let glwe_modular_std_dev = params.glwe_modular_std_dev;
@@ -194,7 +194,9 @@ create_parametrized_test!(lwe_compact_public_encrypt_noise_distribution_custom_m
TEST_PARAMS_4_BITS_NATIVE_U64
});
fn random_noise_roundtrip<Scalar: UnsignedTorus + CastInto<usize>>(params: TestParams<Scalar>) {
fn random_noise_roundtrip<Scalar: UnsignedTorus + CastInto<usize>>(
params: ClassicTestParams<Scalar>,
) {
let mut rsc = TestResources::new();
let noise = params.glwe_modular_std_dev;
let ciphertext_modulus = params.ciphertext_modulus;

View File

@@ -0,0 +1,217 @@
use crate::core_crypto::commons::dispersion::*;
use crate::core_crypto::commons::parameters::*;
use crate::core_crypto::entities::*;
use crate::core_crypto::prelude::{CastFrom, CastInto, UnsignedInteger};
use crate::keycache::NamedParam;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ClassicBootstrapKeys<Scalar: UnsignedInteger> {
pub small_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub big_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub bsk: LweBootstrapKeyOwned<Scalar>,
pub fbsk: FourierLweBootstrapKeyOwned,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MultiBitBootstrapKeys<Scalar: UnsignedInteger> {
pub small_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub big_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub bsk: LweMultiBitBootstrapKeyOwned<Scalar>,
pub fbsk: FourierLweMultiBitBootstrapKeyOwned,
}
// Fourier key is generated afterward in order to use generic test function
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct FftBootstrapKeys<Scalar: UnsignedInteger> {
pub small_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub big_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub bsk: LweBootstrapKeyOwned<Scalar>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct FftWopPbsKeys<Scalar: UnsignedInteger> {
pub small_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub big_lwe_sk: LweSecretKey<Vec<Scalar>>,
pub fbsk: FourierLweBootstrapKeyOwned,
pub lwe_pfpksk: LwePrivateFunctionalPackingKeyswitchKeyListOwned<Scalar>,
}
// Fourier key is generated afterward in order to use generic test function
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PackingKeySwitchKeys<Scalar: UnsignedInteger> {
pub lwe_sk: LweSecretKey<Vec<Scalar>>,
pub glwe_sk: GlweSecretKey<Vec<Scalar>>,
pub pksk: LwePackingKeyswitchKeyOwned<Scalar>,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ClassicTestParams<Scalar: UnsignedInteger> {
pub lwe_dimension: LweDimension,
pub glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub lwe_modular_std_dev: StandardDev,
pub glwe_modular_std_dev: StandardDev,
pub pbs_base_log: DecompositionBaseLog,
pub pbs_level: DecompositionLevelCount,
pub ks_base_log: DecompositionBaseLog,
pub ks_level: DecompositionLevelCount,
pub pfks_level: DecompositionLevelCount,
pub pfks_base_log: DecompositionBaseLog,
pub pfks_modular_std_dev: StandardDev,
pub cbs_level: DecompositionLevelCount,
pub cbs_base_log: DecompositionBaseLog,
pub message_modulus_log: CiphertextModulusLog,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct MultiBitTestParams<Scalar: UnsignedInteger> {
pub input_lwe_dimension: LweDimension,
pub lwe_modular_std_dev: StandardDev,
pub decomp_base_log: DecompositionBaseLog,
pub decomp_level_count: DecompositionLevelCount,
pub glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub glwe_modular_std_dev: StandardDev,
pub message_modulus_log: CiphertextModulusLog,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
pub grouping_factor: LweBskGroupingFactor,
pub thread_count: ThreadCount,
}
// PartialEq is implemented manually because thread_count doesn't affect key generation and we want
// to change its value in test without the need of regenerating keys in the key cache.
impl<Scalar: UnsignedInteger> PartialEq for MultiBitTestParams<Scalar> {
fn eq(&self, other: &Self) -> bool {
self.input_lwe_dimension == other.input_lwe_dimension
&& self.lwe_modular_std_dev == other.lwe_modular_std_dev
&& self.decomp_base_log == other.decomp_base_log
&& self.decomp_level_count == other.decomp_level_count
&& self.glwe_dimension == other.glwe_dimension
&& self.polynomial_size == other.polynomial_size
&& self.glwe_modular_std_dev == other.glwe_modular_std_dev
&& self.message_modulus_log == other.message_modulus_log
&& self.ciphertext_modulus == other.ciphertext_modulus
&& self.grouping_factor == other.grouping_factor
}
}
// Parameters to test FFT implementation
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct FftTestParams<Scalar: UnsignedInteger> {
pub lwe_dimension: LweDimension,
pub glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub lwe_modular_std_dev: StandardDev,
pub glwe_modular_std_dev: StandardDev,
pub pbs_base_log: DecompositionBaseLog,
pub pbs_level: DecompositionLevelCount,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
// Parameters to test FFT implementation on wopPBS
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct FftWopPbsTestParams<Scalar: UnsignedInteger> {
pub lwe_dimension: LweDimension,
pub glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub lwe_modular_std_dev: StandardDev,
pub glwe_modular_std_dev: StandardDev,
pub pbs_base_log: DecompositionBaseLog,
pub pbs_level: DecompositionLevelCount,
pub pfks_level: DecompositionLevelCount,
pub pfks_base_log: DecompositionBaseLog,
pub cbs_level: DecompositionLevelCount,
pub cbs_base_log: DecompositionBaseLog,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PackingKeySwitchTestParams<Scalar: UnsignedInteger> {
pub lwe_dimension: LweDimension,
pub glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub lwe_modular_std_dev: StandardDev,
pub glwe_modular_std_dev: StandardDev,
pub pbs_base_log: DecompositionBaseLog,
pub pbs_level: DecompositionLevelCount,
pub message_modulus_log: CiphertextModulusLog,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
impl<Scalar: UnsignedInteger + CastFrom<usize> + CastInto<usize>> From<ClassicTestParams<Scalar>>
for PackingKeySwitchTestParams<Scalar>
{
fn from(params: ClassicTestParams<Scalar>) -> Self {
Self {
lwe_dimension: params.lwe_dimension,
glwe_dimension: params.glwe_dimension,
polynomial_size: params.polynomial_size,
lwe_modular_std_dev: params.lwe_modular_std_dev,
glwe_modular_std_dev: params.glwe_modular_std_dev,
pbs_base_log: params.pbs_base_log,
pbs_level: params.pbs_level,
message_modulus_log: params.message_modulus_log,
ciphertext_modulus: params.ciphertext_modulus,
}
}
}
impl<Scalar: UnsignedInteger> NamedParam for ClassicTestParams<Scalar> {
fn name(&self) -> String {
format!(
"PARAM_LWE_BOOTSTRAP_glwe_{}_poly_{}_decomp_base_log_{}_decomp_level_{}_lwe_dim_{}_ct_modulus_{}_msg_modulus_{}",
self.glwe_dimension.0, self.polynomial_size.0, self.pbs_base_log.0, self.pbs_level.0,
self.lwe_dimension.0, self.ciphertext_modulus, self.message_modulus_log.0
)
}
}
impl<Scalar: UnsignedInteger> NamedParam for MultiBitTestParams<Scalar> {
fn name(&self) -> String {
format!(
"PARAM_LWE_MULTI_BIT_BOOTSTRAP_glwe_{}_poly_{}_decomp_base_log_{}_decomp_level_{}_input_dim_{}_ct_modulus_{}_msg_modulus_log_{}_group_factor_{}",
self.glwe_dimension.0, self.polynomial_size.0, self.decomp_base_log.0,
self.decomp_level_count.0, self.input_lwe_dimension.0, self.ciphertext_modulus, self.message_modulus_log.0,
self.grouping_factor.0,
)
}
}
impl<Scalar: UnsignedInteger> NamedParam for FftTestParams<Scalar> {
fn name(&self) -> String {
format!(
"PARAM_FFT_BOOTSTRAP_glwe_{}_poly_{}_decomp_base_log_{}_decomp_level_{}_lwe_dim_{}_ct_modulus_{}_lwe_std_dev_{}_glwe_std_dev_{}",
self.glwe_dimension.0, self.polynomial_size.0, self.pbs_base_log.0,
self.pbs_level.0,
self.lwe_dimension.0, self.ciphertext_modulus, self.lwe_modular_std_dev.0.to_string().replace('.', "-"),
self.glwe_modular_std_dev.0.to_string().replace('.', "-"),
)
}
}
impl<Scalar: UnsignedInteger> NamedParam for FftWopPbsTestParams<Scalar> {
fn name(&self) -> String {
format!(
"PARAM_FFT_WOPBS_BOOTSTRAP_glwe_{}_poly_{}_decomp_base_log_{}_decomp_level_{}_lwe_dim_{}_ct_modulus_{}_pfks_level_{}_pfks_base_log_{}_cbs_level_{}_cbs_base_log_{}",
self.glwe_dimension.0, self.polynomial_size.0, self.pbs_base_log.0,
self.pbs_level.0,
self.lwe_dimension.0, self.ciphertext_modulus, self.pfks_level.0, self.pfks_base_log.0,
self.cbs_level.0, self.cbs_base_log.0,
)
}
}
impl<Scalar: UnsignedInteger> NamedParam for PackingKeySwitchTestParams<Scalar> {
fn name(&self) -> String {
format!(
"PARAM_PKS_glwe_{}_poly_{}_decomp_base_log_{}_decomp_level_{}_lwe_dim_{}_ct_modulus_{}_lwe_std_dev_{}_glwe_std_dev_{}",
self.glwe_dimension.0, self.polynomial_size.0, self.pbs_base_log.0,
self.pbs_level.0,
self.lwe_dimension.0, self.ciphertext_modulus, self.lwe_modular_std_dev.0.to_string().replace('.', "-"),
self.glwe_modular_std_dev.0.to_string().replace('.', "-"),
)
}
}

View File

@@ -86,70 +86,89 @@ pub trait FourierBootstrapKey<Scalar: UnsignedInteger> {
#[cfg(test)]
pub mod tests {
pub(crate) use crate::core_crypto::algorithms::test::gen_keys_or_get_from_cache_if_enabled;
use crate::core_crypto::algorithms::test::{FftBootstrapKeys, FftTestParams, TestResources};
use crate::core_crypto::commons::numeric::Numeric;
use crate::core_crypto::fft_impl::common::FourierBootstrapKey;
use crate::core_crypto::keycache::KeyCacheAccess;
use crate::core_crypto::prelude::*;
use dyn_stack::{GlobalPodBuffer, PodStack};
use serde::de::DeserializeOwned;
use serde::Serialize;
pub fn test_bootstrap_generic<
Scalar: Numeric + UnsignedTorus + CastFrom<usize> + CastInto<usize> + Send + Sync,
K: FourierBootstrapKey<Scalar>,
pub fn generate_keys<
Scalar: UnsignedTorus
+ Sync
+ Send
+ CastFrom<usize>
+ CastInto<usize>
+ Serialize
+ DeserializeOwned,
>(
lwe_modular_std_dev: StandardDev,
glwe_modular_std_dev: StandardDev,
) {
// DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
// computations
// Define the parameters for a 4 bits message able to hold the doubled 2 bits message
let small_lwe_dimension = LweDimension(742);
let glwe_dimension = GlweDimension(1);
let polynomial_size = PolynomialSize(2048);
let pbs_base_log = DecompositionBaseLog(23);
let pbs_level = DecompositionLevelCount(1);
let ciphertext_modulus = CiphertextModulus::new_native();
// Request the best seeder possible, starting with hardware entropy sources and falling back
// to /dev/random on Unix systems if enabled via cargo features
let mut boxed_seeder = new_seeder();
// Get a mutable reference to the seeder as a trait object from the Box returned by
// new_seeder
let seeder = boxed_seeder.as_mut();
// Create a generator which uses a CSPRNG to generate secret keys
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
// Create a generator which uses two CSPRNGs to generate public masks and secret encryption
// noise
let mut encryption_generator =
EncryptionRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed(), seeder);
println!("Generating keys...");
params: FftTestParams<Scalar>,
rsc: &mut TestResources,
) -> FftBootstrapKeys<Scalar> {
// Generate an LweSecretKey with binary coefficients
let small_lwe_sk =
LweSecretKey::generate_new_binary(small_lwe_dimension, &mut secret_generator);
let small_lwe_sk = LweSecretKey::generate_new_binary(
params.lwe_dimension,
&mut rsc.secret_random_generator,
);
// Generate a GlweSecretKey with binary coefficients
let glwe_sk = GlweSecretKey::generate_new_binary(
glwe_dimension,
polynomial_size,
&mut secret_generator,
params.glwe_dimension,
params.polynomial_size,
&mut rsc.secret_random_generator,
);
// Create a copy of the GlweSecretKey re-interpreted as an LweSecretKey
let big_lwe_sk = glwe_sk.clone().into_lwe_secret_key();
let std_bootstrapping_key = par_allocate_and_generate_new_lwe_bootstrap_key(
let bsk = par_allocate_and_generate_new_lwe_bootstrap_key(
&small_lwe_sk,
&glwe_sk,
pbs_base_log,
pbs_level,
glwe_modular_std_dev,
ciphertext_modulus,
&mut encryption_generator,
params.pbs_base_log,
params.pbs_level,
params.glwe_modular_std_dev,
params.ciphertext_modulus,
&mut rsc.encryption_random_generator,
);
FftBootstrapKeys {
small_lwe_sk,
big_lwe_sk,
bsk,
}
}
pub fn test_bootstrap_generic<Scalar, K>(params: FftTestParams<Scalar>)
where
Scalar: Numeric
+ UnsignedTorus
+ CastFrom<usize>
+ CastInto<usize>
+ Send
+ Sync
+ Serialize
+ DeserializeOwned,
K: FourierBootstrapKey<Scalar>,
FftTestParams<Scalar>: KeyCacheAccess<Keys = FftBootstrapKeys<Scalar>>,
{
let lwe_modular_std_dev = params.lwe_modular_std_dev;
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let ciphertext_modulus = params.ciphertext_modulus;
let mut rsc = TestResources::new();
let fft = K::new_fft(polynomial_size);
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (std_bootstrapping_key, small_lwe_sk, big_lwe_sk) =
(keys.bsk, keys.small_lwe_sk, keys.big_lwe_sk);
// Create the empty bootstrapping key in the Fourier domain
let mut fourier_bsk = K::new(
std_bootstrapping_key.input_lwe_dimension(),
@@ -159,7 +178,6 @@ pub mod tests {
std_bootstrapping_key.decomposition_level_count(),
);
let fft = K::new_fft(polynomial_size);
fourier_bsk.fill_with_forward_fourier(
&std_bootstrapping_key,
&fft,
@@ -186,7 +204,7 @@ pub mod tests {
plaintext,
lwe_modular_std_dev,
ciphertext_modulus,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
// Now we will use a PBS to compute a multiplication by 2, it is NOT the recommended way of

View File

@@ -1,31 +1,18 @@
use crate::core_crypto::fft_impl::common::tests::test_bootstrap_generic;
use crate::core_crypto::fft_impl::fft128::crypto::bootstrap::Fourier128LweBootstrapKeyOwned;
use crate::core_crypto::prelude::*;
fn sqr(x: f64) -> f64 {
x * x
}
use crate::core_crypto::prelude::test::{FFT_U128_PARAMS, FFT_U32_PARAMS, FFT_U64_PARAMS};
#[test]
fn test_bootstrap_u128() {
test_bootstrap_generic::<u128, Fourier128LweBootstrapKeyOwned>(
StandardDev(sqr(0.000007069849454709433)),
StandardDev(sqr(0.00000000000000029403601535432533)),
);
test_bootstrap_generic::<u128, Fourier128LweBootstrapKeyOwned>(FFT_U128_PARAMS);
}
#[test]
fn test_bootstrap_u64() {
test_bootstrap_generic::<u64, Fourier128LweBootstrapKeyOwned>(
StandardDev(sqr(0.000007069849454709433)),
StandardDev(sqr(0.00000000000000029403601535432533)),
);
test_bootstrap_generic::<u64, Fourier128LweBootstrapKeyOwned>(FFT_U64_PARAMS);
}
#[test]
fn test_bootstrap_u32() {
test_bootstrap_generic::<u32, Fourier128LweBootstrapKeyOwned>(
StandardDev(sqr(0.000007069849454709433)),
StandardDev(sqr(0.00000000000000029403601535432533)),
);
test_bootstrap_generic::<u32, Fourier128LweBootstrapKeyOwned>(FFT_U32_PARAMS);
}

View File

@@ -2,24 +2,24 @@ use dyn_stack::{GlobalPodBuffer, PodStack, ReborrowMut};
use super::super::super::{fft128, fft128_u128};
use super::super::math::fft::{Fft128, Fft128View};
use crate::core_crypto::fft_impl::common::tests::{
gen_keys_or_get_from_cache_if_enabled, generate_keys,
};
use crate::core_crypto::prelude::test::{TestResources, FFT128_U128_PARAMS};
use crate::core_crypto::prelude::*;
use aligned_vec::CACHELINE_ALIGN;
fn sqr(x: f64) -> f64 {
x * x
}
#[test]
fn test_split_external_product() {
let small_lwe_dimension = LweDimension(742);
let glwe_dimension = GlweDimension(1);
let polynomial_size = PolynomialSize(2048);
let pbs_base_log = DecompositionBaseLog(23);
let pbs_level = DecompositionLevelCount(1);
let glwe_modular_std_dev = StandardDev(sqr(0.00000000000000029403601535432533));
let ciphertext_modulus = CiphertextModulus::<u128>::new_native();
let params = FFT128_U128_PARAMS;
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let ciphertext_modulus = params.ciphertext_modulus;
let ciphertext_modulus_split = CiphertextModulus::<u64>::new_native();
let mut rsc = TestResources::new();
let mut glwe = GlweCiphertext::new(
0u128,
glwe_dimension.to_glwe_size(),
@@ -31,27 +31,9 @@ fn test_split_external_product() {
*x = rand::random();
}
let mut boxed_seeder = new_seeder();
let seeder = boxed_seeder.as_mut();
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
let mut encryption_generator =
EncryptionRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed(), seeder);
let small_lwe_sk =
LweSecretKey::generate_new_binary(small_lwe_dimension, &mut secret_generator);
let glwe_sk =
GlweSecretKey::generate_new_binary(glwe_dimension, polynomial_size, &mut secret_generator);
let std_bootstrapping_key = par_allocate_and_generate_new_lwe_bootstrap_key(
&small_lwe_sk,
&glwe_sk,
pbs_base_log,
pbs_level,
glwe_modular_std_dev,
ciphertext_modulus,
&mut encryption_generator,
);
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let std_bootstrapping_key = keys.bsk;
let mut fourier_bsk = Fourier128LweBootstrapKey::new(
std_bootstrapping_key.input_lwe_dimension(),
@@ -154,35 +136,18 @@ fn test_split_external_product() {
#[test]
fn test_split_pbs() {
let small_lwe_dimension = LweDimension(742);
let glwe_dimension = GlweDimension(1);
let polynomial_size = PolynomialSize(2048);
let pbs_base_log = DecompositionBaseLog(23);
let pbs_level = DecompositionLevelCount(1);
let glwe_modular_std_dev = StandardDev(sqr(0.00000000000000029403601535432533));
let ciphertext_modulus = CiphertextModulus::<u128>::new_native();
let params = FFT128_U128_PARAMS;
let mut boxed_seeder = new_seeder();
let seeder = boxed_seeder.as_mut();
let mut secret_generator =
SecretRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed());
let mut encryption_generator =
EncryptionRandomGenerator::<ActivatedRandomGenerator>::new(seeder.seed(), seeder);
let small_lwe_dimension = params.lwe_dimension;
let glwe_dimension = params.glwe_dimension;
let polynomial_size = params.polynomial_size;
let ciphertext_modulus = params.ciphertext_modulus;
let small_lwe_sk =
LweSecretKey::generate_new_binary(small_lwe_dimension, &mut secret_generator);
let glwe_sk =
GlweSecretKey::generate_new_binary(glwe_dimension, polynomial_size, &mut secret_generator);
let mut rsc = TestResources::new();
let std_bootstrapping_key = par_allocate_and_generate_new_lwe_bootstrap_key(
&small_lwe_sk,
&glwe_sk,
pbs_base_log,
pbs_level,
glwe_modular_std_dev,
ciphertext_modulus,
&mut encryption_generator,
);
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let std_bootstrapping_key = keys.bsk;
let mut fourier_bsk = Fourier128LweBootstrapKey::new(
std_bootstrapping_key.input_lwe_dimension(),

View File

@@ -1,19 +1,13 @@
use crate::core_crypto::fft_impl::common::tests::test_bootstrap_generic;
use crate::core_crypto::fft_impl::fft64::crypto::bootstrap::FourierLweBootstrapKeyOwned;
use crate::core_crypto::prelude::*;
use crate::core_crypto::prelude::test::{FFT_U32_PARAMS, FFT_U64_PARAMS};
#[test]
fn test_bootstrap_u64() {
test_bootstrap_generic::<u64, FourierLweBootstrapKeyOwned>(
StandardDev(0.000007069849454709433),
StandardDev(0.00000000000000029403601535432533),
);
test_bootstrap_generic::<u64, FourierLweBootstrapKeyOwned>(FFT_U64_PARAMS);
}
#[test]
fn test_bootstrap_u32() {
test_bootstrap_generic::<u32, FourierLweBootstrapKeyOwned>(
StandardDev(0.000007069849454709433),
StandardDev(0.00000000000000029403601535432533),
);
test_bootstrap_generic::<u32, FourierLweBootstrapKeyOwned>(FFT_U32_PARAMS);
}

View File

@@ -892,4 +892,4 @@ pub fn blind_rotate_assign<Scalar: UnsignedTorus + CastInto<usize>>(
}
#[cfg(test)]
mod tests;
pub mod tests;

View File

@@ -1,21 +1,100 @@
use super::*;
use crate::core_crypto::algorithms::slice_algorithms::*;
use crate::core_crypto::commons::dispersion::{LogStandardDev, StandardDev};
use crate::core_crypto::commons::generators::{EncryptionRandomGenerator, SecretRandomGenerator};
use crate::core_crypto::algorithms::test::{FftWopPbsKeys, FftWopPbsTestParams};
use crate::core_crypto::commons::dispersion::LogStandardDev;
use crate::core_crypto::commons::math::decomposition::SignedDecomposer;
use crate::core_crypto::commons::parameters::{
DecompositionBaseLog, DecompositionLevelCount, DeltaLog, ExtractedBitsCount, GlweDimension,
LweDimension, PlaintextCount, PolynomialCount, PolynomialSize,
};
use crate::core_crypto::commons::test_tools;
use crate::core_crypto::fft_impl::common::tests::gen_keys_or_get_from_cache_if_enabled;
use crate::core_crypto::fft_impl::fft64::crypto::bootstrap::{
fill_with_forward_fourier_scratch, FourierLweBootstrapKey,
};
use crate::core_crypto::fft_impl::fft64::math::fft::Fft;
use crate::core_crypto::seeders::new_seeder;
use concrete_csprng::generators::SoftwareRandomGenerator;
use crate::core_crypto::prelude::test::{
TestResources, FFT_WOPBS_N1024_PARAMS, FFT_WOPBS_N2048_PARAMS, FFT_WOPBS_N512_PARAMS,
FFT_WOPBS_PARAMS,
};
use concrete_fft::c64;
use dyn_stack::{GlobalPodBuffer, PodStack, ReborrowMut, StackReq};
use serde::de::DeserializeOwned;
use serde::Serialize;
#[cfg(not(feature = "__coverage"))]
// Tests take about 2-3 seconds on a laptop with this number
const NB_TESTS: usize = 32;
#[cfg(not(feature = "__coverage"))]
const NB_TESTS_LIGHT: usize = 10;
#[cfg(feature = "__coverage")]
const NB_TESTS: usize = 1;
#[cfg(feature = "__coverage")]
const NB_TESTS_LIGHT: usize = 1;
pub fn generate_keys<
Scalar: UnsignedTorus + Sync + Send + CastFrom<usize> + CastInto<usize> + Serialize + DeserializeOwned,
>(
params: FftWopPbsTestParams<Scalar>,
rsc: &mut TestResources,
) -> FftWopPbsKeys<Scalar> {
//create GLWE and LWE secret key
let glwe_sk = allocate_and_generate_new_binary_glwe_secret_key(
params.glwe_dimension,
params.polynomial_size,
&mut rsc.secret_random_generator,
);
let small_lwe_sk = allocate_and_generate_new_binary_lwe_secret_key(
params.lwe_dimension,
&mut rsc.secret_random_generator,
);
let big_lwe_sk = glwe_sk.clone().into_lwe_secret_key();
// allocation and generation of the key in coef domain:
let std_bsk = allocate_and_generate_new_lwe_bootstrap_key(
&small_lwe_sk,
&glwe_sk,
params.pbs_base_log,
params.pbs_level,
params.lwe_modular_std_dev,
params.ciphertext_modulus,
&mut rsc.encryption_random_generator,
);
// allocation for the bootstrapping key
let mut fourier_bsk = FourierLweBootstrapKey::new(
params.lwe_dimension,
params.glwe_dimension.to_glwe_size(),
params.polynomial_size,
params.pbs_base_log,
params.pbs_level,
);
let fft = Fft::new(params.polynomial_size);
let fft = fft.as_view();
fourier_bsk
.as_mut_view()
.par_fill_with_forward_fourier(std_bsk.as_view(), fft);
// Creation of all the pfksk for the circuit bootstrapping
let vec_pfpksk = par_allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list(
&big_lwe_sk,
&glwe_sk,
params.pfks_base_log,
params.pfks_level,
params.lwe_modular_std_dev,
params.ciphertext_modulus,
&mut rsc.encryption_random_generator,
);
FftWopPbsKeys {
small_lwe_sk,
big_lwe_sk,
fbsk: fourier_bsk,
lwe_pfpksk: vec_pfpksk,
}
}
// Extract all the bits of a LWE
#[test]
@@ -36,24 +115,19 @@ pub fn test_extract_bits() {
let ciphertext_modulus = CiphertextModulus::new_native();
let number_of_bits_of_message_including_padding = 5_usize;
// Tests take about 2-3 seconds on a laptop with this number
let number_of_test_runs = 32;
let mut seeder = new_seeder();
let seeder = seeder.as_mut();
let mut secret_generator = SecretRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed());
let mut encryption_generator =
EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed(), seeder);
let mut rsc = TestResources::new();
// allocation and generation of the key in coef domain:
let glwe_sk: GlweSecretKeyOwned<u64> = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut secret_generator,
&mut rsc.secret_random_generator,
);
let lwe_small_sk: LweSecretKeyOwned<u64> = allocate_and_generate_new_binary_lwe_secret_key(
small_lwe_dimension,
&mut rsc.secret_random_generator,
);
let lwe_small_sk: LweSecretKeyOwned<u64> =
allocate_and_generate_new_binary_lwe_secret_key(small_lwe_dimension, &mut secret_generator);
let std_bsk: LweBootstrapKeyOwned<u64> = allocate_and_generate_new_lwe_bootstrap_key(
&lwe_small_sk,
@@ -62,7 +136,7 @@ pub fn test_extract_bits() {
level_bsk,
std,
ciphertext_modulus,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
let mut fourier_bsk = FourierLweBootstrapKey::new(
@@ -85,7 +159,7 @@ pub fn test_extract_bits() {
level_ksk,
std,
ciphertext_modulus,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
let input_lwe_dimension = lwe_big_sk.lwe_dimension();
@@ -116,7 +190,7 @@ pub fn test_extract_bits() {
////////////////////////////////////////////////////////////////////////////////////////////////
for _ in 0..number_of_test_runs {
for _ in 0..NB_TESTS {
// Generate a random plaintext in [0; 2^{number_of_bits_of_message_including_padding}[
let val = test_tools::random_uint_between(
0..2u64.pow(number_of_bits_of_message_including_padding as u32),
@@ -135,7 +209,7 @@ pub fn test_extract_bits() {
&mut lwe_in,
message,
std,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
// Bit extraction
@@ -202,21 +276,18 @@ fn test_circuit_bootstrapping_binary() {
let ciphertext_modulus = CiphertextModulus::new_native();
let mut seeder = new_seeder();
let seeder = seeder.as_mut();
let mut secret_generator = SecretRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed());
let mut encryption_generator =
EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed(), seeder);
let mut rsc = TestResources::new();
// Create GLWE and LWE secret key
let glwe_sk: GlweSecretKeyOwned<u64> = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut secret_generator,
&mut rsc.secret_random_generator,
);
let lwe_sk: LweSecretKeyOwned<u64> = allocate_and_generate_new_binary_lwe_secret_key(
small_lwe_dimension,
&mut rsc.secret_random_generator,
);
let lwe_sk: LweSecretKeyOwned<u64> =
allocate_and_generate_new_binary_lwe_secret_key(small_lwe_dimension, &mut secret_generator);
// Allocation and generation of the bootstrap key in standard domain:
let std_bsk: LweBootstrapKeyOwned<u64> = allocate_and_generate_new_lwe_bootstrap_key(
@@ -226,7 +297,7 @@ fn test_circuit_bootstrapping_binary() {
level_bsk,
std,
ciphertext_modulus,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
let mut fourier_bsk = FourierLweBootstrapKey::new(
@@ -254,14 +325,12 @@ fn test_circuit_bootstrapping_binary() {
level_pksk,
std,
ciphertext_modulus,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
let delta_log = DeltaLog(60);
let number_of_test_runs = 32;
for _ in 0..number_of_test_runs {
for _ in 0..NB_TESTS {
// value is 0 or 1 as CBS works on messages expected to contain 1 bit of information
let value: u64 = test_tools::random_uint_between(0..2u64);
// Encryption of an LWE with the value 'message'
@@ -273,7 +342,7 @@ fn test_circuit_bootstrapping_binary() {
&mut lwe_in,
message,
std,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
let mut cbs_res = GgswCiphertextOwned::new(
@@ -386,12 +455,6 @@ fn test_circuit_bootstrapping_binary() {
#[test]
pub fn test_cmux_tree() {
// Define settings for an insecure toy example
let mut seeder = new_seeder();
let seeder = seeder.as_mut();
let mut secret_generator = SecretRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed());
let mut encryption_generator =
EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed(), seeder);
let polynomial_size = PolynomialSize(512);
let glwe_dimension = GlweDimension(1);
let std = LogStandardDev::from_log_standard_dev(-60.);
@@ -403,11 +466,13 @@ pub fn test_cmux_tree() {
let nb_ggsw = 10;
let delta_log = 60;
let mut rsc = TestResources::new();
// Allocation and generation of the key in coef domain:
let glwe_sk: GlweSecretKeyOwned<u64> = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut secret_generator,
&mut rsc.secret_random_generator,
);
let glwe_size = glwe_sk.glwe_dimension().to_glwe_size();
@@ -428,9 +493,7 @@ pub fn test_cmux_tree() {
// Decomposer to manage the rounding after decrypting
let decomposer = SignedDecomposer::new(DecompositionBaseLog(4), DecompositionLevelCount(1));
let number_of_test_runs = 32;
for _ in 0..number_of_test_runs {
for _ in 0..NB_TESTS {
let mut value =
test_tools::random_uint_between(0..2u64.pow(number_of_bits_for_payload as u32));
println!("value: {value}");
@@ -478,7 +541,7 @@ pub fn test_cmux_tree() {
&mut ggsw,
single_bit_msg,
std,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
let mut mem = GlobalPodBuffer::new(fill_with_forward_fourier_scratch(fft).unwrap());
@@ -517,83 +580,35 @@ pub fn test_cmux_tree() {
}
}
// Circuit bootstrap + vecrtical packing applying an identity lut
// Circuit bootstrap + vertical packing applying an identity lut
#[test]
pub fn test_extract_bit_circuit_bootstrapping_vertical_packing() {
// define settings
let polynomial_size = PolynomialSize(1024);
let glwe_dimension = GlweDimension(1);
let small_lwe_dimension = LweDimension(481);
let level_bsk = DecompositionLevelCount(9);
let base_log_bsk = DecompositionBaseLog(4);
let level_pksk = DecompositionLevelCount(9);
let base_log_pksk = DecompositionBaseLog(4);
let params = FFT_WOPBS_PARAMS;
let polynomial_size = params.polynomial_size;
let glwe_dimension = params.glwe_dimension;
let ciphertext_modulus = params.ciphertext_modulus;
let level_cbs = params.cbs_level;
let base_log_cbs = params.cbs_base_log;
let level_ksk = DecompositionLevelCount(9);
let base_log_ksk = DecompositionBaseLog(1);
let std_big = params.glwe_modular_std_dev;
let level_cbs = DecompositionLevelCount(4);
let base_log_cbs = DecompositionBaseLog(6);
let ciphertext_modulus = CiphertextModulus::new_native();
// Value was 0.000_000_000_000_000_221_486_881_160_055_68_513645324585951
// But rust indicates it gets truncated anyways to
// 0.000_000_000_000_000_221_486_881_160_055_68
let std_small = StandardDev::from_standard_dev(0.000_000_000_000_000_221_486_881_160_055_68);
// Value was 0.000_061_200_133_780_220_371_345
// But rust indicates it gets truncated anyways to
// 0.000_061_200_133_780_220_36
let std_big = StandardDev::from_standard_dev(0.000_061_200_133_780_220_36);
let mut seeder = new_seeder();
let seeder = seeder.as_mut();
let mut secret_generator = SecretRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed());
let mut encryption_generator =
EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed(), seeder);
//create GLWE and LWE secret key
let glwe_sk: GlweSecretKeyOwned<u64> = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dimension,
polynomial_size,
&mut secret_generator,
);
let lwe_small_sk: LweSecretKeyOwned<u64> =
allocate_and_generate_new_binary_lwe_secret_key(small_lwe_dimension, &mut secret_generator);
let lwe_big_sk = glwe_sk.clone().into_lwe_secret_key();
let input_lwe_dimension = lwe_big_sk.lwe_dimension();
// allocation and generation of the key in coef domain:
let std_bsk: LweBootstrapKeyOwned<u64> = allocate_and_generate_new_lwe_bootstrap_key(
&lwe_small_sk,
&glwe_sk,
base_log_bsk,
level_bsk,
std_small,
ciphertext_modulus,
&mut encryption_generator,
);
// allocation for the bootstrapping key
let mut fourier_bsk = FourierLweBootstrapKey::new(
small_lwe_dimension,
glwe_dimension.to_glwe_size(),
polynomial_size,
base_log_bsk,
level_bsk,
);
let mut rsc = TestResources::new();
let fft = Fft::new(polynomial_size);
let fft = fft.as_view();
fourier_bsk
.as_mut_view()
.par_fill_with_forward_fourier(std_bsk.as_view(), fft);
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (fourier_bsk, lwe_small_sk, lwe_big_sk, vec_pfpksk) = (
keys.fbsk,
keys.small_lwe_sk,
keys.big_lwe_sk,
keys.lwe_pfpksk,
);
let input_lwe_dimension = lwe_big_sk.lwe_dimension();
let ksk_lwe_big_to_small: LweKeyswitchKeyOwned<u64> =
allocate_and_generate_new_lwe_keyswitch_key(
@@ -603,20 +618,9 @@ pub fn test_extract_bit_circuit_bootstrapping_vertical_packing() {
level_ksk,
std_big,
ciphertext_modulus,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
// Creation of all the pfksk for the circuit bootstrapping
let vec_pfpksk = par_allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list(
&lwe_big_sk,
&glwe_sk,
base_log_pksk,
level_pksk,
std_small,
ciphertext_modulus,
&mut encryption_generator,
);
let number_of_bits_in_input_lwe = 10;
let number_of_values_to_extract = ExtractedBitsCount(number_of_bits_in_input_lwe);
@@ -627,9 +631,7 @@ pub fn test_extract_bit_circuit_bootstrapping_vertical_packing() {
let delta_log = DeltaLog(64 - number_of_values_to_extract.0);
let delta_lut = DeltaLog(64 - number_of_values_to_extract.0);
let number_of_test_runs = 10;
for run_number in 0..number_of_test_runs {
for run_number in 0..NB_TESTS_LIGHT {
let cleartext =
test_tools::random_uint_between(0..2u64.pow(number_of_bits_in_input_lwe as u32));
@@ -649,7 +651,7 @@ pub fn test_extract_bit_circuit_bootstrapping_vertical_packing() {
&mut lwe_in,
message,
std_big,
&mut encryption_generator,
&mut rsc.encryption_random_generator,
);
let mut extracted_bits_lwe_list = LweCiphertextListOwned::new(
@@ -762,8 +764,7 @@ pub fn test_extract_bit_circuit_bootstrapping_vertical_packing() {
let result_ct = vertical_packing_lwe_list_out.iter().next().unwrap();
// decrypt result
let lwe_sk = glwe_sk.clone().into_lwe_secret_key();
let decrypted_message = decrypt_lwe_ciphertext(&lwe_sk, &result_ct);
let decrypted_message = decrypt_lwe_ciphertext(&lwe_big_sk, &result_ct);
let decoded_message = decomposer.closest_representable(decrypted_message.0) >> delta_log.0;
// print information if the result is wrong
@@ -776,83 +777,42 @@ pub fn test_extract_bit_circuit_bootstrapping_vertical_packing() {
}
}
fn test_wop_add_one(polynomial_size: PolynomialSize) {
// DISCLAIMER: these are toy parameters and are not guaranteed to be secure
let glwe_dim = GlweDimension(1);
let small_dim = LweDimension(4);
let level_bsk = DecompositionLevelCount(4);
let base_log_bsk = DecompositionBaseLog(9);
let level_pksk = DecompositionLevelCount(2);
let base_log_pksk = DecompositionBaseLog(15);
let level_cbs = DecompositionLevelCount(4);
let base_log_cbs = DecompositionBaseLog(6);
let ciphertext_modulus = CiphertextModulus::new_native();
let variance = crate::core_crypto::commons::dispersion::Variance(0.0);
fn test_wop_add_one(params: FftWopPbsTestParams<u64>) {
let polynomial_size = params.polynomial_size;
let small_dim = params.lwe_dimension;
let level_cbs = params.cbs_level;
let base_log_cbs = params.cbs_base_log;
let ciphertext_modulus = params.ciphertext_modulus;
let std_small = params.lwe_modular_std_dev;
let mut seeder = new_seeder();
let seeder = seeder.as_mut();
let mut secret_generator = SecretRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed());
let mut encryption_generator =
EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(seeder.seed(), seeder);
let small_sk =
allocate_and_generate_new_binary_lwe_secret_key::<u64, _>(small_dim, &mut secret_generator);
let big_sk = allocate_and_generate_new_binary_glwe_secret_key(
glwe_dim,
polynomial_size,
&mut secret_generator,
);
let big_lwe_sk = big_sk.clone().into_lwe_secret_key();
// allocation and generation of the key in coef domain:
let std_bsk: LweBootstrapKeyOwned<u64> = allocate_and_generate_new_lwe_bootstrap_key(
&small_sk,
&big_sk,
base_log_bsk,
level_bsk,
variance,
ciphertext_modulus,
&mut encryption_generator,
);
// allocation for the bootstrapping key
let mut fourier_bsk = FourierLweBootstrapKey::new(
small_dim,
glwe_dim.to_glwe_size(),
polynomial_size,
base_log_bsk,
level_bsk,
);
let mut rsc = TestResources::new();
let fft = Fft::new(polynomial_size);
let fft = fft.as_view();
fourier_bsk
.as_mut_view()
.par_fill_with_forward_fourier(std_bsk.as_view(), fft);
// Creation of all the pfksk for the circuit bootstrapping
let cbs_pfpksk = par_allocate_and_generate_new_circuit_bootstrap_lwe_pfpksk_list(
&big_lwe_sk,
&big_sk,
base_log_pksk,
level_pksk,
variance,
ciphertext_modulus,
&mut encryption_generator,
let mut keys_gen = |params| generate_keys(params, &mut rsc);
let keys = gen_keys_or_get_from_cache_if_enabled(params, &mut keys_gen);
let (fourier_bsk, small_sk, big_lwe_sk, cbs_pfpksk) = (
keys.fbsk,
keys.small_lwe_sk,
keys.big_lwe_sk,
keys.lwe_pfpksk,
);
// We are going to encrypt 10 bits
let number_of_input_bits: usize = 10;
#[cfg(not(feature = "__coverage"))]
const SIZE: usize = 10;
#[cfg(feature = "__coverage")]
const SIZE: usize = 1;
// Test on 610, binary representation 10011 00010
let mut vals = [0u64; 10];
let mut vals = [0u64; SIZE];
vals[0] = 610;
// Use our generator to have more random values
encryption_generator.fill_slice_with_random_mask(&mut vals[1..]);
rsc.encryption_random_generator
.fill_slice_with_random_mask(&mut vals[1..]);
// Apply our modulus to be sure we can represent the test values
vals.iter_mut()
.for_each(|x| *x %= 1 << number_of_input_bits);
@@ -871,8 +831,8 @@ fn test_wop_add_one(polynomial_size: PolynomialSize) {
&small_sk,
&mut extracted_bits.get_mut(number_of_input_bits - i - 1),
Plaintext(((val >> i) & 1) << 63),
variance,
&mut encryption_generator,
std_small,
&mut rsc.encryption_random_generator,
)
}
@@ -957,17 +917,17 @@ fn test_wop_add_one(polynomial_size: PolynomialSize) {
//CMUX tree
#[test]
fn test_wop_add_one_cmux_tree() {
test_wop_add_one(PolynomialSize(512))
test_wop_add_one(FFT_WOPBS_N512_PARAMS)
}
//No CMUX tree
#[test]
fn test_wop_add_one_no_cmux_tree() {
test_wop_add_one(PolynomialSize(1024))
test_wop_add_one(FFT_WOPBS_N1024_PARAMS)
}
//Expanded lut
#[test]
fn test_wop_add_one_expanded_lut() {
test_wop_add_one(PolynomialSize(2048))
test_wop_add_one(FFT_WOPBS_N2048_PARAMS)
}

View File

@@ -0,0 +1,273 @@
use crate::core_crypto::algorithms::test::{
ClassicBootstrapKeys, ClassicTestParams, FftBootstrapKeys, FftTestParams, FftWopPbsKeys,
FftWopPbsTestParams, MultiBitBootstrapKeys, MultiBitTestParams, PackingKeySwitchKeys,
PackingKeySwitchTestParams,
};
use crate::keycache::*;
use lazy_static::*;
use serde::de::DeserializeOwned;
use serde::Serialize;
#[cfg(feature = "internal-keycache")]
use std::fmt::Debug;
pub struct KeyCacheCoreImpl<P, K>
where
P: Copy + NamedParam + DeserializeOwned + Serialize + PartialEq,
K: DeserializeOwned + Serialize,
{
inner: ImplKeyCache<P, K, FileStorage>,
}
impl<
P: Copy + NamedParam + DeserializeOwned + Serialize + PartialEq,
K: DeserializeOwned + Serialize,
> Default for KeyCacheCoreImpl<P, K>
{
fn default() -> Self {
Self {
inner: ImplKeyCache::new(FileStorage::new(
"../keys/core_crypto/bootstrap".to_string(),
)),
}
}
}
impl<P, K> KeyCacheCoreImpl<P, K>
where
P: Copy + NamedParam + DeserializeOwned + Serialize + PartialEq,
K: DeserializeOwned + Serialize + Clone,
{
pub fn get_key_with_closure<C>(&self, params: P, mut c: C) -> K
where
C: FnMut(P) -> K,
{
(*self.inner.get_with_closure(params, &mut c)).clone()
}
pub fn clear_in_memory_cache(&self) {
self.inner.clear_in_memory_cache();
}
}
#[derive(Default)]
pub struct KeyCache {
u32_multi_bit_cache: KeyCacheCoreImpl<MultiBitTestParams<u32>, MultiBitBootstrapKeys<u32>>,
u64_multi_bit_cache: KeyCacheCoreImpl<MultiBitTestParams<u64>, MultiBitBootstrapKeys<u64>>,
u32_classic_cache: KeyCacheCoreImpl<ClassicTestParams<u32>, ClassicBootstrapKeys<u32>>,
u64_classic_cache: KeyCacheCoreImpl<ClassicTestParams<u64>, ClassicBootstrapKeys<u64>>,
u128_classic_cache: KeyCacheCoreImpl<ClassicTestParams<u128>, ClassicBootstrapKeys<u128>>,
u32_fft_cache: KeyCacheCoreImpl<FftTestParams<u32>, FftBootstrapKeys<u32>>,
u64_fft_cache: KeyCacheCoreImpl<FftTestParams<u64>, FftBootstrapKeys<u64>>,
u128_fft_cache: KeyCacheCoreImpl<FftTestParams<u128>, FftBootstrapKeys<u128>>,
u64_fft_wopbs_cache: KeyCacheCoreImpl<FftWopPbsTestParams<u64>, FftWopPbsKeys<u64>>,
u32_pksk_cache: KeyCacheCoreImpl<PackingKeySwitchTestParams<u32>, PackingKeySwitchKeys<u32>>,
u64_pksk_cache: KeyCacheCoreImpl<PackingKeySwitchTestParams<u64>, PackingKeySwitchKeys<u64>>,
}
impl KeyCache {
pub fn get_key_with_closure<C, P, K>(&self, params: P, c: C) -> K
where
C: FnMut(P) -> K,
P: KeyCacheAccess<Keys = K> + Serialize + DeserializeOwned + Copy + PartialEq + NamedParam,
K: DeserializeOwned + Serialize + Clone,
{
P::access(self).get_key_with_closure(params, c)
}
pub fn clear_in_memory_cache<P, K>(&self)
where
P: KeyCacheAccess<Keys = K> + Serialize + DeserializeOwned + Copy + PartialEq + NamedParam,
K: DeserializeOwned + Serialize + Clone,
{
P::access(self).clear_in_memory_cache();
}
}
pub trait KeyCacheAccess: Serialize + DeserializeOwned + Copy + PartialEq + NamedParam {
type Keys: DeserializeOwned + Serialize;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys>;
}
impl KeyCacheAccess for MultiBitTestParams<u32> {
type Keys = MultiBitBootstrapKeys<u32>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u32_multi_bit_cache
}
}
impl KeyCacheAccess for MultiBitTestParams<u64> {
type Keys = MultiBitBootstrapKeys<u64>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u64_multi_bit_cache
}
}
impl KeyCacheAccess for ClassicTestParams<u32> {
type Keys = ClassicBootstrapKeys<u32>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u32_classic_cache
}
}
impl KeyCacheAccess for ClassicTestParams<u64> {
type Keys = ClassicBootstrapKeys<u64>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u64_classic_cache
}
}
impl KeyCacheAccess for ClassicTestParams<u128> {
type Keys = ClassicBootstrapKeys<u128>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u128_classic_cache
}
}
impl KeyCacheAccess for FftTestParams<u32> {
type Keys = FftBootstrapKeys<u32>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u32_fft_cache
}
}
impl KeyCacheAccess for FftTestParams<u64> {
type Keys = FftBootstrapKeys<u64>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u64_fft_cache
}
}
impl KeyCacheAccess for FftTestParams<u128> {
type Keys = FftBootstrapKeys<u128>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u128_fft_cache
}
}
impl KeyCacheAccess for FftWopPbsTestParams<u64> {
type Keys = FftWopPbsKeys<u64>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u64_fft_wopbs_cache
}
}
impl KeyCacheAccess for PackingKeySwitchTestParams<u32> {
type Keys = PackingKeySwitchKeys<u32>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u32_pksk_cache
}
}
impl KeyCacheAccess for PackingKeySwitchTestParams<u64> {
type Keys = PackingKeySwitchKeys<u64>;
fn access(keycache: &KeyCache) -> &KeyCacheCoreImpl<Self, Self::Keys> {
&keycache.u64_pksk_cache
}
}
lazy_static! {
pub static ref KEY_CACHE: KeyCache = Default::default();
}
#[cfg(feature = "internal-keycache")]
#[test]
pub fn generate_keys() {
use crate::core_crypto::algorithms::test::{
lwe_multi_bit_programmable_bootstrapping, lwe_programmable_bootstrapping, TestResources,
DUMMY_31_U32, DUMMY_NATIVE_U32, FFT128_U128_PARAMS, FFT_U128_PARAMS, FFT_U32_PARAMS,
FFT_U64_PARAMS, FFT_WOPBS_N1024_PARAMS, FFT_WOPBS_N2048_PARAMS, FFT_WOPBS_N512_PARAMS,
FFT_WOPBS_PARAMS, MULTI_BIT_2_2_2_CUSTOM_MOD_PARAMS, MULTI_BIT_2_2_2_PARAMS,
MULTI_BIT_2_2_3_CUSTOM_MOD_PARAMS, MULTI_BIT_2_2_3_PARAMS, TEST_PARAMS_3_BITS_63_U64,
TEST_PARAMS_4_BITS_NATIVE_U64,
};
use crate::core_crypto::fft_impl;
use crate::core_crypto::fft_impl::fft64::crypto::wop_pbs;
fn generate_and_store<
P: Debug + KeyCacheAccess<Keys = K> + serde::Serialize + serde::de::DeserializeOwned,
K: serde::de::DeserializeOwned + serde::Serialize + Clone,
>(
params: P,
keygen_func: &mut dyn FnMut(P) -> K,
) {
println!("Generating : {}", params.name());
let start = std::time::Instant::now();
let _ = KEY_CACHE.get_key_with_closure(params, keygen_func);
let stop = start.elapsed().as_secs();
println!("Generation took {stop} seconds");
// Clear keys as we go to avoid filling the RAM
KEY_CACHE.clear_in_memory_cache::<P, K>()
}
let mut rsc = TestResources::new();
println!("Generating keys for core_crypto");
let classical_u32_params = vec![DUMMY_31_U32, DUMMY_NATIVE_U32];
for param in classical_u32_params.iter().copied() {
let mut keys_gen = |_| lwe_programmable_bootstrapping::generate_keys(param, &mut rsc);
generate_and_store(param, &mut keys_gen);
}
let multi_bit_params = [
MULTI_BIT_2_2_2_PARAMS,
MULTI_BIT_2_2_3_PARAMS,
MULTI_BIT_2_2_2_CUSTOM_MOD_PARAMS,
MULTI_BIT_2_2_3_CUSTOM_MOD_PARAMS,
];
for param in multi_bit_params.iter().copied() {
let mut keys_gen =
|_| lwe_multi_bit_programmable_bootstrapping::generate_keys(param, &mut rsc);
generate_and_store(param, &mut keys_gen);
}
let classical_u64_params = [TEST_PARAMS_4_BITS_NATIVE_U64, TEST_PARAMS_3_BITS_63_U64];
for param in classical_u64_params.iter().copied() {
let mut keys_gen = |_| lwe_programmable_bootstrapping::generate_keys(param, &mut rsc);
generate_and_store(param, &mut keys_gen);
}
generate_and_store(FFT_U32_PARAMS, &mut |_| {
fft_impl::common::tests::generate_keys(FFT_U32_PARAMS, &mut rsc)
});
generate_and_store(FFT_U64_PARAMS, &mut |_| {
fft_impl::common::tests::generate_keys(FFT_U64_PARAMS, &mut rsc)
});
generate_and_store(FFT_U128_PARAMS, &mut |_| {
fft_impl::common::tests::generate_keys(FFT_U128_PARAMS, &mut rsc)
});
generate_and_store(FFT128_U128_PARAMS, &mut |_| {
fft_impl::common::tests::generate_keys(FFT128_U128_PARAMS, &mut rsc)
});
generate_and_store(FFT_WOPBS_PARAMS, &mut |_| {
wop_pbs::tests::generate_keys(FFT_WOPBS_PARAMS, &mut rsc)
});
generate_and_store(FFT_WOPBS_N512_PARAMS, &mut |_| {
wop_pbs::tests::generate_keys(FFT_WOPBS_N512_PARAMS, &mut rsc)
});
generate_and_store(FFT_WOPBS_N1024_PARAMS, &mut |_| {
wop_pbs::tests::generate_keys(FFT_WOPBS_N1024_PARAMS, &mut rsc)
});
generate_and_store(FFT_WOPBS_N2048_PARAMS, &mut |_| {
wop_pbs::tests::generate_keys(FFT_WOPBS_N2048_PARAMS, &mut rsc)
});
}

View File

@@ -17,3 +17,6 @@ pub mod prelude;
pub mod seeders;
pub mod fft_impl;
#[cfg(test)]
pub mod keycache;

View File

@@ -155,12 +155,26 @@ pub mod utils {
K: From<P> + Clone,
{
pub fn get(&self, param: P) -> SharedKey<K> {
self.with_key(param, |k| k.clone())
self.get_with_closure(param, &mut K::from)
}
}
impl<P, K, S> KeyCache<P, K, S>
where
P: Copy + PartialEq + NamedParam,
S: PersistentStorage<P, K>,
{
pub fn get_with_closure<C: FnMut(P) -> K>(
&self,
param: P,
key_gen_closure: &mut C,
) -> SharedKey<K> {
self.with_closure(param, key_gen_closure)
}
pub fn with_key<F, R>(&self, param: P, f: F) -> R
pub fn with_closure<C>(&self, param: P, key_gen_closure: &mut C) -> SharedKey<K>
where
F: FnOnce(&SharedKey<K>) -> R,
C: FnMut(P) -> K,
{
let load_from_persistent_storage = || {
// we check if we can load the key from persistent storage
@@ -168,7 +182,7 @@ pub mod utils {
let maybe_key = persistent_storage.load(param);
maybe_key.map_or_else(
|| {
let key = K::from(param);
let key = key_gen_closure(param);
persistent_storage.store(param, &key);
key
},
@@ -176,42 +190,40 @@ pub mod utils {
)
};
let try_load_from_memory_and_init = || {
// we only hold a read lock for a short duration to find the key
let maybe_shared_cell = {
let memory_storage = self.memory_storage.read().unwrap();
memory_storage
.iter()
.find(|(p, _)| *p == param)
.map(|param_key| param_key.1.clone())
let try_load_from_memory_and_init = || -> Result<_, ()> {
let maybe_shared_key = {
let mut res = None;
let lock = &*self.memory_storage.read().unwrap();
for (p, key) in lock.iter() {
if *p == param {
res = Some(key.clone());
break;
}
}
res
};
if let Some(shared_cell) = maybe_shared_cell {
shared_cell.inner.get_or_init(load_from_persistent_storage);
Ok(shared_cell)
} else {
Err(())
}
maybe_shared_key.map_or_else(
|| {
let shared_key = SharedKey {
inner: Arc::new(OnceLock::new()),
};
shared_key.inner.get_or_init(load_from_persistent_storage);
{
// we only hold a write lock for a short duration to push the key
// if it doesn't already exists.
let mut memory_storage = self.memory_storage.write().unwrap();
if memory_storage.iter().all(|(p, _)| *p != param) {
memory_storage.push((param, shared_key.clone()));
}
}
Ok(shared_key)
},
Ok,
)
};
if let Ok(result) = try_load_from_memory_and_init() {
f(&result)
} else {
{
// we only hold a write lock for a short duration to push the lazily
// evaluated key without actually evaluating the key
let mut memory_storage = self.memory_storage.write().unwrap();
if !memory_storage.iter().any(|(p, _)| *p == param) {
memory_storage.push((
param,
SharedKey {
inner: Arc::new(OnceLock::new()),
},
));
}
}
f(&try_load_from_memory_and_init().ok().unwrap())
}
try_load_from_memory_and_init().ok().unwrap()
}
}
}

View File

@@ -392,15 +392,6 @@ where
}
}
impl From<WopbsParamPair> for WopbsKey {
fn from(params: WopbsParamPair) -> Self {
// use with_key to avoid doing a temporary cloning
KEY_CACHE.inner.with_key(params.0, |keys| {
Self::new_wopbs_key(&keys.0, &keys.1, &params.1)
})
}
}
impl NamedParam for WopbsParamPair {
fn name(&self) -> String {
self.1.name()
@@ -427,7 +418,9 @@ impl KeycacheWopbsV0 {
pub fn get_from_param<T: Into<WopbsParamPair>>(&self, params: T) -> SharedWopbsKey {
let params = params.into();
let key = KEY_CACHE.get_from_param(params.0);
let wk = self.inner.get(params);
let wk = self.inner.get_with_closure(params, &mut |_| {
WopbsKey::new_wopbs_key(&key.inner.0, &key.inner.1, &params.1)
});
SharedWopbsKey {
inner: key.inner,
wopbs: wk,
@@ -455,17 +448,6 @@ where
}
}
impl From<KeySwitchingKeyParams> for KeySwitchingKey {
fn from(params: KeySwitchingKeyParams) -> Self {
// use with_key to avoid doing a temporary cloning
KEY_CACHE.inner.with_key(params.0, |keys_1| {
KEY_CACHE.inner.with_key(params.1, |keys_2| {
Self::new((&keys_1.0, &keys_1.1), (&keys_2.0, &keys_2.1), params.2)
})
})
}
}
impl NamedParam for KeySwitchingKeyParams {
fn name(&self) -> String {
format!("{}__{}__{}", self.0.name(), self.1.name(), self.2.name())
@@ -496,7 +478,13 @@ impl KeycacheKeySwitchingKey {
let params = params.into();
let key_1 = KEY_CACHE.get_from_param(params.0);
let key_2 = KEY_CACHE.get_from_param(params.1);
let ksk = self.inner.get(params);
let ksk = self.inner.get_with_closure(params, &mut |_| {
KeySwitchingKey::new(
(key_1.client_key(), key_1.server_key()),
(key_2.client_key(), key_2.server_key()),
params.2,
)
});
SharedKeySwitchingKey {
inner_1: key_1.inner,
inner_2: key_2.inner,

View File

@@ -253,6 +253,7 @@ fn test_ct_scalar_op_assign_noise_level_propagation(sk: &ServerKey, ct: &Ciphert
});
}
#[cfg(not(feature = "__coverage"))] // This test is ignored in coverage, it takes around 4 hours to run otherwise.
#[test]
fn test_noise_level_propagation_ci_run_filter() {
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS;