mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
Examples, benchmarks, and minor changes for consistency, in BDD API
This commit is contained in:
@@ -25,4 +25,12 @@ paste = "1.0.15"
|
|||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "circuit_bootstrapping"
|
name = "circuit_bootstrapping"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "bdd_prepare"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "bdd_arithmetic"
|
||||||
harness = false
|
harness = false
|
||||||
@@ -9,7 +9,7 @@ See [./examples/circuit_bootstrapping.rs](./examples/circuit_bootstrapping.rs)
|
|||||||
## Available Schemes
|
## Available Schemes
|
||||||
|
|
||||||
- **BIN FHE**:
|
- **BIN FHE**:
|
||||||
- **bdd_arithmetic**: high level API for u32 arithmetic (u8 to u256 planned) using binary decision circuits. Also provides API for blind retrieval, blind rotation (using encpypted integers) and blind selection.
|
- **bdd_arithmetic**: high level API for u32 arithmetic (u8 to u256 planned) using binary decision circuits. Also provides API for blind retrieval, blind rotation (using encrypted integers) and blind selection.
|
||||||
- **blind_rotation**: API for blind rotation (LWE(m) -> GLWE(X^m))
|
- **blind_rotation**: API for blind rotation (LWE(m) -> GLWE(X^m))
|
||||||
- **circuit_bootstrapping**: API for circuit bootstrapping (LWE(m) -> GGSW(m) or GGSW(X^m)).
|
- **circuit_bootstrapping**: API for circuit bootstrapping (LWE(m) -> GGSW(m) or GGSW(X^m)).
|
||||||
- **CKKS**: planned
|
- **CKKS**: planned
|
||||||
454
poulpy-schemes/benches/bdd_arithmetic.rs
Normal file
454
poulpy-schemes/benches/bdd_arithmetic.rs
Normal file
@@ -0,0 +1,454 @@
|
|||||||
|
use std::hint::black_box;
|
||||||
|
|
||||||
|
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||||
|
use poulpy_core::{
|
||||||
|
GGSWNoise, GLWEDecrypt, GLWEEncryptSk, GLWEExternalProduct, LWEEncryptSk, ScratchTakeCore,
|
||||||
|
layouts::{
|
||||||
|
Base2K, Degree, Dnum, Dsize, GGLWEToGGSWKeyLayout, GGSWLayout, GGSWPreparedFactory, GLWEAutomorphismKeyLayout,
|
||||||
|
GLWELayout, GLWESecret, GLWESecretPrepared, GLWESecretPreparedFactory, GLWESwitchingKeyLayout, GLWEToLWEKeyLayout,
|
||||||
|
LWESecret, Rank, TorusPrecision,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
pub use poulpy_cpu_avx::FFT64Avx as BackendImpl;
|
||||||
|
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
pub use poulpy_cpu_ref::FFT64Ref as BackendImpl;
|
||||||
|
|
||||||
|
use poulpy_hal::{
|
||||||
|
api::{ModuleN, ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxRotateInplace},
|
||||||
|
layouts::{Backend, Module, Scratch, ScratchOwned},
|
||||||
|
source::Source,
|
||||||
|
};
|
||||||
|
use poulpy_schemes::bin_fhe::{
|
||||||
|
bdd_arithmetic::{
|
||||||
|
Add, And, BDDKey, BDDKeyEncryptSk, BDDKeyLayout, BDDKeyPrepared, BDDKeyPreparedFactory, ExecuteBDDCircuit2WTo1W, FheUint,
|
||||||
|
FheUintPrepare, FheUintPrepared, Or, Sll, Slt, Sltu, Sra, Srl, Sub, Xor,
|
||||||
|
},
|
||||||
|
blind_rotation::{
|
||||||
|
BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory, BlindRotationKeyInfos, BlindRotationKeyLayout, CGGI,
|
||||||
|
},
|
||||||
|
circuit_bootstrapping::{
|
||||||
|
CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout,
|
||||||
|
CircuitBootstrappingKeyPrepared, CircuitBootstrappingKeyPreparedFactory, CirtuitBootstrappingExecute,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Common setup data structure
|
||||||
|
struct BenchmarkSetup<BE: Backend, BRA: BlindRotationAlgo> {
|
||||||
|
module: Module<BE>,
|
||||||
|
scratch: ScratchOwned<BE>,
|
||||||
|
a_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE>,
|
||||||
|
b_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE>,
|
||||||
|
bdd_key_prepared: BDDKeyPrepared<Vec<u8>, BRA, BE>,
|
||||||
|
glwe_layout: GLWELayout,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Params {
|
||||||
|
name: String,
|
||||||
|
block_size: usize,
|
||||||
|
glwe_layout: GLWELayout,
|
||||||
|
ggsw_layout: GGSWLayout,
|
||||||
|
bdd_layout: BDDKeyLayout,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_benchmark<BE: Backend, BRA: BlindRotationAlgo>(params: &Params) -> BenchmarkSetup<BE, BRA>
|
||||||
|
where
|
||||||
|
Module<BE>: ModuleNew<BE>
|
||||||
|
+ ModuleN
|
||||||
|
+ GLWESecretPreparedFactory<BE>
|
||||||
|
+ GLWEExternalProduct<BE>
|
||||||
|
+ GLWEDecrypt<BE>
|
||||||
|
+ LWEEncryptSk<BE>
|
||||||
|
+ CircuitBootstrappingKeyEncryptSk<BRA, BE>
|
||||||
|
+ CircuitBootstrappingKeyPreparedFactory<BRA, BE>
|
||||||
|
+ CirtuitBootstrappingExecute<BRA, BE>
|
||||||
|
+ GGSWPreparedFactory<BE>
|
||||||
|
+ GGSWNoise<BE>
|
||||||
|
+ GLWEEncryptSk<BE>
|
||||||
|
+ VecZnxRotateInplace<BE>
|
||||||
|
+ BDDKeyEncryptSk<BRA, BE>
|
||||||
|
+ BDDKeyPreparedFactory<BRA, BE>
|
||||||
|
+ FheUintPrepare<BRA, BE>
|
||||||
|
+ ExecuteBDDCircuit2WTo1W<BE>,
|
||||||
|
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
|
||||||
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
// Scratch space (16MB)
|
||||||
|
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 24);
|
||||||
|
|
||||||
|
let n_glwe: poulpy_core::layouts::Degree = params.bdd_layout.cbt_layout.brk_layout.n_glwe();
|
||||||
|
let n_lwe: poulpy_core::layouts::Degree = params.bdd_layout.cbt_layout.brk_layout.n_lwe();
|
||||||
|
let rank: poulpy_core::layouts::Rank = params.bdd_layout.cbt_layout.brk_layout.rank;
|
||||||
|
|
||||||
|
let module: Module<BE> = Module::<BE>::new(n_glwe.as_u32() as u64);
|
||||||
|
|
||||||
|
let mut source_xs: Source = Source::new([1u8; 32]);
|
||||||
|
let mut source_xa: Source = Source::new([1u8; 32]);
|
||||||
|
let mut source_xe: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
|
||||||
|
sk_lwe.fill_binary_block(params.block_size, &mut source_xs);
|
||||||
|
|
||||||
|
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe, rank);
|
||||||
|
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||||
|
|
||||||
|
// Circuit bootstrapping evaluation key
|
||||||
|
let mut cbt_key: CircuitBootstrappingKey<Vec<u8>, BRA> =
|
||||||
|
CircuitBootstrappingKey::alloc_from_infos(¶ms.bdd_layout.cbt_layout);
|
||||||
|
cbt_key.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
&sk_lwe,
|
||||||
|
&sk_glwe,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut cbt_key_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, BE> =
|
||||||
|
CircuitBootstrappingKeyPrepared::alloc_from_infos(&module, ¶ms.bdd_layout.cbt_layout);
|
||||||
|
cbt_key_prepared.prepare(&module, &cbt_key, scratch.borrow());
|
||||||
|
|
||||||
|
let mut sk_glwe_prepared = GLWESecretPrepared::alloc_from_infos(&module, ¶ms.glwe_layout);
|
||||||
|
sk_glwe_prepared.prepare(&module, &sk_glwe);
|
||||||
|
|
||||||
|
let mut bdd_key: BDDKey<Vec<u8>, BRA> = BDDKey::alloc_from_infos(¶ms.bdd_layout);
|
||||||
|
bdd_key.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
&sk_lwe,
|
||||||
|
&sk_glwe,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let input_a = 255_u32;
|
||||||
|
let input_b = 30_u32;
|
||||||
|
|
||||||
|
let mut a_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(¶ms.glwe_layout);
|
||||||
|
a_enc.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
input_a,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut b_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(¶ms.glwe_layout);
|
||||||
|
b_enc.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
input_b,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
//////// Homomorphic computation starts here ////////
|
||||||
|
|
||||||
|
// Preparing the BDD Key
|
||||||
|
// The BDD key must be prepared once before any operation is performed
|
||||||
|
let mut bdd_key_prepared: BDDKeyPrepared<Vec<u8>, BRA, BE> = BDDKeyPrepared::alloc_from_infos(&module, ¶ms.bdd_layout);
|
||||||
|
bdd_key_prepared.prepare(&module, &bdd_key, scratch.borrow());
|
||||||
|
|
||||||
|
// Input Preparation
|
||||||
|
// Before each operation, the inputs to that operation must be prepared
|
||||||
|
// Preparation extracts each bit of the integer into a seperate GLWE ciphertext and bootstraps it into a GGSW ciphertext
|
||||||
|
let mut a_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> = FheUintPrepared::alloc_from_infos(&module, ¶ms.ggsw_layout);
|
||||||
|
a_enc_prepared.prepare(&module, &a_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
let mut b_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> = FheUintPrepared::alloc_from_infos(&module, ¶ms.ggsw_layout);
|
||||||
|
b_enc_prepared.prepare(&module, &b_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
BenchmarkSetup {
|
||||||
|
module,
|
||||||
|
scratch,
|
||||||
|
a_enc_prepared,
|
||||||
|
b_enc_prepared,
|
||||||
|
bdd_key_prepared,
|
||||||
|
glwe_layout: params.glwe_layout.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_runner<BE: Backend, BRA: BlindRotationAlgo, F>(setup: BenchmarkSetup<BE, BRA>, operation: F) -> impl FnMut()
|
||||||
|
where
|
||||||
|
Module<BE>: ExecuteBDDCircuit2WTo1W<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
ScratchOwned<BE>: ScratchOwnedBorrow<BE>,
|
||||||
|
F: Fn(
|
||||||
|
&mut FheUint<Vec<u8>, u32>,
|
||||||
|
&Module<BE>,
|
||||||
|
&FheUintPrepared<Vec<u8>, u32, BE>,
|
||||||
|
&FheUintPrepared<Vec<u8>, u32, BE>,
|
||||||
|
&BDDKeyPrepared<Vec<u8>, BRA, BE>,
|
||||||
|
&mut Scratch<BE>,
|
||||||
|
),
|
||||||
|
{
|
||||||
|
let BenchmarkSetup {
|
||||||
|
module,
|
||||||
|
mut scratch,
|
||||||
|
a_enc_prepared,
|
||||||
|
b_enc_prepared,
|
||||||
|
bdd_key_prepared,
|
||||||
|
glwe_layout,
|
||||||
|
} = setup;
|
||||||
|
|
||||||
|
let mut c_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
|
||||||
|
move || {
|
||||||
|
operation(
|
||||||
|
&mut c_enc,
|
||||||
|
&module,
|
||||||
|
&a_enc_prepared,
|
||||||
|
&b_enc_prepared,
|
||||||
|
&bdd_key_prepared,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
black_box(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_operation<BE: Backend, BRA: BlindRotationAlgo, F>(
|
||||||
|
group: &mut criterion::BenchmarkGroup<'_, criterion::measurement::WallTime>,
|
||||||
|
params: &Params,
|
||||||
|
operation_name: &str,
|
||||||
|
operation: F,
|
||||||
|
) where
|
||||||
|
Module<BE>: ModuleNew<BE>
|
||||||
|
+ ModuleN
|
||||||
|
+ GLWESecretPreparedFactory<BE>
|
||||||
|
+ GLWEExternalProduct<BE>
|
||||||
|
+ GLWEDecrypt<BE>
|
||||||
|
+ LWEEncryptSk<BE>
|
||||||
|
+ CircuitBootstrappingKeyEncryptSk<BRA, BE>
|
||||||
|
+ CircuitBootstrappingKeyPreparedFactory<BRA, BE>
|
||||||
|
+ CirtuitBootstrappingExecute<BRA, BE>
|
||||||
|
+ GGSWPreparedFactory<BE>
|
||||||
|
+ GGSWNoise<BE>
|
||||||
|
+ GLWEEncryptSk<BE>
|
||||||
|
+ VecZnxRotateInplace<BE>
|
||||||
|
+ BDDKeyEncryptSk<BRA, BE>
|
||||||
|
+ BDDKeyPreparedFactory<BRA, BE>
|
||||||
|
+ FheUintPrepare<BRA, BE>
|
||||||
|
+ ExecuteBDDCircuit2WTo1W<BE>,
|
||||||
|
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
|
||||||
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
F: Fn(
|
||||||
|
&mut FheUint<Vec<u8>, u32>,
|
||||||
|
&Module<BE>,
|
||||||
|
&FheUintPrepared<Vec<u8>, u32, BE>,
|
||||||
|
&FheUintPrepared<Vec<u8>, u32, BE>,
|
||||||
|
&BDDKeyPrepared<Vec<u8>, BRA, BE>,
|
||||||
|
&mut Scratch<BE>,
|
||||||
|
) + 'static,
|
||||||
|
{
|
||||||
|
let setup = setup_benchmark::<BE, BRA>(params);
|
||||||
|
let mut runner = create_runner(setup, operation);
|
||||||
|
let id = BenchmarkId::from_parameter(format!("{}_{}", params.name, operation_name));
|
||||||
|
group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn benc_bdd_arithmetic<BE: Backend, BRA: BlindRotationAlgo>(c: &mut Criterion, label: &str)
|
||||||
|
where
|
||||||
|
Module<BE>: ModuleNew<BE>
|
||||||
|
+ ModuleN
|
||||||
|
+ GLWESecretPreparedFactory<BE>
|
||||||
|
+ GLWEExternalProduct<BE>
|
||||||
|
+ GLWEDecrypt<BE>
|
||||||
|
+ LWEEncryptSk<BE>
|
||||||
|
+ CircuitBootstrappingKeyEncryptSk<BRA, BE>
|
||||||
|
+ CircuitBootstrappingKeyPreparedFactory<BRA, BE>
|
||||||
|
+ CirtuitBootstrappingExecute<BRA, BE>
|
||||||
|
+ GGSWPreparedFactory<BE>
|
||||||
|
+ GGSWNoise<BE>
|
||||||
|
+ GLWEEncryptSk<BE>
|
||||||
|
+ VecZnxRotateInplace<BE>
|
||||||
|
+ BDDKeyEncryptSk<BRA, BE>
|
||||||
|
+ BDDKeyPreparedFactory<BRA, BE>
|
||||||
|
+ FheUintPrepare<BRA, BE>
|
||||||
|
+ ExecuteBDDCircuit2WTo1W<BE>,
|
||||||
|
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, // TODO find a way to remove this bound or move it to CBT KEY
|
||||||
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
let group_name: String = format!("bdd_arithmetic::{label}");
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group(group_name);
|
||||||
|
|
||||||
|
const N_GLWE: u32 = 1024;
|
||||||
|
const N_LWE: u32 = 679;
|
||||||
|
const BINARY_BLOCK_SIZE: u32 = 7;
|
||||||
|
const BASE2K: u32 = 15;
|
||||||
|
const RANK: u32 = 2;
|
||||||
|
|
||||||
|
let params: Params = Params {
|
||||||
|
name: String::from(format!("n_glwe={N_GLWE}")),
|
||||||
|
block_size: BINARY_BLOCK_SIZE as usize,
|
||||||
|
glwe_layout: GLWELayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(2 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
ggsw_layout: GGSWLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(3 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
dnum: Dnum(3),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
},
|
||||||
|
bdd_layout: BDDKeyLayout {
|
||||||
|
cbt_layout: CircuitBootstrappingKeyLayout {
|
||||||
|
brk_layout: BlindRotationKeyLayout {
|
||||||
|
n_glwe: Degree(N_GLWE),
|
||||||
|
n_lwe: Degree(N_LWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ks_glwe_layout: Some(GLWESwitchingKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank_in: Rank(RANK),
|
||||||
|
rank_out: Rank(1),
|
||||||
|
}),
|
||||||
|
ks_lwe_layout: GLWEToLWEKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
rank_in: Rank(1),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Benchmark each operation
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"add",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.add(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"sub",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.sub(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"sll",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.sll(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"sra",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.sra(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"srl",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.srl(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"slt",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.slt(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"sltu",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.sltu(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"or",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.or(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"and",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.and(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bench_operation::<BE, BRA, _>(
|
||||||
|
&mut group,
|
||||||
|
¶ms,
|
||||||
|
"xor",
|
||||||
|
|c_enc, module, a, b, key, scratch| {
|
||||||
|
c_enc.xor(module, a, b, key, scratch);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
group.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_bdd_arithmetic_fft64(c: &mut Criterion) {
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
let label = "fft64_avx";
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
let label = "fft64_ref";
|
||||||
|
benc_bdd_arithmetic::<BackendImpl, CGGI>(c, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, bench_bdd_arithmetic_fft64);
|
||||||
|
criterion_main!(benches);
|
||||||
238
poulpy-schemes/benches/bdd_prepare.rs
Normal file
238
poulpy-schemes/benches/bdd_prepare.rs
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
use std::hint::black_box;
|
||||||
|
|
||||||
|
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||||
|
use poulpy_core::{
|
||||||
|
GGSWNoise, GLWEDecrypt, GLWEEncryptSk, GLWEExternalProduct, LWEEncryptSk, ScratchTakeCore,
|
||||||
|
layouts::{
|
||||||
|
Base2K, Degree, Dnum, Dsize, GGLWEToGGSWKeyLayout, GGSWLayout, GGSWPreparedFactory, GLWEAutomorphismKeyLayout,
|
||||||
|
GLWELayout, GLWESecret, GLWESecretPrepared, GLWESecretPreparedFactory, GLWESwitchingKeyLayout, GLWEToLWEKeyLayout,
|
||||||
|
LWESecret, Rank, TorusPrecision,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
pub use poulpy_cpu_avx::FFT64Avx as BackendImpl;
|
||||||
|
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
pub use poulpy_cpu_ref::FFT64Ref as BackendImpl;
|
||||||
|
|
||||||
|
use poulpy_hal::{
|
||||||
|
api::{ModuleN, ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxRotateInplace},
|
||||||
|
layouts::{Backend, Module, Scratch, ScratchOwned},
|
||||||
|
source::Source,
|
||||||
|
};
|
||||||
|
use poulpy_schemes::bin_fhe::{
|
||||||
|
bdd_arithmetic::{
|
||||||
|
BDDKey, BDDKeyEncryptSk, BDDKeyLayout, BDDKeyPrepared, BDDKeyPreparedFactory, ExecuteBDDCircuit2WTo1W, FheUint,
|
||||||
|
FheUintPrepare, FheUintPrepared,
|
||||||
|
},
|
||||||
|
blind_rotation::{
|
||||||
|
BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory, BlindRotationKeyInfos, BlindRotationKeyLayout, CGGI,
|
||||||
|
},
|
||||||
|
circuit_bootstrapping::{
|
||||||
|
CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout, CircuitBootstrappingKeyPreparedFactory,
|
||||||
|
CirtuitBootstrappingExecute,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn benc_bdd_prepare<BE: Backend, BRA: BlindRotationAlgo>(c: &mut Criterion, label: &str)
|
||||||
|
where
|
||||||
|
Module<BE>: ModuleNew<BE>
|
||||||
|
+ ModuleN
|
||||||
|
+ GLWESecretPreparedFactory<BE>
|
||||||
|
+ GLWEExternalProduct<BE>
|
||||||
|
+ GLWEDecrypt<BE>
|
||||||
|
+ LWEEncryptSk<BE>
|
||||||
|
+ CircuitBootstrappingKeyEncryptSk<BRA, BE>
|
||||||
|
+ CircuitBootstrappingKeyPreparedFactory<BRA, BE>
|
||||||
|
+ CirtuitBootstrappingExecute<BRA, BE>
|
||||||
|
+ GGSWPreparedFactory<BE>
|
||||||
|
+ GGSWNoise<BE>
|
||||||
|
+ GLWEEncryptSk<BE>
|
||||||
|
+ VecZnxRotateInplace<BE>
|
||||||
|
+ BDDKeyEncryptSk<BRA, BE>
|
||||||
|
+ BDDKeyPreparedFactory<BRA, BE>
|
||||||
|
+ FheUintPrepare<BRA, BE>
|
||||||
|
+ ExecuteBDDCircuit2WTo1W<BE>,
|
||||||
|
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, // TODO find a way to remove this bound or move it to CBT KEY
|
||||||
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
let group_name: String = format!("bdd_arithmetic::{label}");
|
||||||
|
|
||||||
|
let mut group = c.benchmark_group(group_name);
|
||||||
|
|
||||||
|
struct Params {
|
||||||
|
name: String,
|
||||||
|
block_size: usize,
|
||||||
|
glwe_layout: GLWELayout,
|
||||||
|
ggsw_layout: GGSWLayout,
|
||||||
|
bdd_layout: BDDKeyLayout,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn runner<BE: Backend, BRA: BlindRotationAlgo>(params: &Params) -> impl FnMut()
|
||||||
|
where
|
||||||
|
Module<BE>: ModuleNew<BE>
|
||||||
|
+ ModuleN
|
||||||
|
+ GLWESecretPreparedFactory<BE>
|
||||||
|
+ GLWEExternalProduct<BE>
|
||||||
|
+ GLWEDecrypt<BE>
|
||||||
|
+ LWEEncryptSk<BE>
|
||||||
|
+ CircuitBootstrappingKeyEncryptSk<BRA, BE>
|
||||||
|
+ CircuitBootstrappingKeyPreparedFactory<BRA, BE>
|
||||||
|
+ CirtuitBootstrappingExecute<BRA, BE>
|
||||||
|
+ GGSWPreparedFactory<BE>
|
||||||
|
+ GGSWNoise<BE>
|
||||||
|
+ GLWEEncryptSk<BE>
|
||||||
|
+ VecZnxRotateInplace<BE>
|
||||||
|
+ BDDKeyEncryptSk<BRA, BE>
|
||||||
|
+ BDDKeyPreparedFactory<BRA, BE>
|
||||||
|
+ FheUintPrepare<BRA, BE>
|
||||||
|
+ ExecuteBDDCircuit2WTo1W<BE>,
|
||||||
|
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, /* TODO find a way to remove this bound or move it to CBT KEY */
|
||||||
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
// Scratch space (4MB)
|
||||||
|
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 25);
|
||||||
|
|
||||||
|
let n_glwe: poulpy_core::layouts::Degree = params.bdd_layout.cbt_layout.brk_layout.n_glwe();
|
||||||
|
let n_lwe: poulpy_core::layouts::Degree = params.bdd_layout.cbt_layout.brk_layout.n_lwe();
|
||||||
|
let rank: poulpy_core::layouts::Rank = params.bdd_layout.cbt_layout.brk_layout.rank;
|
||||||
|
|
||||||
|
let module: Module<BE> = Module::<BE>::new(n_glwe.as_u32() as u64);
|
||||||
|
|
||||||
|
let mut source_xs: Source = Source::new([1u8; 32]);
|
||||||
|
let mut source_xa: Source = Source::new([1u8; 32]);
|
||||||
|
let mut source_xe: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
|
||||||
|
sk_lwe.fill_binary_block(params.block_size, &mut source_xs);
|
||||||
|
|
||||||
|
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe, rank);
|
||||||
|
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||||
|
|
||||||
|
let mut sk_glwe_prepared = GLWESecretPrepared::alloc_from_infos(&module, ¶ms.glwe_layout);
|
||||||
|
sk_glwe_prepared.prepare(&module, &sk_glwe);
|
||||||
|
|
||||||
|
let mut bdd_key: BDDKey<Vec<u8>, BRA> = BDDKey::alloc_from_infos(¶ms.bdd_layout);
|
||||||
|
bdd_key.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
&sk_lwe,
|
||||||
|
&sk_glwe,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let input_a = 255_u32;
|
||||||
|
|
||||||
|
let mut a_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(¶ms.glwe_layout);
|
||||||
|
a_enc.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
input_a,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut bdd_key_prepared: BDDKeyPrepared<Vec<u8>, BRA, BE> =
|
||||||
|
BDDKeyPrepared::alloc_from_infos(&module, ¶ms.bdd_layout);
|
||||||
|
bdd_key_prepared.prepare(&module, &bdd_key, scratch.borrow());
|
||||||
|
|
||||||
|
let mut a_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> =
|
||||||
|
FheUintPrepared::alloc_from_infos(&module, ¶ms.ggsw_layout);
|
||||||
|
|
||||||
|
move || {
|
||||||
|
a_enc_prepared.prepare(&module, &a_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
black_box(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const N_GLWE: u32 = 1024;
|
||||||
|
const N_LWE: u32 = 679;
|
||||||
|
const BINARY_BLOCK_SIZE: u32 = 7;
|
||||||
|
const BASE2K: u32 = 15;
|
||||||
|
const RANK: u32 = 2;
|
||||||
|
|
||||||
|
let params: Params = Params {
|
||||||
|
name: String::from(format!("n_glwe={N_GLWE}")),
|
||||||
|
block_size: BINARY_BLOCK_SIZE as usize,
|
||||||
|
glwe_layout: GLWELayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(2 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
ggsw_layout: GGSWLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(3 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
dnum: Dnum(3),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
},
|
||||||
|
bdd_layout: BDDKeyLayout {
|
||||||
|
cbt_layout: CircuitBootstrappingKeyLayout {
|
||||||
|
brk_layout: BlindRotationKeyLayout {
|
||||||
|
n_glwe: Degree(N_GLWE),
|
||||||
|
n_lwe: Degree(N_LWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ks_glwe_layout: Some(GLWESwitchingKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank_in: Rank(RANK),
|
||||||
|
rank_out: Rank(1),
|
||||||
|
}),
|
||||||
|
ks_lwe_layout: GLWEToLWEKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
rank_in: Rank(1),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let id: BenchmarkId = BenchmarkId::from_parameter(params.name.clone());
|
||||||
|
let mut runner = runner::<BE, BRA>(¶ms);
|
||||||
|
group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
|
||||||
|
|
||||||
|
group.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_bdd_prepare_fft64(c: &mut Criterion) {
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
let label = "fft64_avx";
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
let label = "fft64_ref";
|
||||||
|
benc_bdd_prepare::<BackendImpl, CGGI>(c, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, bench_bdd_prepare_fft64);
|
||||||
|
criterion_main!(benches);
|
||||||
@@ -85,9 +85,9 @@ where
|
|||||||
// Scratch space (4MB)
|
// Scratch space (4MB)
|
||||||
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 22);
|
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 22);
|
||||||
|
|
||||||
let n_glwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_glwe();
|
let n_glwe: poulpy_core::layouts::Degree = params.cbt_infos.brk_layout.n_glwe();
|
||||||
let n_lwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_lwe();
|
let n_lwe: poulpy_core::layouts::Degree = params.cbt_infos.brk_layout.n_lwe();
|
||||||
let rank: poulpy_core::layouts::Rank = params.cbt_infos.layout_brk.rank;
|
let rank: poulpy_core::layouts::Rank = params.cbt_infos.brk_layout.rank;
|
||||||
|
|
||||||
let module: Module<BE> = Module::<BE>::new(n_glwe.as_u32() as u64);
|
let module: Module<BE> = Module::<BE>::new(n_glwe.as_u32() as u64);
|
||||||
|
|
||||||
@@ -97,7 +97,6 @@ where
|
|||||||
|
|
||||||
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
|
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);
|
||||||
sk_lwe.fill_binary_block(params.block_size, &mut source_xs);
|
sk_lwe.fill_binary_block(params.block_size, &mut source_xs);
|
||||||
sk_lwe.fill_zero();
|
|
||||||
|
|
||||||
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe, rank);
|
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe, rank);
|
||||||
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||||
@@ -151,7 +150,7 @@ where
|
|||||||
rank: 2_u32.into(),
|
rank: 2_u32.into(),
|
||||||
},
|
},
|
||||||
cbt_infos: CircuitBootstrappingKeyLayout {
|
cbt_infos: CircuitBootstrappingKeyLayout {
|
||||||
layout_brk: BlindRotationKeyLayout {
|
brk_layout: BlindRotationKeyLayout {
|
||||||
n_glwe: 1024_u32.into(),
|
n_glwe: 1024_u32.into(),
|
||||||
n_lwe: 574_u32.into(),
|
n_lwe: 574_u32.into(),
|
||||||
base2k: 13_u32.into(),
|
base2k: 13_u32.into(),
|
||||||
@@ -159,7 +158,7 @@ where
|
|||||||
dnum: 3_u32.into(),
|
dnum: 3_u32.into(),
|
||||||
rank: 2_u32.into(),
|
rank: 2_u32.into(),
|
||||||
},
|
},
|
||||||
layout_atk: GLWEAutomorphismKeyLayout {
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
n: 1024_u32.into(),
|
n: 1024_u32.into(),
|
||||||
base2k: 13_u32.into(),
|
base2k: 13_u32.into(),
|
||||||
k: 52_u32.into(),
|
k: 52_u32.into(),
|
||||||
@@ -167,7 +166,7 @@ where
|
|||||||
dsize: Dsize(1),
|
dsize: Dsize(1),
|
||||||
rank: 2_u32.into(),
|
rank: 2_u32.into(),
|
||||||
},
|
},
|
||||||
layout_tsk: GGLWEToGGSWKeyLayout {
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
n: 1024_u32.into(),
|
n: 1024_u32.into(),
|
||||||
base2k: 13_u32.into(),
|
base2k: 13_u32.into(),
|
||||||
k: 52_u32.into(),
|
k: 52_u32.into(),
|
||||||
|
|||||||
332
poulpy-schemes/examples/bdd_arithmetic.rs
Normal file
332
poulpy-schemes/examples/bdd_arithmetic.rs
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use poulpy_core::{
|
||||||
|
GLWEDecrypt, GLWEEncryptSk, GLWEExternalProduct, LWEEncryptSk, ScratchTakeCore,
|
||||||
|
layouts::{
|
||||||
|
Base2K, Degree, Dnum, Dsize, GGLWEToGGSWKeyLayout, GGSWLayout, GGSWPreparedFactory, GLWEAutomorphismKeyLayout,
|
||||||
|
GLWELayout, GLWESecret, GLWESecretPrepared, GLWESecretPreparedFactory, GLWESwitchingKeyLayout, GLWEToLWEKeyLayout,
|
||||||
|
LWESecret, Rank, TorusPrecision,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use poulpy_hal::{
|
||||||
|
api::{ModuleN, ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxRotateInplace},
|
||||||
|
layouts::{Backend, Module, Scratch, ScratchOwned},
|
||||||
|
source::Source,
|
||||||
|
};
|
||||||
|
use poulpy_schemes::bin_fhe::{
|
||||||
|
bdd_arithmetic::{
|
||||||
|
Add, BDDKey, BDDKeyEncryptSk, BDDKeyLayout, BDDKeyPrepared, BDDKeyPreparedFactory, ExecuteBDDCircuit2WTo1W, FheUint,
|
||||||
|
FheUintPrepare, FheUintPrepared, GLWEBlindSelection, Xor,
|
||||||
|
},
|
||||||
|
blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory, BlindRotationKeyLayout, CGGI},
|
||||||
|
circuit_bootstrapping::CircuitBootstrappingKeyLayout,
|
||||||
|
};
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
use poulpy_cpu_avx::FFT64Avx;
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
use poulpy_cpu_ref::FFT64Ref;
|
||||||
|
|
||||||
|
// This example demonstrates and end-to-end example usage of the BDD arithmetic API
|
||||||
|
// It includes all steps including:
|
||||||
|
//
|
||||||
|
// - Parameter Selection
|
||||||
|
// - Key Generation
|
||||||
|
// - Input Encryption
|
||||||
|
//
|
||||||
|
// - Key preparation
|
||||||
|
// - Input Preparation
|
||||||
|
// - Operation Execution
|
||||||
|
//
|
||||||
|
// - Result Decryption
|
||||||
|
//
|
||||||
|
|
||||||
|
fn example_bdd_arithmetic<BE: Backend, BRA: BlindRotationAlgo>()
|
||||||
|
where
|
||||||
|
Module<BE>: ModuleNew<BE>
|
||||||
|
+ ModuleN
|
||||||
|
+ GLWESecretPreparedFactory<BE>
|
||||||
|
+ GLWEExternalProduct<BE>
|
||||||
|
+ GLWEDecrypt<BE>
|
||||||
|
+ LWEEncryptSk<BE>
|
||||||
|
+ GGSWPreparedFactory<BE>
|
||||||
|
+ GLWEEncryptSk<BE>
|
||||||
|
+ VecZnxRotateInplace<BE>
|
||||||
|
+ BDDKeyEncryptSk<BRA, BE>
|
||||||
|
+ BDDKeyPreparedFactory<BRA, BE>
|
||||||
|
+ FheUintPrepare<BRA, BE>
|
||||||
|
+ ExecuteBDDCircuit2WTo1W<BE>
|
||||||
|
+ GLWEBlindSelection<u32, BE>,
|
||||||
|
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, // TODO find a way to remove this bound or move it to CBT KEY
|
||||||
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
////////// Parameter Selection
|
||||||
|
const N_GLWE: u32 = 1024;
|
||||||
|
const N_LWE: u32 = 567;
|
||||||
|
const BINARY_BLOCK_SIZE: u32 = 7;
|
||||||
|
const BASE2K: u32 = 17;
|
||||||
|
const RANK: u32 = 1;
|
||||||
|
|
||||||
|
// GLWE layout, used to generate GLWE Ciphertexts, keys, switching keys, etc
|
||||||
|
let glwe_layout = GLWELayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(2 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to generate GGSW Ciphertexts
|
||||||
|
let ggsw_layout = GGSWLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(3 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
dnum: Dnum(3),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to generate BDD Keys, for the arithmetic operations
|
||||||
|
let bdd_layout = BDDKeyLayout {
|
||||||
|
cbt_layout: CircuitBootstrappingKeyLayout {
|
||||||
|
brk_layout: BlindRotationKeyLayout {
|
||||||
|
n_glwe: Degree(N_GLWE),
|
||||||
|
n_lwe: Degree(N_LWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ks_glwe_layout: Some(GLWESwitchingKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank_in: Rank(RANK),
|
||||||
|
rank_out: Rank(1),
|
||||||
|
}),
|
||||||
|
ks_lwe_layout: GLWEToLWEKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
rank_in: Rank(1),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let module = Module::<BE>::new(N_GLWE as u64);
|
||||||
|
|
||||||
|
// Secret key sampling source
|
||||||
|
let mut source_xs: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
// Public randomness sampling source
|
||||||
|
let mut source_xa: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
// Noise sampling source
|
||||||
|
let mut source_xe: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
// Scratch space (4MB)
|
||||||
|
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 22);
|
||||||
|
|
||||||
|
////////// Key Generation and Preparation
|
||||||
|
// Generating the GLWE and LWE key
|
||||||
|
let mut sk_glwe = GLWESecret::alloc_from_infos(&glwe_layout);
|
||||||
|
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||||
|
|
||||||
|
let mut sk_lwe = LWESecret::alloc(bdd_layout.cbt_layout.brk_layout.n_lwe);
|
||||||
|
sk_lwe.fill_binary_block(BINARY_BLOCK_SIZE as usize, &mut source_xs);
|
||||||
|
|
||||||
|
// Preparing the private keys
|
||||||
|
let mut sk_glwe_prepared = GLWESecretPrepared::alloc_from_infos(&module, &glwe_layout);
|
||||||
|
sk_glwe_prepared.prepare(&module, &sk_glwe);
|
||||||
|
|
||||||
|
// Creating the public BDD Key
|
||||||
|
// This key is required to prepare all Fhe Integers for operations,
|
||||||
|
// and for performing the operations themselves
|
||||||
|
let mut bdd_key: BDDKey<Vec<u8>, BRA> = BDDKey::alloc_from_infos(&bdd_layout);
|
||||||
|
bdd_key.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
&sk_lwe,
|
||||||
|
&sk_glwe,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
////////// Input Encryption
|
||||||
|
// Encrypting the inputs
|
||||||
|
let input_a = 255_u32;
|
||||||
|
let input_b = 30_u32;
|
||||||
|
|
||||||
|
let mut a_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
a_enc.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
input_a,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut b_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
b_enc.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
input_b,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
//////// Homomorphic computation starts here ////////
|
||||||
|
|
||||||
|
// Preparing the BDD Key
|
||||||
|
// The BDD key must be prepared once before any operation is performed
|
||||||
|
let mut bdd_key_prepared: BDDKeyPrepared<Vec<u8>, BRA, BE> = BDDKeyPrepared::alloc_from_infos(&module, &bdd_layout);
|
||||||
|
bdd_key_prepared.prepare(&module, &bdd_key, scratch.borrow());
|
||||||
|
|
||||||
|
// Input Preparation
|
||||||
|
// Before each operation, the inputs to that operation must be prepared
|
||||||
|
// Preparation extracts each bit of the integer into a seperate GLWE ciphertext and bootstraps it into a GGSW ciphertext
|
||||||
|
let mut a_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> = FheUintPrepared::alloc_from_infos(&module, &ggsw_layout);
|
||||||
|
a_enc_prepared.prepare(&module, &a_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
let mut b_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> = FheUintPrepared::alloc_from_infos(&module, &ggsw_layout);
|
||||||
|
b_enc_prepared.prepare(&module, &b_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
// Allocating the intermediate ciphertext c_enc
|
||||||
|
let mut c_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
|
||||||
|
// Performing the operation
|
||||||
|
c_enc.add(
|
||||||
|
&module,
|
||||||
|
&a_enc_prepared,
|
||||||
|
&b_enc_prepared,
|
||||||
|
&bdd_key_prepared,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Preparing the intermediate result ciphertext, c_enc, for the next operation
|
||||||
|
let mut c_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> = FheUintPrepared::alloc_from_infos(&module, &ggsw_layout);
|
||||||
|
c_enc_prepared.prepare(&module, &c_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
// Creating the output ciphertext d_enc
|
||||||
|
let mut selected_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
selected_enc.xor(
|
||||||
|
&module,
|
||||||
|
&c_enc_prepared,
|
||||||
|
&a_enc_prepared,
|
||||||
|
&bdd_key_prepared,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
//////// Homomorphic computation ends here ////////
|
||||||
|
|
||||||
|
// Decrypting the result
|
||||||
|
let d_dec = selected_enc.decrypt(&module, &sk_glwe_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
// d = (a + b) ^ a
|
||||||
|
let d_correct = (input_a.wrapping_add(input_b)) ^ input_a;
|
||||||
|
println!("Result: {} == {}", d_dec, d_correct);
|
||||||
|
|
||||||
|
// List of available operations are:
|
||||||
|
// - add: addition
|
||||||
|
// - sub: subtraction
|
||||||
|
// - sll: left shift logical
|
||||||
|
// - sra: right shift arithmetic
|
||||||
|
// - srl: right shift logical
|
||||||
|
// - slt: less than
|
||||||
|
// - sltu: less than unsigned
|
||||||
|
// - and: bitwise and
|
||||||
|
// - or: bitwise or
|
||||||
|
// - xor: bitwise xor
|
||||||
|
|
||||||
|
///////////////////////////// GLWE Blind Selection
|
||||||
|
// This example demonstrates the use of the GLWE Blind Selection operation
|
||||||
|
// It can choose between any number of encrypted fheuint inputs
|
||||||
|
// using an encrypted fheuint selector
|
||||||
|
|
||||||
|
let log_2_number_of_inputs: usize = 5;
|
||||||
|
let number_of_inputs: usize = 1 << log_2_number_of_inputs;
|
||||||
|
let inputs_a_vec: Vec<u32> = (0..number_of_inputs)
|
||||||
|
.map(|_| rand::rng().random_range(0..u32::MAX - 1))
|
||||||
|
.collect();
|
||||||
|
let input_selector: u32 = rand::rng().random_range(0..number_of_inputs as u32);
|
||||||
|
|
||||||
|
let mut inputs_a_enc_vec: Vec<FheUint<Vec<u8>, u32>> = Vec::new();
|
||||||
|
for input in &inputs_a_vec {
|
||||||
|
let mut next_input: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
next_input.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
*input,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
inputs_a_enc_vec.push(next_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut inputs_a_enc_vec_map: HashMap<usize, &mut FheUint<Vec<u8>, u32>> = HashMap::new();
|
||||||
|
for (i, input) in inputs_a_enc_vec.iter_mut().enumerate() {
|
||||||
|
inputs_a_enc_vec_map.insert(i, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut input_selector_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
input_selector_enc.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
input_selector,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
let mut input_selector_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> =
|
||||||
|
FheUintPrepared::alloc_from_infos(&module, &ggsw_layout);
|
||||||
|
input_selector_enc_prepared.prepare(
|
||||||
|
&module,
|
||||||
|
&input_selector_enc,
|
||||||
|
&bdd_key_prepared,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
module.glwe_blind_selection(
|
||||||
|
&mut selected_enc,
|
||||||
|
inputs_a_enc_vec_map,
|
||||||
|
&input_selector_enc_prepared,
|
||||||
|
0,
|
||||||
|
log_2_number_of_inputs,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let selected_dec = selected_enc.decrypt(&module, &sk_glwe_prepared, scratch.borrow());
|
||||||
|
let selected_correct = inputs_a_vec[input_selector as usize];
|
||||||
|
println!("Result: {} == {}", selected_dec, selected_correct);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
example_bdd_arithmetic::<FFT64Avx, CGGI>();
|
||||||
|
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
example_bdd_arithmetic::<FFT64Ref, CGGI>();
|
||||||
|
}
|
||||||
@@ -77,8 +77,8 @@ fn main() {
|
|||||||
// GGLWE tensor key modulus
|
// GGLWE tensor key modulus
|
||||||
let k_tsk: usize = (rows_tsk + 1) * base2k;
|
let k_tsk: usize = (rows_tsk + 1) * base2k;
|
||||||
|
|
||||||
let cbt_infos: CircuitBootstrappingKeyLayout = CircuitBootstrappingKeyLayout {
|
let cbt_layout: CircuitBootstrappingKeyLayout = CircuitBootstrappingKeyLayout {
|
||||||
layout_brk: BlindRotationKeyLayout {
|
brk_layout: BlindRotationKeyLayout {
|
||||||
n_glwe: n_glwe.into(),
|
n_glwe: n_glwe.into(),
|
||||||
n_lwe: n_lwe.into(),
|
n_lwe: n_lwe.into(),
|
||||||
base2k: base2k.into(),
|
base2k: base2k.into(),
|
||||||
@@ -86,7 +86,7 @@ fn main() {
|
|||||||
dnum: rows_brk.into(),
|
dnum: rows_brk.into(),
|
||||||
rank: rank.into(),
|
rank: rank.into(),
|
||||||
},
|
},
|
||||||
layout_atk: GLWEAutomorphismKeyLayout {
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
n: n_glwe.into(),
|
n: n_glwe.into(),
|
||||||
base2k: base2k.into(),
|
base2k: base2k.into(),
|
||||||
k: k_trace.into(),
|
k: k_trace.into(),
|
||||||
@@ -94,7 +94,7 @@ fn main() {
|
|||||||
dsize: 1_u32.into(),
|
dsize: 1_u32.into(),
|
||||||
rank: rank.into(),
|
rank: rank.into(),
|
||||||
},
|
},
|
||||||
layout_tsk: GGLWEToGGSWKeyLayout {
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
n: n_glwe.into(),
|
n: n_glwe.into(),
|
||||||
base2k: base2k.into(),
|
base2k: base2k.into(),
|
||||||
k: k_tsk.into(),
|
k: k_tsk.into(),
|
||||||
@@ -134,12 +134,12 @@ fn main() {
|
|||||||
// LWE secret
|
// LWE secret
|
||||||
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe.into());
|
let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe.into());
|
||||||
sk_lwe.fill_binary_block(block_size, &mut source_xs);
|
sk_lwe.fill_binary_block(block_size, &mut source_xs);
|
||||||
sk_lwe.fill_zero();
|
// sk_lwe.fill_zero(); // for testing
|
||||||
|
|
||||||
// GLWE secret
|
// GLWE secret
|
||||||
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe.into(), rank.into());
|
let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe.into(), rank.into());
|
||||||
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||||
// sk_glwe.fill_zero();
|
// sk_glwe.fill_zero(); // for testing
|
||||||
|
|
||||||
// GLWE secret prepared (opaque backend dependant write only struct)
|
// GLWE secret prepared (opaque backend dependant write only struct)
|
||||||
let mut sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, BackendImpl> = GLWESecretPrepared::alloc(&module, rank.into());
|
let mut sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, BackendImpl> = GLWESecretPrepared::alloc(&module, rank.into());
|
||||||
@@ -151,7 +151,7 @@ fn main() {
|
|||||||
// LWE plaintext
|
// LWE plaintext
|
||||||
let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into());
|
let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into());
|
||||||
|
|
||||||
// LWE plaintext(data * 2^{- (k_lwe_pt - 1)})
|
// LWE plaintext(data * 2^{- (k_lwe_pt + 1)})
|
||||||
pt_lwe.encode_i64(data, (k_lwe_pt + 1).into()); // +1 for padding bit
|
pt_lwe.encode_i64(data, (k_lwe_pt + 1).into()); // +1 for padding bit
|
||||||
|
|
||||||
// Normalize plaintext to nicely print coefficients
|
// Normalize plaintext to nicely print coefficients
|
||||||
@@ -174,7 +174,7 @@ fn main() {
|
|||||||
let now: Instant = Instant::now();
|
let now: Instant = Instant::now();
|
||||||
|
|
||||||
// Circuit bootstrapping evaluation key
|
// Circuit bootstrapping evaluation key
|
||||||
let mut cbt_key: CircuitBootstrappingKey<Vec<u8>, CGGI> = CircuitBootstrappingKey::alloc_from_infos(&cbt_infos);
|
let mut cbt_key: CircuitBootstrappingKey<Vec<u8>, CGGI> = CircuitBootstrappingKey::alloc_from_infos(&cbt_layout);
|
||||||
|
|
||||||
cbt_key.encrypt_sk(
|
cbt_key.encrypt_sk(
|
||||||
&module,
|
&module,
|
||||||
@@ -192,7 +192,7 @@ fn main() {
|
|||||||
|
|
||||||
// Circuit bootstrapping key prepared (opaque backend dependant write only struct)
|
// Circuit bootstrapping key prepared (opaque backend dependant write only struct)
|
||||||
let mut cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, CGGI, BackendImpl> =
|
let mut cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, CGGI, BackendImpl> =
|
||||||
CircuitBootstrappingKeyPrepared::alloc_from_infos(&module, &cbt_infos);
|
CircuitBootstrappingKeyPrepared::alloc_from_infos(&module, &cbt_layout);
|
||||||
cbt_prepared.prepare(&module, &cbt_key, scratch.borrow());
|
cbt_prepared.prepare(&module, &cbt_key, scratch.borrow());
|
||||||
|
|
||||||
// Apply circuit bootstrapping: LWE(data * 2^{- (k_lwe_pt + 2)}) -> GGSW(data)
|
// Apply circuit bootstrapping: LWE(data * 2^{- (k_lwe_pt + 2)}) -> GGSW(data)
|
||||||
|
|||||||
259
poulpy-schemes/examples/max_array.rs
Normal file
259
poulpy-schemes/examples/max_array.rs
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use poulpy_core::{
|
||||||
|
GLWECopy, GLWEDecrypt, GLWEEncryptSk, GLWEExternalProduct, LWEEncryptSk, ScratchTakeCore,
|
||||||
|
layouts::{
|
||||||
|
Base2K, Degree, Dnum, Dsize, GGLWEToGGSWKeyLayout, GGSWLayout, GGSWPreparedFactory, GLWEAutomorphismKeyLayout,
|
||||||
|
GLWELayout, GLWESecret, GLWESecretPrepared, GLWESecretPreparedFactory, GLWESwitchingKeyLayout, GLWEToLWEKeyLayout,
|
||||||
|
GLWEToMut, GLWEToRef, LWESecret, Rank, TorusPrecision,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use poulpy_hal::{
|
||||||
|
api::{ModuleN, ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxRotateInplace},
|
||||||
|
layouts::{Backend, Module, Scratch, ScratchOwned},
|
||||||
|
source::Source,
|
||||||
|
};
|
||||||
|
use poulpy_schemes::bin_fhe::{
|
||||||
|
bdd_arithmetic::{
|
||||||
|
BDDKey, BDDKeyEncryptSk, BDDKeyLayout, BDDKeyPrepared, BDDKeyPreparedFactory, ExecuteBDDCircuit2WTo1W, FheUint,
|
||||||
|
FheUintPrepare, FheUintPrepared, GLWEBlindSelection, Sltu,
|
||||||
|
},
|
||||||
|
blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory, BlindRotationKeyLayout, CGGI},
|
||||||
|
circuit_bootstrapping::CircuitBootstrappingKeyLayout,
|
||||||
|
};
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
use poulpy_cpu_avx::FFT64Avx;
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
use poulpy_cpu_ref::FFT64Ref;
|
||||||
|
|
||||||
|
// This example demonstrates and end-to-end example usage of the BDD arithmetic API
|
||||||
|
// to compute the maximum of an array of integers.
|
||||||
|
|
||||||
|
fn example_max_array<BE: Backend, BRA: BlindRotationAlgo>()
|
||||||
|
where
|
||||||
|
Module<BE>: ModuleNew<BE>
|
||||||
|
+ ModuleN
|
||||||
|
+ GLWESecretPreparedFactory<BE>
|
||||||
|
+ GLWEExternalProduct<BE>
|
||||||
|
+ GLWEDecrypt<BE>
|
||||||
|
+ LWEEncryptSk<BE>
|
||||||
|
+ GGSWPreparedFactory<BE>
|
||||||
|
+ GLWEEncryptSk<BE>
|
||||||
|
+ VecZnxRotateInplace<BE>
|
||||||
|
+ BDDKeyEncryptSk<BRA, BE>
|
||||||
|
+ BDDKeyPreparedFactory<BRA, BE>
|
||||||
|
+ FheUintPrepare<BRA, BE>
|
||||||
|
+ ExecuteBDDCircuit2WTo1W<BE>
|
||||||
|
+ GLWEBlindSelection<u32, BE>,
|
||||||
|
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>, // TODO find a way to remove this bound or move it to CBT KEY
|
||||||
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
////////// Parameter Selection
|
||||||
|
const N_GLWE: u32 = 1024;
|
||||||
|
const N_LWE: u32 = 567;
|
||||||
|
const BINARY_BLOCK_SIZE: u32 = 7;
|
||||||
|
const BASE2K: u32 = 17;
|
||||||
|
const RANK: u32 = 1;
|
||||||
|
|
||||||
|
// GLWE layout, used to generate GLWE Ciphertexts, keys, switching keys, etc
|
||||||
|
let glwe_layout = GLWELayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(2 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to generate GGSW Ciphertexts
|
||||||
|
let ggsw_layout = GGSWLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(3 * BASE2K),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
dnum: Dnum(3),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to generate CBT Keys
|
||||||
|
let cbt_layout = CircuitBootstrappingKeyLayout {
|
||||||
|
brk_layout: BlindRotationKeyLayout {
|
||||||
|
n_glwe: Degree(N_GLWE),
|
||||||
|
n_lwe: Degree(N_LWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank: Rank(RANK),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to generate BDD Keys, for the arithmetic operations
|
||||||
|
let bdd_layout = BDDKeyLayout {
|
||||||
|
cbt_layout: cbt_layout,
|
||||||
|
ks_glwe_layout: Some(GLWESwitchingKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
dsize: Dsize(1),
|
||||||
|
rank_in: Rank(RANK),
|
||||||
|
rank_out: Rank(1),
|
||||||
|
}),
|
||||||
|
ks_lwe_layout: GLWEToLWEKeyLayout {
|
||||||
|
n: Degree(N_GLWE),
|
||||||
|
base2k: Base2K(BASE2K),
|
||||||
|
k: TorusPrecision(4 * BASE2K),
|
||||||
|
rank_in: Rank(RANK),
|
||||||
|
dnum: Dnum(4),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let module = Module::<BE>::new(N_GLWE as u64);
|
||||||
|
|
||||||
|
// Secret key sampling source
|
||||||
|
let mut source_xs: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
// Public randomness sampling source
|
||||||
|
let mut source_xa: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
// Noise sampling source
|
||||||
|
let mut source_xe: Source = Source::new([1u8; 32]);
|
||||||
|
|
||||||
|
// Scratch space (4MB)
|
||||||
|
let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 22);
|
||||||
|
|
||||||
|
////////// Key Generation and Preparation
|
||||||
|
// Generating the GLWE and LWE key
|
||||||
|
let mut sk_glwe = GLWESecret::alloc_from_infos(&glwe_layout);
|
||||||
|
sk_glwe.fill_ternary_prob(0.5, &mut source_xs);
|
||||||
|
|
||||||
|
let mut sk_lwe = LWESecret::alloc(Degree(N_LWE));
|
||||||
|
sk_lwe.fill_binary_block(BINARY_BLOCK_SIZE as usize, &mut source_xs);
|
||||||
|
|
||||||
|
// Preparing the private keys
|
||||||
|
let mut sk_glwe_prepared = GLWESecretPrepared::alloc_from_infos(&module, &glwe_layout);
|
||||||
|
sk_glwe_prepared.prepare(&module, &sk_glwe);
|
||||||
|
|
||||||
|
// Creating the public BDD Key
|
||||||
|
// This key is required to prepare all Fhe Integers for operations,
|
||||||
|
// and for performing the operations themselves
|
||||||
|
let mut bdd_key: BDDKey<Vec<u8>, BRA> = BDDKey::alloc_from_infos(&bdd_layout);
|
||||||
|
bdd_key.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
&sk_lwe,
|
||||||
|
&sk_glwe,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
////////// Input Encryption
|
||||||
|
// Encrypting the inputs
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
let inputs: Vec<u32> = (0..3).map(|_| rng.random_range(0..u32::MAX - 1)).collect();
|
||||||
|
|
||||||
|
let mut inputs_enc: Vec<FheUint<Vec<u8>, u32>> = Vec::new();
|
||||||
|
for input in &inputs {
|
||||||
|
let mut next_input = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
next_input.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
*input,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
inputs_enc.push(next_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// Homomorphic computation starts here ////////
|
||||||
|
|
||||||
|
// Preparing the BDD Key
|
||||||
|
// The BDD key must be prepared once before any operation is performed
|
||||||
|
let mut bdd_key_prepared: BDDKeyPrepared<Vec<u8>, BRA, BE> = BDDKeyPrepared::alloc_from_infos(&module, &bdd_layout);
|
||||||
|
bdd_key_prepared.prepare(&module, &bdd_key, scratch.borrow());
|
||||||
|
|
||||||
|
let mut max_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
max_enc.encrypt_sk(
|
||||||
|
&module,
|
||||||
|
0,
|
||||||
|
&sk_glwe_prepared,
|
||||||
|
&mut source_xa,
|
||||||
|
&mut source_xe,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
// Copy of max_enc for the HashMap
|
||||||
|
let mut max_enc_copy: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
|
||||||
|
// Allocating the intermediate ciphertext c_enc
|
||||||
|
let mut compare_enc: FheUint<Vec<u8>, u32> = FheUint::alloc_from_infos(&glwe_layout);
|
||||||
|
let mut compare_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> = FheUintPrepared::alloc_from_infos(&module, &ggsw_layout);
|
||||||
|
|
||||||
|
for input_i in inputs_enc.iter_mut() {
|
||||||
|
let mut max_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> = FheUintPrepared::alloc_from_infos(&module, &ggsw_layout);
|
||||||
|
max_enc_prepared.prepare(&module, &max_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
let mut input_i_enc_prepared: FheUintPrepared<Vec<u8>, u32, BE> =
|
||||||
|
FheUintPrepared::alloc_from_infos(&module, &ggsw_layout);
|
||||||
|
input_i_enc_prepared.prepare(&module, &input_i, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
// b = (input_i < max)
|
||||||
|
compare_enc.sltu(
|
||||||
|
&module,
|
||||||
|
&input_i_enc_prepared,
|
||||||
|
&max_enc_prepared,
|
||||||
|
&bdd_key_prepared,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
compare_enc_prepared.prepare(&module, &compare_enc, &bdd_key_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
module.glwe_copy(&mut max_enc_copy.to_mut(), &max_enc.to_ref());
|
||||||
|
|
||||||
|
let cts = HashMap::from([(0, input_i), (1, &mut max_enc_copy)]);
|
||||||
|
|
||||||
|
<Module<BE> as GLWEBlindSelection<u32, BE>>::glwe_blind_selection(
|
||||||
|
&module,
|
||||||
|
&mut max_enc,
|
||||||
|
cts,
|
||||||
|
&compare_enc_prepared,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
scratch.borrow(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// Homomorphic computation ends here ////////
|
||||||
|
|
||||||
|
// Decrypting the result
|
||||||
|
let result_dec = max_enc.decrypt(&module, &sk_glwe_prepared, scratch.borrow());
|
||||||
|
|
||||||
|
// result = max of inputs
|
||||||
|
let result_correct = inputs.iter().max().unwrap();
|
||||||
|
println!("Result: {} == {}", result_dec, result_correct);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
#[cfg(all(feature = "enable-avx", target_arch = "x86_64"))]
|
||||||
|
example_max_array::<FFT64Avx, CGGI>();
|
||||||
|
|
||||||
|
#[cfg(not(all(feature = "enable-avx", target_arch = "x86_64")))]
|
||||||
|
example_max_array::<FFT64Ref, CGGI>();
|
||||||
|
}
|
||||||
@@ -188,15 +188,35 @@ macro_rules! impl_bdd_2w_to_1w_trait {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a + b
|
||||||
define_bdd_2w_to_1w_trait!(pub Add, add);
|
define_bdd_2w_to_1w_trait!(pub Add, add);
|
||||||
|
|
||||||
|
// a - b
|
||||||
define_bdd_2w_to_1w_trait!(pub Sub, sub);
|
define_bdd_2w_to_1w_trait!(pub Sub, sub);
|
||||||
|
|
||||||
|
// a << b
|
||||||
define_bdd_2w_to_1w_trait!(pub Sll, sll);
|
define_bdd_2w_to_1w_trait!(pub Sll, sll);
|
||||||
|
|
||||||
|
// a >> b arithmetic
|
||||||
define_bdd_2w_to_1w_trait!(pub Sra, sra);
|
define_bdd_2w_to_1w_trait!(pub Sra, sra);
|
||||||
|
|
||||||
|
// a >> b logical
|
||||||
define_bdd_2w_to_1w_trait!(pub Srl, srl);
|
define_bdd_2w_to_1w_trait!(pub Srl, srl);
|
||||||
|
|
||||||
|
// signed a < signed b
|
||||||
define_bdd_2w_to_1w_trait!(pub Slt, slt);
|
define_bdd_2w_to_1w_trait!(pub Slt, slt);
|
||||||
|
|
||||||
|
// unsigned a < unsigned b
|
||||||
define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
|
define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
|
||||||
|
|
||||||
|
// a or b
|
||||||
define_bdd_2w_to_1w_trait!(pub Or, or);
|
define_bdd_2w_to_1w_trait!(pub Or, or);
|
||||||
|
|
||||||
|
// a and b
|
||||||
define_bdd_2w_to_1w_trait!(pub And, and);
|
define_bdd_2w_to_1w_trait!(pub And, and);
|
||||||
|
|
||||||
|
// a xor b
|
||||||
define_bdd_2w_to_1w_trait!(pub Xor, xor);
|
define_bdd_2w_to_1w_trait!(pub Xor, xor);
|
||||||
|
|
||||||
impl_bdd_2w_to_1w_trait!(
|
impl_bdd_2w_to_1w_trait!(
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ use poulpy_hal::layouts::{Backend, Module, Scratch, ZnxZero};
|
|||||||
|
|
||||||
use crate::bin_fhe::bdd_arithmetic::{Cmux, GetGGSWBit, UnsignedInteger};
|
use crate::bin_fhe::bdd_arithmetic::{Cmux, GetGGSWBit, UnsignedInteger};
|
||||||
|
|
||||||
impl<T: UnsignedInteger, BE: Backend> GLWEBlinSelection<T, BE> for Module<BE> where Self: GLWECopy + Cmux<BE> + GLWEDecrypt<BE> {}
|
impl<T: UnsignedInteger, BE: Backend> GLWEBlindSelection<T, BE> for Module<BE> where Self: GLWECopy + Cmux<BE> + GLWEDecrypt<BE> {}
|
||||||
|
|
||||||
pub trait GLWEBlinSelection<T: UnsignedInteger, BE: Backend>
|
pub trait GLWEBlindSelection<T: UnsignedInteger, BE: Backend>
|
||||||
where
|
where
|
||||||
Self: GLWECopy + Cmux<BE> + GLWEDecrypt<BE>,
|
Self: GLWECopy + Cmux<BE> + GLWEDecrypt<BE>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ impl<D: DataMut, T: UnsignedInteger + ToBits> FheUint<D, T> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
module: &M,
|
module: &M,
|
||||||
data: T,
|
data: T,
|
||||||
sk: &S,
|
sk_glwe: &S,
|
||||||
source_xa: &mut Source,
|
source_xa: &mut Source,
|
||||||
source_xe: &mut Source,
|
source_xe: &mut Source,
|
||||||
scratch: &mut Scratch<BE>,
|
scratch: &mut Scratch<BE>,
|
||||||
@@ -100,7 +100,7 @@ impl<D: DataMut, T: UnsignedInteger + ToBits> FheUint<D, T> {
|
|||||||
{
|
{
|
||||||
assert!(module.n().is_multiple_of(T::BITS as usize));
|
assert!(module.n().is_multiple_of(T::BITS as usize));
|
||||||
assert_eq!(self.n(), module.n() as u32);
|
assert_eq!(self.n(), module.n() as u32);
|
||||||
assert_eq!(sk.n(), module.n() as u32);
|
assert_eq!(sk_glwe.n(), module.n() as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut data_bits: Vec<i64> = vec![0i64; module.n()];
|
let mut data_bits: Vec<i64> = vec![0i64; module.n()];
|
||||||
@@ -122,7 +122,7 @@ impl<D: DataMut, T: UnsignedInteger + ToBits> FheUint<D, T> {
|
|||||||
|
|
||||||
pt.encode_vec_i64(&data_bits, TorusPrecision(2));
|
pt.encode_vec_i64(&data_bits, TorusPrecision(2));
|
||||||
self.bits
|
self.bits
|
||||||
.encrypt_sk(module, &pt, sk, source_xa, source_xe, scratch_1);
|
.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, scratch_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ impl<D: DataRef, T: UnsignedInteger + FromBits> FheUint<D, T> {
|
|||||||
self.bits.noise(module, &pt, sk, scratch_1)
|
self.bits.noise(module, &pt, sk, scratch_1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt<S, M, BE: Backend>(&self, module: &M, sk: &S, scratch: &mut Scratch<BE>) -> T
|
pub fn decrypt<S, M, BE: Backend>(&self, module: &M, sk_glwe: &S, scratch: &mut Scratch<BE>) -> T
|
||||||
where
|
where
|
||||||
S: GLWESecretPreparedToRef<BE> + GLWEInfos,
|
S: GLWESecretPreparedToRef<BE> + GLWEInfos,
|
||||||
M: ModuleLogN + GLWEDecrypt<BE>,
|
M: ModuleLogN + GLWEDecrypt<BE>,
|
||||||
@@ -160,7 +160,7 @@ impl<D: DataRef, T: UnsignedInteger + FromBits> FheUint<D, T> {
|
|||||||
{
|
{
|
||||||
assert!(module.n().is_multiple_of(T::BITS as usize));
|
assert!(module.n().is_multiple_of(T::BITS as usize));
|
||||||
assert_eq!(self.n(), module.n() as u32);
|
assert_eq!(self.n(), module.n() as u32);
|
||||||
assert_eq!(sk.n(), module.n() as u32);
|
assert_eq!(sk_glwe.n(), module.n() as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pt_infos = GLWEPlaintextLayout {
|
let pt_infos = GLWEPlaintextLayout {
|
||||||
@@ -171,7 +171,7 @@ impl<D: DataRef, T: UnsignedInteger + FromBits> FheUint<D, T> {
|
|||||||
|
|
||||||
let (mut pt, scratch_1) = scratch.take_glwe_plaintext(&pt_infos);
|
let (mut pt, scratch_1) = scratch.take_glwe_plaintext(&pt_infos);
|
||||||
|
|
||||||
self.bits.decrypt(module, &mut pt, sk, scratch_1);
|
self.bits.decrypt(module, &mut pt, sk_glwe, scratch_1);
|
||||||
|
|
||||||
let mut data_bits: Vec<i64> = vec![0i64; module.n()];
|
let mut data_bits: Vec<i64> = vec![0i64; module.n()];
|
||||||
pt.decode_vec_i64(&mut data_bits, TorusPrecision(2));
|
pt.decode_vec_i64(&mut data_bits, TorusPrecision(2));
|
||||||
|
|||||||
@@ -34,22 +34,22 @@ pub trait BDDKeyInfos {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct BDDKeyLayout {
|
pub struct BDDKeyLayout {
|
||||||
pub cbt: CircuitBootstrappingKeyLayout,
|
pub cbt_layout: CircuitBootstrappingKeyLayout,
|
||||||
pub ks_glwe: Option<GLWESwitchingKeyLayout>,
|
pub ks_glwe_layout: Option<GLWESwitchingKeyLayout>,
|
||||||
pub ks_lwe: GLWEToLWEKeyLayout,
|
pub ks_lwe_layout: GLWEToLWEKeyLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BDDKeyInfos for BDDKeyLayout {
|
impl BDDKeyInfos for BDDKeyLayout {
|
||||||
fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
|
fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
|
||||||
self.cbt
|
self.cbt_layout
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
|
fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
|
||||||
self.ks_glwe
|
self.ks_glwe_layout
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout {
|
fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout {
|
||||||
self.ks_lwe
|
self.ks_lwe_layout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,9 +176,9 @@ where
|
|||||||
impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BDDKeyInfos for BDDKeyPrepared<D, BRA, BE> {
|
impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BDDKeyInfos for BDDKeyPrepared<D, BRA, BE> {
|
||||||
fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
|
fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
|
||||||
CircuitBootstrappingKeyLayout {
|
CircuitBootstrappingKeyLayout {
|
||||||
layout_brk: self.cbt.brk_infos(),
|
brk_layout: self.cbt.brk_infos(),
|
||||||
layout_atk: self.cbt.atk_infos(),
|
atk_layout: self.cbt.atk_infos(),
|
||||||
layout_tsk: self.cbt.tsk_infos(),
|
tsk_layout: self.cbt.tsk_infos(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
|
fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use rand::RngCore;
|
|||||||
|
|
||||||
use crate::bin_fhe::{
|
use crate::bin_fhe::{
|
||||||
bdd_arithmetic::{
|
bdd_arithmetic::{
|
||||||
FheUintPrepared, GLWEBlinSelection,
|
FheUintPrepared, GLWEBlindSelection,
|
||||||
tests::test_suite::{TEST_FHEUINT_BASE2K, TEST_RANK, TestContext},
|
tests::test_suite::{TEST_FHEUINT_BASE2K, TEST_RANK, TestContext},
|
||||||
},
|
},
|
||||||
blind_rotation::BlindRotationAlgo,
|
blind_rotation::BlindRotationAlgo,
|
||||||
@@ -28,7 +28,7 @@ where
|
|||||||
+ GLWESecretPreparedFactory<BE>
|
+ GLWESecretPreparedFactory<BE>
|
||||||
+ GGSWPreparedFactory<BE>
|
+ GGSWPreparedFactory<BE>
|
||||||
+ GGSWEncryptSk<BE>
|
+ GGSWEncryptSk<BE>
|
||||||
+ GLWEBlinSelection<u32, BE>
|
+ GLWEBlindSelection<u32, BE>
|
||||||
+ GLWEDecrypt<BE>
|
+ GLWEDecrypt<BE>
|
||||||
+ GLWEEncryptSk<BE>,
|
+ GLWEEncryptSk<BE>,
|
||||||
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
|
||||||
|
|||||||
@@ -165,8 +165,8 @@ pub(crate) static TEST_GGSW_INFOS: GGSWLayout = GGSWLayout {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) static TEST_BDD_KEY_LAYOUT: BDDKeyLayout = BDDKeyLayout {
|
pub(crate) static TEST_BDD_KEY_LAYOUT: BDDKeyLayout = BDDKeyLayout {
|
||||||
cbt: CircuitBootstrappingKeyLayout {
|
cbt_layout: CircuitBootstrappingKeyLayout {
|
||||||
layout_brk: BlindRotationKeyLayout {
|
brk_layout: BlindRotationKeyLayout {
|
||||||
n_glwe: Degree(TEST_N_GLWE),
|
n_glwe: Degree(TEST_N_GLWE),
|
||||||
n_lwe: Degree(TEST_N_LWE),
|
n_lwe: Degree(TEST_N_LWE),
|
||||||
base2k: Base2K(TEST_BRK_BASE2K),
|
base2k: Base2K(TEST_BRK_BASE2K),
|
||||||
@@ -174,7 +174,7 @@ pub(crate) static TEST_BDD_KEY_LAYOUT: BDDKeyLayout = BDDKeyLayout {
|
|||||||
dnum: Dnum(4),
|
dnum: Dnum(4),
|
||||||
rank: Rank(TEST_RANK),
|
rank: Rank(TEST_RANK),
|
||||||
},
|
},
|
||||||
layout_atk: GLWEAutomorphismKeyLayout {
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
n: Degree(TEST_N_GLWE),
|
n: Degree(TEST_N_GLWE),
|
||||||
base2k: Base2K(TEST_ATK_BASE2K),
|
base2k: Base2K(TEST_ATK_BASE2K),
|
||||||
k: TorusPrecision(52),
|
k: TorusPrecision(52),
|
||||||
@@ -182,7 +182,7 @@ pub(crate) static TEST_BDD_KEY_LAYOUT: BDDKeyLayout = BDDKeyLayout {
|
|||||||
dnum: Dnum(4),
|
dnum: Dnum(4),
|
||||||
dsize: Dsize(1),
|
dsize: Dsize(1),
|
||||||
},
|
},
|
||||||
layout_tsk: GGLWEToGGSWKeyLayout {
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
n: Degree(TEST_N_GLWE),
|
n: Degree(TEST_N_GLWE),
|
||||||
base2k: Base2K(TEST_TSK_BASE2K),
|
base2k: Base2K(TEST_TSK_BASE2K),
|
||||||
k: TorusPrecision(52),
|
k: TorusPrecision(52),
|
||||||
@@ -191,7 +191,7 @@ pub(crate) static TEST_BDD_KEY_LAYOUT: BDDKeyLayout = BDDKeyLayout {
|
|||||||
dsize: Dsize(1),
|
dsize: Dsize(1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ks_glwe: Some(GLWESwitchingKeyLayout {
|
ks_glwe_layout: Some(GLWESwitchingKeyLayout {
|
||||||
n: Degree(TEST_N_GLWE),
|
n: Degree(TEST_N_GLWE),
|
||||||
base2k: Base2K(TEST_LWE_BASE2K),
|
base2k: Base2K(TEST_LWE_BASE2K),
|
||||||
k: TorusPrecision(20),
|
k: TorusPrecision(20),
|
||||||
@@ -200,7 +200,7 @@ pub(crate) static TEST_BDD_KEY_LAYOUT: BDDKeyLayout = BDDKeyLayout {
|
|||||||
dnum: Dnum(3),
|
dnum: Dnum(3),
|
||||||
dsize: Dsize(1),
|
dsize: Dsize(1),
|
||||||
}),
|
}),
|
||||||
ks_lwe: GLWEToLWEKeyLayout {
|
ks_lwe_layout: GLWEToLWEKeyLayout {
|
||||||
n: Degree(TEST_N_GLWE),
|
n: Degree(TEST_N_GLWE),
|
||||||
base2k: Base2K(TEST_LWE_BASE2K),
|
base2k: Base2K(TEST_LWE_BASE2K),
|
||||||
k: TorusPrecision(16),
|
k: TorusPrecision(16),
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ pub trait CircuitBootstrappingKeyInfos {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct CircuitBootstrappingKeyLayout {
|
pub struct CircuitBootstrappingKeyLayout {
|
||||||
pub layout_brk: BlindRotationKeyLayout,
|
pub brk_layout: BlindRotationKeyLayout,
|
||||||
pub layout_atk: GLWEAutomorphismKeyLayout,
|
pub atk_layout: GLWEAutomorphismKeyLayout,
|
||||||
pub layout_tsk: GGLWEToGGSWKeyLayout,
|
pub tsk_layout: GGLWEToGGSWKeyLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyLayout {
|
impl CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyLayout {
|
||||||
@@ -38,15 +38,15 @@ impl CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn atk_infos(&self) -> GLWEAutomorphismKeyLayout {
|
fn atk_infos(&self) -> GLWEAutomorphismKeyLayout {
|
||||||
self.layout_atk
|
self.atk_layout
|
||||||
}
|
}
|
||||||
|
|
||||||
fn brk_infos(&self) -> BlindRotationKeyLayout {
|
fn brk_infos(&self) -> BlindRotationKeyLayout {
|
||||||
self.layout_brk
|
self.brk_layout
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tsk_infos(&self) -> GGLWEToGGSWKeyLayout {
|
fn tsk_infos(&self) -> GGLWEToGGSWKeyLayout {
|
||||||
self.layout_tsk
|
self.tsk_layout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let cbt_infos: CircuitBootstrappingKeyLayout = CircuitBootstrappingKeyLayout {
|
let cbt_infos: CircuitBootstrappingKeyLayout = CircuitBootstrappingKeyLayout {
|
||||||
layout_brk: BlindRotationKeyLayout {
|
brk_layout: BlindRotationKeyLayout {
|
||||||
n_glwe: n_glwe.into(),
|
n_glwe: n_glwe.into(),
|
||||||
n_lwe: n_lwe.into(),
|
n_lwe: n_lwe.into(),
|
||||||
base2k: base2k_brk.into(),
|
base2k: base2k_brk.into(),
|
||||||
@@ -86,7 +86,7 @@ where
|
|||||||
dnum: rows_brk.into(),
|
dnum: rows_brk.into(),
|
||||||
rank: rank.into(),
|
rank: rank.into(),
|
||||||
},
|
},
|
||||||
layout_atk: GLWEAutomorphismKeyLayout {
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
n: n_glwe.into(),
|
n: n_glwe.into(),
|
||||||
base2k: base2k_atk.into(),
|
base2k: base2k_atk.into(),
|
||||||
k: k_atk.into(),
|
k: k_atk.into(),
|
||||||
@@ -94,7 +94,7 @@ where
|
|||||||
rank: rank.into(),
|
rank: rank.into(),
|
||||||
dsize: Dsize(1),
|
dsize: Dsize(1),
|
||||||
},
|
},
|
||||||
layout_tsk: GGLWEToGGSWKeyLayout {
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
n: n_glwe.into(),
|
n: n_glwe.into(),
|
||||||
base2k: base2k_tsk.into(),
|
base2k: base2k_tsk.into(),
|
||||||
k: k_tsk.into(),
|
k: k_tsk.into(),
|
||||||
@@ -285,7 +285,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let cbt_infos: CircuitBootstrappingKeyLayout = CircuitBootstrappingKeyLayout {
|
let cbt_infos: CircuitBootstrappingKeyLayout = CircuitBootstrappingKeyLayout {
|
||||||
layout_brk: BlindRotationKeyLayout {
|
brk_layout: BlindRotationKeyLayout {
|
||||||
n_glwe: n_glwe.into(),
|
n_glwe: n_glwe.into(),
|
||||||
n_lwe: n_lwe.into(),
|
n_lwe: n_lwe.into(),
|
||||||
base2k: base2k_brk.into(),
|
base2k: base2k_brk.into(),
|
||||||
@@ -293,7 +293,7 @@ where
|
|||||||
dnum: rows_brk.into(),
|
dnum: rows_brk.into(),
|
||||||
rank: rank.into(),
|
rank: rank.into(),
|
||||||
},
|
},
|
||||||
layout_atk: GLWEAutomorphismKeyLayout {
|
atk_layout: GLWEAutomorphismKeyLayout {
|
||||||
n: n_glwe.into(),
|
n: n_glwe.into(),
|
||||||
base2k: base2k_atk.into(),
|
base2k: base2k_atk.into(),
|
||||||
k: k_atk.into(),
|
k: k_atk.into(),
|
||||||
@@ -301,7 +301,7 @@ where
|
|||||||
rank: rank.into(),
|
rank: rank.into(),
|
||||||
dsize: Dsize(1),
|
dsize: Dsize(1),
|
||||||
},
|
},
|
||||||
layout_tsk: GGLWEToGGSWKeyLayout {
|
tsk_layout: GGLWEToGGSWKeyLayout {
|
||||||
n: n_glwe.into(),
|
n: n_glwe.into(),
|
||||||
base2k: base2k_tsk.into(),
|
base2k: base2k_tsk.into(),
|
||||||
k: k_tsk.into(),
|
k: k_tsk.into(),
|
||||||
|
|||||||
Reference in New Issue
Block a user