-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(hlapi): add glwe compression c-api
- Loading branch information
1 parent
25e7158
commit 82f2d4a
Showing
4 changed files
with
381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
#include "tfhe.h" | ||
|
||
#include <assert.h> | ||
#include <stdbool.h> | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
|
||
int main(void) { | ||
int ok = 0; | ||
|
||
// First, we create a ClientKey and a CompactPublicKey | ||
ClientKey *client_key = NULL; | ||
ServerKey *server_key = NULL; | ||
|
||
{ | ||
ConfigBuilder *builder; | ||
Config *config; | ||
ok = config_builder_default(&builder); | ||
assert(ok == 0); | ||
|
||
config_builder_enable_compression(&builder, COMP_PARAMS_FOR_MESSAGE_2_CARRY_2_KS_PBS); | ||
|
||
ok = config_builder_build(builder, &config); | ||
assert(ok == 0); | ||
|
||
ok = generate_keys(config, &client_key, &server_key); | ||
assert(ok == 0); | ||
|
||
ok = set_server_key(server_key); | ||
assert(ok == 0); | ||
} | ||
|
||
// Then, we create the compact list | ||
CompressedCiphertextList *list = NULL; | ||
{ | ||
CompressedCiphertextListBuilder *builder; | ||
ok = compressed_ciphertext_list_builder_new(&builder); | ||
assert(ok == 0); | ||
|
||
FheUint32 *a = NULL; | ||
FheInt64 *b = NULL; | ||
FheBool *c = NULL; | ||
FheUint2 *d = NULL; | ||
|
||
// Encrypt | ||
{ | ||
ok = fhe_uint32_try_encrypt_with_client_key_u32(38382, client_key, &a); | ||
assert(ok == 0); | ||
|
||
ok = fhe_int64_try_encrypt_with_client_key_i64(-1, client_key, &b); | ||
assert(ok == 0); | ||
|
||
ok = fhe_bool_try_encrypt_with_client_key_bool(true, client_key, &c); | ||
assert(ok == 0); | ||
|
||
ok = fhe_uint2_try_encrypt_with_client_key_u8(3, client_key, &d); | ||
assert(ok == 0); | ||
} | ||
|
||
// Push some values | ||
ok = compressed_ciphertext_list_builder_push_u32(builder, a); | ||
assert(ok == 0); | ||
|
||
ok = compressed_ciphertext_list_builder_push_i64(builder, b); | ||
assert(ok == 0); | ||
|
||
ok = compressed_ciphertext_list_builder_push_bool(builder, c); | ||
assert(ok == 0); | ||
|
||
ok = compressed_ciphertext_list_builder_push_u2(builder, d); | ||
assert(ok == 0); | ||
|
||
ok = compressed_ciphertext_list_builder_build(builder, &list); | ||
assert(ok == 0); | ||
|
||
// Don't forget to destroy the builder | ||
compressed_ciphertext_list_builder_destroy(builder); | ||
} | ||
|
||
// Now we can expand values | ||
FheUint32 *a = NULL; | ||
FheInt64 *b = NULL; | ||
FheBool *c = NULL; | ||
FheUint2 *d = NULL; | ||
{ | ||
FheTypes type = Type_FheBool; | ||
|
||
size_t len = 0; | ||
ok = compressed_ciphertext_list_len(list, &len); | ||
assert(ok == 0 && len == 4); | ||
|
||
// First, an example of getting the type in a slot | ||
ok = compressed_ciphertext_list_get_kind_of(list, 0, &type); | ||
assert(ok == 0 && type == Type_FheUint32); | ||
|
||
ok = compressed_ciphertext_list_get_kind_of(list, 1, &type); | ||
assert(ok == 0 && type == Type_FheInt64); | ||
|
||
ok = compressed_ciphertext_list_get_kind_of(list, 2, &type); | ||
assert(ok == 0 && type == Type_FheBool); | ||
|
||
ok = compressed_ciphertext_list_get_kind_of(list, 3, &type); | ||
assert(ok == 0 && type == Type_FheUint2); | ||
|
||
// Then how to get the values | ||
ok = compressed_ciphertext_list_get_fhe_uint32(list, 0, &a); | ||
assert(ok == 0); | ||
|
||
ok = compressed_ciphertext_list_get_fhe_int64(list, 1, &b); | ||
assert(ok == 0); | ||
|
||
ok = compressed_ciphertext_list_get_fhe_bool(list, 2, &c); | ||
assert(ok == 0); | ||
|
||
ok = compressed_ciphertext_list_get_fhe_uint2(list, 3, &d); | ||
assert(ok == 0); | ||
} | ||
|
||
uint32_t clear_a = 0; | ||
ok = fhe_uint32_decrypt(a, client_key, &clear_a); | ||
assert(ok == 0); | ||
assert(clear_a == 38382); | ||
|
||
int64_t clear_b = 0; | ||
ok = fhe_int64_decrypt(b, client_key, &clear_b); | ||
assert(ok == 0); | ||
assert(clear_b == -1); | ||
|
||
bool clear_c = false; | ||
ok = fhe_bool_decrypt(c, client_key, &clear_c); | ||
assert(ok == 0); | ||
assert(clear_c == true); | ||
|
||
uint8_t clear_d = 0; | ||
ok = fhe_uint2_decrypt(d, client_key, &clear_d); | ||
assert(ok == 0); | ||
assert(clear_d == 3); | ||
|
||
fhe_uint32_destroy(a); | ||
fhe_int64_destroy(b); | ||
fhe_bool_destroy(c); | ||
fhe_uint2_destroy(d); | ||
client_key_destroy(client_key); | ||
return EXIT_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
use crate::c_api::high_level_api::booleans::FheBool; | ||
use crate::c_api::high_level_api::integers::{ | ||
FheInt10, FheInt12, FheInt128, FheInt14, FheInt16, FheInt160, FheInt2, FheInt256, FheInt32, | ||
FheInt4, FheInt6, FheInt64, FheInt8, FheUint10, FheUint12, FheUint128, FheUint14, FheUint16, | ||
FheUint160, FheUint2, FheUint256, FheUint32, FheUint4, FheUint6, FheUint64, FheUint8, | ||
}; | ||
use crate::c_api::high_level_api::utils::{ | ||
impl_destroy_on_type, impl_serialize_deserialize_on_type, | ||
}; | ||
use crate::c_api::utils::{catch_panic, get_mut_checked, get_ref_checked}; | ||
use std::ffi::c_int; | ||
|
||
pub struct CompressedCiphertextListBuilder(crate::high_level_api::CompressedCiphertextListBuilder); | ||
impl_destroy_on_type!(CompressedCiphertextListBuilder); | ||
|
||
pub struct CompressedCiphertextList(crate::high_level_api::CompressedCiphertextList); | ||
impl_destroy_on_type!(CompressedCiphertextList); | ||
impl_serialize_deserialize_on_type!(CompressedCiphertextList); | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn compressed_ciphertext_list_builder_new( | ||
builder: *mut *mut CompressedCiphertextListBuilder, | ||
) -> c_int { | ||
catch_panic(|| { | ||
let inner = crate::high_level_api::CompressedCiphertextListBuilder::new(); | ||
|
||
*builder = Box::into_raw(Box::new(CompressedCiphertextListBuilder(inner))); | ||
}) | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn compressed_ciphertext_list_builder_build( | ||
builder: *const CompressedCiphertextListBuilder, | ||
list: *mut *mut CompressedCiphertextList, | ||
) -> c_int { | ||
catch_panic(|| { | ||
let builder: &CompressedCiphertextListBuilder = get_ref_checked(builder).unwrap(); | ||
|
||
let inner = builder.0.build().unwrap(); | ||
|
||
*list = Box::into_raw(Box::new(CompressedCiphertextList(inner))); | ||
}) | ||
} | ||
|
||
/// Pushes a boolean into the list | ||
#[no_mangle] | ||
pub unsafe extern "C" fn compressed_ciphertext_list_builder_push_bool( | ||
builder: *mut CompressedCiphertextListBuilder, | ||
value: *const FheBool, | ||
) -> c_int { | ||
catch_panic(|| { | ||
let builder = get_mut_checked(builder).unwrap(); | ||
|
||
let value: &FheBool = get_ref_checked(value).unwrap(); | ||
|
||
builder.0.push(value.0.clone()); | ||
}) | ||
} | ||
|
||
macro_rules! define_compressed_ciphertext_list_builder_push_method { | ||
( | ||
unsigned: $($num_bits:literal),* | ||
$(,)? | ||
) => { | ||
::paste::paste!{ | ||
$( | ||
#[doc = concat!("Pushes an unsigned integer of ", stringify!($num_bits), " bits to the list")] | ||
#[no_mangle] | ||
pub unsafe extern "C" fn [<compressed_ciphertext_list_builder_push_u $num_bits>]( | ||
builder: *mut CompressedCiphertextListBuilder, | ||
value: *const [<FheUint $num_bits>], | ||
) -> c_int { | ||
catch_panic(|| { | ||
let builder = get_mut_checked(builder).unwrap(); | ||
|
||
let value: &[<FheUint $num_bits>] = get_ref_checked(value).unwrap(); | ||
|
||
|
||
builder.0.push(value.0.clone()); | ||
}) | ||
} | ||
)* | ||
} | ||
}; | ||
( | ||
signed: $($num_bits:literal),* | ||
$(,)? | ||
) => { | ||
::paste::paste!{ | ||
$( | ||
#[doc = concat!("Pushes a signed integer of ", stringify!($num_bits), " bits to the list")] | ||
#[no_mangle] | ||
pub unsafe extern "C" fn [<compressed_ciphertext_list_builder_push_i $num_bits>]( | ||
builder: *mut CompressedCiphertextListBuilder, | ||
value: *const [<FheInt $num_bits>], | ||
) -> c_int { | ||
catch_panic(|| { | ||
let builder = get_mut_checked(builder).unwrap(); | ||
|
||
let value: &[<FheInt $num_bits>] = get_ref_checked(value).unwrap(); | ||
|
||
builder.0.push(value.0.clone()); | ||
}) | ||
} | ||
)* | ||
} | ||
}; | ||
} | ||
|
||
define_compressed_ciphertext_list_builder_push_method!(unsigned: 2, 4, 6, 8, 10, 12, 14, 16, 32, 64, 128, 160, 256); | ||
define_compressed_ciphertext_list_builder_push_method!(signed: 2, 4, 6, 8, 10, 12, 14, 16, 32, 64, 128, 160, 256); | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn compressed_ciphertext_list_len( | ||
expander: *mut CompressedCiphertextList, | ||
out: *mut usize, | ||
) -> c_int { | ||
catch_panic(|| { | ||
let expander = get_ref_checked(expander).unwrap(); | ||
*out = expander.0.len(); | ||
}) | ||
} | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn compressed_ciphertext_list_get_kind_of( | ||
expander: *mut CompressedCiphertextList, | ||
index: usize, | ||
out: *mut super::FheTypes, | ||
) -> c_int { | ||
let mut result = None; | ||
catch_panic(|| { | ||
let expander = get_ref_checked(expander).unwrap(); | ||
result = expander.0.get_kind_of(index); | ||
}); | ||
result.map_or(1, |r| { | ||
*out = r.into(); | ||
0 | ||
}) | ||
} | ||
|
||
macro_rules! define_ciphertext_list_get { | ||
( | ||
unsigned: $($num_bits:literal),* | ||
$(,)? | ||
) => { | ||
::paste::paste!( | ||
$( | ||
#[no_mangle] | ||
pub unsafe extern "C" fn [<compressed_ciphertext_list_get_fhe_uint $num_bits>]( | ||
expander: *mut CompressedCiphertextList, | ||
index: usize, | ||
out: *mut *mut [<FheUint $num_bits>], | ||
) -> c_int { | ||
catch_panic(|| { | ||
let expander = get_mut_checked(expander).unwrap(); | ||
|
||
let inner = expander.0.get(index).unwrap().unwrap(); | ||
|
||
*out = Box::into_raw(Box::new([<FheUint $num_bits>](inner))); | ||
}) | ||
} | ||
)* | ||
); | ||
}; | ||
( | ||
signed: $($num_bits:literal),* | ||
$(,)? | ||
) => { | ||
::paste::paste!( | ||
$( | ||
#[no_mangle] | ||
pub unsafe extern "C" fn [<compressed_ciphertext_list_get_fhe_int $num_bits>]( | ||
expander: *mut CompressedCiphertextList, | ||
index: usize, | ||
out: *mut *mut [<FheInt $num_bits>], | ||
) -> c_int { | ||
catch_panic(|| { | ||
let expander = get_mut_checked(expander).unwrap(); | ||
|
||
let inner = expander.0.get(index).unwrap().unwrap(); | ||
|
||
*out = Box::into_raw(Box::new([<FheInt $num_bits>](inner))); | ||
}) | ||
} | ||
)* | ||
); | ||
} | ||
} | ||
|
||
define_ciphertext_list_get!(unsigned: 2, 4, 6, 8, 10, 12, 14, 16, 32, 64, 128, 160, 256); | ||
define_ciphertext_list_get!(signed: 2, 4, 6, 8, 10, 12, 14, 16, 32, 64, 128, 160, 256); | ||
|
||
#[no_mangle] | ||
pub unsafe extern "C" fn compressed_ciphertext_list_get_fhe_bool( | ||
expander: *mut CompressedCiphertextList, | ||
index: usize, | ||
out: *mut *mut FheBool, | ||
) -> c_int { | ||
catch_panic(|| { | ||
let expander = get_mut_checked(expander).unwrap(); | ||
|
||
let inner = expander.0.get(index).unwrap().unwrap(); | ||
|
||
*out = Box::into_raw(Box::new(FheBool(inner))); | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters