tfhe 1.7.0

TFHE-rs is a fully homomorphic encryption (FHE) library that implements Zama's variant of TFHE.
Documentation
use crate::c_api::high_level_api::booleans::FheBool;
use crate::c_api::high_level_api::i128::I128;
use crate::c_api::high_level_api::i256::I256;
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::keys::CompactPublicKey;
use crate::c_api::high_level_api::u128::U128;
use crate::c_api::high_level_api::u256::U256;
use crate::c_api::high_level_api::utils::{
    impl_destroy_on_type, impl_safe_deserialize_on_type, impl_safe_serialize_on_type,
    CApiIntegerType,
};
#[cfg(feature = "zk-pok")]
use crate::c_api::high_level_api::zk::{CompactPkeCrs, ZkComputeLoad};
use crate::c_api::utils::{catch_panic, get_mut_checked, get_ref_checked};
use crate::conformance::{ListSizeConstraint, ParameterSetConformant};
use crate::prelude::CiphertextList;
use std::ffi::c_int;

pub struct CompactCiphertextListBuilder(crate::high_level_api::CompactCiphertextListBuilder);
impl_destroy_on_type!(CompactCiphertextListBuilder);

pub struct CompactCiphertextList(crate::high_level_api::CompactCiphertextList);
impl_destroy_on_type!(CompactCiphertextList);
impl_safe_serialize_on_type!(CompactCiphertextList);
impl_safe_deserialize_on_type!(CompactCiphertextList);

#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_safe_deserialize_conformant(
    buffer_view: crate::c_api::buffer::DynamicBufferView,
    serialized_size_limit: u64,
    public_key: *const CompactPublicKey,
    expected_num_elements: usize,
    result: *mut *mut CompactCiphertextList,
) -> c_int {
    let rc = compact_ciphertext_list_safe_deserialize(buffer_view, serialized_size_limit, result);
    if rc != 0 {
        return rc;
    }
    catch_panic(|| {
        let pk = get_ref_checked(public_key).unwrap();
        let list = get_ref_checked(*result).unwrap();
        let params =
            crate::high_level_api::CompactCiphertextListConformanceParams::from_parameters_and_size_constraint(
                pk.0.parameters(),
                ListSizeConstraint::exact_size(expected_num_elements),
            );
        if !list.0.is_conformant(&params) {
            drop(Box::from_raw(*result));
            *result = std::ptr::null_mut();
            panic!("CompactCiphertextList is not conformant with the provided parameters");
        }
    })
}

#[cfg(feature = "zk-pok")]
pub struct ProvenCompactCiphertextList(crate::high_level_api::ProvenCompactCiphertextList);
#[cfg(feature = "zk-pok")]
impl_destroy_on_type!(ProvenCompactCiphertextList);
#[cfg(feature = "zk-pok")]
impl_safe_serialize_on_type!(ProvenCompactCiphertextList);
#[cfg(feature = "zk-pok")]
impl_safe_deserialize_on_type!(ProvenCompactCiphertextList);

#[cfg(feature = "zk-pok")]
#[no_mangle]
pub unsafe extern "C" fn proven_compact_ciphertext_list_safe_deserialize_conformant(
    buffer_view: crate::c_api::buffer::DynamicBufferView,
    serialized_size_limit: u64,
    public_key: *const CompactPublicKey,
    crs: *const CompactPkeCrs,
    result: *mut *mut ProvenCompactCiphertextList,
) -> c_int {
    let rc =
        proven_compact_ciphertext_list_safe_deserialize(buffer_view, serialized_size_limit, result);
    if rc != 0 {
        return rc;
    }
    catch_panic(|| {
        let pk = get_ref_checked(public_key).unwrap();
        let crs = get_ref_checked(crs).unwrap();
        let list = get_ref_checked(*result).unwrap();
        let params = crate::integer::ciphertext::IntegerProvenCompactCiphertextListConformanceParams::from_crs_and_parameters(
            pk.0.parameters(),
            &crs.0,
        );
        if !list.0.is_conformant(&params) {
            drop(Box::from_raw(*result));
            *result = std::ptr::null_mut();
            panic!("ProvenCompactCiphertextList is not conformant with the provided parameters");
        }
    })
}

#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_builder_new(
    compact_public_key: *const CompactPublicKey,
    builder: *mut *mut CompactCiphertextListBuilder,
) -> c_int {
    catch_panic(|| {
        let pk = get_ref_checked(compact_public_key).unwrap();

        let inner = crate::high_level_api::CompactCiphertextListBuilder::new(&pk.0);

        *builder = Box::into_raw(Box::new(CompactCiphertextListBuilder(inner)));
    })
}

#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_builder_build(
    builder: *const CompactCiphertextListBuilder,
    list: *mut *mut CompactCiphertextList,
) -> c_int {
    catch_panic(|| {
        let builder = get_ref_checked(builder).unwrap();

        let inner = builder.0.build();

        *list = Box::into_raw(Box::new(CompactCiphertextList(inner)));
    })
}

#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_builder_build_packed(
    builder: *const CompactCiphertextListBuilder,
    list: *mut *mut CompactCiphertextList,
) -> c_int {
    catch_panic(|| {
        let builder = get_ref_checked(builder).unwrap();

        let inner = builder.0.build_packed();

        *list = Box::into_raw(Box::new(CompactCiphertextList(inner)));
    })
}

#[cfg(feature = "zk-pok")]
#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_builder_build_with_proof_packed(
    builder: *const CompactCiphertextListBuilder,
    crs: *const CompactPkeCrs,
    metadata: *const u8,
    metadata_len: usize,
    compute_load: ZkComputeLoad,
    list: *mut *mut ProvenCompactCiphertextList,
) -> c_int {
    catch_panic(|| {
        let builder = get_ref_checked(builder).unwrap();
        let crs = get_ref_checked(crs).unwrap();

        let metadata = if metadata.is_null() {
            &[]
        } else {
            let _metadata_check_ptr = get_ref_checked(metadata).unwrap();
            core::slice::from_raw_parts(metadata, metadata_len)
        };

        let inner = builder
            .0
            .build_with_proof_packed(&crs.0, metadata, compute_load.into())
            .unwrap();

        *list = Box::into_raw(Box::new(ProvenCompactCiphertextList(inner)));
    })
}

/// Pushes a boolean into the list
#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_builder_push_bool(
    builder: *mut CompactCiphertextListBuilder,
    value: bool,
) -> c_int {
    catch_panic(|| {
        let builder = get_mut_checked(builder).unwrap();
        builder.0.push(value);
    })
}

macro_rules! define_compact_ciphertext_list_builder_push_method {
    (
        unsigned: $($num_bits:literal: $rust_ty:ty),* $(,)?
    ) => {
        ::paste::paste!{
            $(
                #[doc = concat!("Pushes an unsigned integer of ", stringify!($num_bits), " bits to the list")]
                #[no_mangle]
                pub unsafe extern "C" fn [<compact_ciphertext_list_builder_push_u $num_bits>](
                    builder: *mut CompactCiphertextListBuilder,
                    value: $rust_ty,
                ) -> c_int {
                    catch_panic(|| {
                        let builder = get_mut_checked(builder).unwrap();
                        builder.0.push_with_num_bits(value.to_rust(), $num_bits).unwrap();
                    })
                }
            )*
        }
    };
    (
        signed: $($num_bits:literal: $rust_ty:ty),* $(,)?
    ) => {
        ::paste::paste!{
            $(
                #[doc = concat!("Pushes a signed integer of ", stringify!($num_bits), " bits to the list")]
                #[no_mangle]
                pub unsafe extern "C" fn [<compact_ciphertext_list_builder_push_i $num_bits>](
                    builder: *mut CompactCiphertextListBuilder,
                    value: $rust_ty,
                ) -> c_int {
                    catch_panic(|| {
                        let builder = get_mut_checked(builder).unwrap();
                        builder.0.push_with_num_bits(value.to_rust(), $num_bits).unwrap();
                    })
                }
            )*
        }
    };
}

define_compact_ciphertext_list_builder_push_method!(
    unsigned: 2: u8, 4: u8, 6: u8, 8: u8, 10: u16, 12: u16, 14: u16, 16: u16, 32: u32, 64: u64, 128: U128, 160: U256, 256: U256
);
define_compact_ciphertext_list_builder_push_method!(
    signed: 2: i8, 4: i8, 6: i8, 8: i8, 10: i16, 12: i16, 14: i16, 16: i16, 32: i32, 64: i64, 128: I128, 160: I256, 256: I256
);

#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_expand(
    compact_list: *const CompactCiphertextList,
    expander: *mut *mut CompactCiphertextListExpander,
) -> c_int {
    catch_panic(|| {
        let list = get_ref_checked(compact_list).unwrap();

        let inner = list.0.expand().unwrap();

        *expander = Box::into_raw(Box::new(CompactCiphertextListExpander(inner)));
    })
}

#[cfg(feature = "zk-pok")]
#[no_mangle]
pub unsafe extern "C" fn proven_compact_ciphertext_list_verify_and_expand(
    compact_list: *const ProvenCompactCiphertextList,
    crs: *const CompactPkeCrs,
    public_key: *const CompactPublicKey,
    metadata: *const u8,
    metadata_len: usize,
    expander: *mut *mut CompactCiphertextListExpander,
) -> c_int {
    catch_panic(|| {
        let list = get_ref_checked(compact_list).unwrap();
        let crs = get_ref_checked(crs).unwrap();
        let public_key = get_ref_checked(public_key).unwrap();

        let metadata = if metadata.is_null() {
            &[]
        } else {
            let _metadata_check_ptr = get_ref_checked(metadata).unwrap();
            core::slice::from_raw_parts(metadata, metadata_len)
        };

        let inner = list
            .0
            .verify_and_expand(&crs.0, &public_key.0, metadata)
            .unwrap();

        *expander = Box::into_raw(Box::new(CompactCiphertextListExpander(inner)));
    })
}

#[cfg(feature = "zk-pok")]
#[no_mangle]
pub unsafe extern "C" fn proven_compact_ciphertext_list_expand_without_verification(
    compact_list: *const ProvenCompactCiphertextList,
    expander: *mut *mut CompactCiphertextListExpander,
) -> c_int {
    catch_panic(|| {
        let list = get_ref_checked(compact_list).unwrap();

        let inner = list.0.expand_without_verification().unwrap();

        *expander = Box::into_raw(Box::new(CompactCiphertextListExpander(inner)));
    })
}

#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_expander_len(
    expander: *mut CompactCiphertextListExpander,
    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 compact_ciphertext_list_expander_get_kind_of(
    expander: *mut CompactCiphertextListExpander,
    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_compact_ciphertext_list_expander_get {
    (
        unsigned: $($num_bits:literal),*
        $(,)?
    ) => {
        ::paste::paste!(
            $(
                #[no_mangle]
                pub unsafe extern "C" fn [<compact_ciphertext_list_expander_get_fhe_uint $num_bits>](
                    expander: *mut CompactCiphertextListExpander,
                    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 [<compact_ciphertext_list_expander_get_fhe_int $num_bits>](
                    expander: *mut CompactCiphertextListExpander,
                    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)));
                    })
                }
            )*
        );
    }
}

pub struct CompactCiphertextListExpander(crate::high_level_api::CompactCiphertextListExpander);
impl_destroy_on_type!(CompactCiphertextListExpander);

define_compact_ciphertext_list_expander_get!(unsigned: 2, 4, 6, 8, 10, 12, 14, 16, 32, 64, 128, 160, 256);
define_compact_ciphertext_list_expander_get!(signed: 2, 4, 6, 8, 10, 12, 14, 16, 32, 64, 128, 160, 256);

#[no_mangle]
pub unsafe extern "C" fn compact_ciphertext_list_expander_get_fhe_bool(
    expander: *mut CompactCiphertextListExpander,
    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)));
    })
}