enhance(runtime): Move to the official concrete-core-ffi release 0.2.0-rc2

Co-authored-by: Mayeul@Zama <mayeul.debellabre@zama.ai>
Co-authored-by: Quentin Bourgerie <bourgerie.quentin@gmail.com>
This commit is contained in:
Mayeul@Zama
2022-06-20 17:53:47 +02:00
committed by mayeul-zama
parent 393d1617eb
commit eb4b0753dc
19 changed files with 540 additions and 195 deletions

2
compiler/.gitignore vendored
View File

@@ -1,4 +1,4 @@
.dependencies/
build/
*.mlir.script
*.lit_test_times.txt
concrete-core-ffi*

View File

@@ -53,7 +53,7 @@ set(CONCRETELANG_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# -------------------------------------------------------------------------------
include_directories(${CONCRETE_FFI_RELEASE})
add_library(Concrete STATIC IMPORTED)
set_target_properties(Concrete PROPERTIES IMPORTED_LOCATION ${CONCRETE_FFI_RELEASE}/libconcrete_ffi.a)
set_target_properties(Concrete PROPERTIES IMPORTED_LOCATION ${CONCRETE_FFI_RELEASE}/libconcrete_core_ffi.a)
# -------------------------------------------------------------------------------
# Python Configuration

View File

@@ -18,6 +18,13 @@ HPX_TARBALL=$(shell pwd)/hpx-$(HPX_VERSION).tar.gz
HPX_LOCAL_DIR=$(shell pwd)/hpx-$(HPX_VERSION)
HPX_INSTALL_DIR?=$(HPX_LOCAL_DIR)
CONCRETE_CORE_FFI_VERSION?=0.2.0-rc.2
ifeq ($(shell uname), Linux)
CONCRETE_CORE_FFI_TARBALL=concrete-core-ffi_$(CONCRETE_CORE_FFI_VERSION)_linux_amd64.tar.gz
else
CONCRETE_CORE_FFI_TARBALL=concrete-core-ffi_$(CONCRETE_CORE_FFI_VERSION)_darwin_amd64.tar.gz
endif
export PATH := $(abspath $(BUILD_DIR))/bin:$(PATH)
ifeq ($(shell which ccache),)
@@ -53,6 +60,46 @@ endif
all: concretecompiler python-bindings build-tests build-benchmarks doc
# concrete-core-ffi #######################################
CONCRETE_CORE_FFI_FOLDER = $(shell pwd)/concrete-core-ffi-$(CONCRETE_CORE_FFI_VERSION)
CONCRETE_CORE_FFI_ARTIFACTS=$(CONCRETE_CORE_FFI_FOLDER)/libconcrete_core_ffi.a $(CONCRETE_CORE_FFI_FOLDER)/concrete-core-ffi.h
concrete-core-ffi: $(CONCRETE_CORE_FFI_ARTIFACTS)
$(CONCRETE_CORE_FFI_ARTIFACTS): $(CONCRETE_CORE_FFI_FOLDER)
$(CONCRETE_CORE_FFI_FOLDER): $(CONCRETE_CORE_FFI_TARBALL)
mkdir -p $(CONCRETE_CORE_FFI_FOLDER)
tar -xvzf $(CONCRETE_CORE_FFI_TARBALL) --directory $(CONCRETE_CORE_FFI_FOLDER)
$(CONCRETE_CORE_FFI_TARBALL):
curl -L https://github.com/zama-ai/concrete-core/releases/download/concrete-core-ffi-$(CONCRETE_CORE_FFI_VERSION)/$(CONCRETE_CORE_FFI_TARBALL) -o $(CONCRETE_CORE_FFI_TARBALL)
# concrete-optimizer ######################################
LIB_CONCRETE_OPTIMIZER_CPP = $(CONCRETE_OPTIMIZER_DIR)/target/libconcrete_optimizer_cpp.a
concrete-optimizer-lib:
make -C $(CONCRETE_OPTIMIZER_DIR)/concrete-optimizer-cpp $(LIB_CONCRETE_OPTIMIZER_CPP)
# HPX #####################################################
install-hpx-from-source: $(HPX_LOCAL_DIR)
mkdir -p $(HPX_LOCAL_DIR)/build
cd $(HPX_LOCAL_DIR)/build && cmake \
-DHPX_WITH_FETCH_ASIO=on \
-DHPX_FILESYSTEM_WITH_BOOST_FILESYSTEM_COMPATIBILITY=ON \
-DHPX_WITH_MALLOC=system ..
cd $(HPX_LOCAL_DIR)/build && make -j2
$(HPX_TARBALL):
curl -L $(HPX_URL) -o $(HPX_TARBALL)
$(HPX_LOCAL_DIR): $(HPX_TARBALL)
tar xzvf $(HPX_TARBALL)
$(BUILD_DIR)/configured.stamp:
mkdir -p $(BUILD_DIR)
cmake -B $(BUILD_DIR) -GNinja ../llvm-project/llvm/ \
@@ -68,7 +115,7 @@ $(BUILD_DIR)/configured.stamp:
-DCONCRETELANG_BINDINGS_PYTHON_ENABLED=$(BINDINGS_PYTHON_ENABLED) \
-DCONCRETELANG_DATAFLOW_EXECUTION_ENABLED=$(DATAFLOW_EXECUTION_ENABLED) \
-DCONCRETELANG_TIMING_ENABLED=$(TIMING_ENABLED) \
-DCONCRETE_FFI_RELEASE=${CONCRETE_PROJECT}/target/release \
-DCONCRETE_FFI_RELEASE=$(CONCRETE_CORE_FFI_FOLDER) \
-DHPX_DIR=${HPX_INSTALL_DIR}/lib/cmake/HPX \
-DLLVM_EXTERNAL_PROJECTS=concretelang \
-DLLVM_EXTERNAL_CONCRETELANG_SOURCE_DIR=. \
@@ -76,30 +123,7 @@ $(BUILD_DIR)/configured.stamp:
-DCONCRETE_OPTIMIZER_DIR=${CONCRETE_OPTIMIZER_DIR}
touch $@
build-initialized: concrete-optimizer-lib $(BUILD_DIR)/configured.stamp
LIB_CONCRETE_OPTIMIZER_CPP = $(CONCRETE_OPTIMIZER_DIR)/target/libconcrete_optimizer_cpp.a
# we need CONCRETE_OPTIMIZER_DIR here to ensure it is present before computing CONCRETE_OPTIMIZER_SRC
concrete-optimizer-lib:
make -C $(CONCRETE_OPTIMIZER_DIR)/concrete-optimizer-cpp $(LIB_CONCRETE_OPTIMIZER_CPP)
# HPX
install-hpx-from-source: $(HPX_LOCAL_DIR)
mkdir -p $(HPX_LOCAL_DIR)/build
cd $(HPX_LOCAL_DIR)/build && cmake \
-DHPX_WITH_FETCH_ASIO=on \
-DHPX_FILESYSTEM_WITH_BOOST_FILESYSTEM_COMPATIBILITY=ON \
-DHPX_WITH_MALLOC=system ..
cd $(HPX_LOCAL_DIR)/build && make -j2
$(HPX_TARBALL):
curl -L $(HPX_URL) -o $(HPX_TARBALL)
$(HPX_LOCAL_DIR): $(HPX_TARBALL)
tar xzvf $(HPX_TARBALL)
build-initialized: concrete-optimizer-lib concrete-core-ffi $(BUILD_DIR)/configured.stamp
doc: build-initialized
cmake --build $(BUILD_DIR) --target mlir-doc
@@ -288,6 +312,7 @@ python_lint:
python_format \
check_python_format \
concrete-optimizer-lib \
concrete-core-ffi \
build-tests \
run-tests \
run-check-tests \
@@ -296,4 +321,5 @@ python_lint:
run-python-tests \
build-end-to-end-tests \
build-end-to-end-dataflow-tests \
run-end-to-end-dataflow-tests
run-end-to-end-dataflow-tests \
concrete-core-ffi

View File

@@ -8,19 +8,18 @@
#include <memory>
extern "C" {
#include "concrete-ffi.h"
}
#include "concrete-core-ffi.h"
#include "concretelang/Common/Error.h"
namespace concretelang {
namespace clientlib {
// =============================================
/// Wrapper for `LweKeyswitchKey_u64` so that it cleans up properly.
/// Wrapper for `LweKeyswitchKey64` so that it cleans up properly.
class LweKeyswitchKey {
private:
LweKeyswitchKey_u64 *ksk;
LweKeyswitchKey64 *ksk;
protected:
friend std::ostream &operator<<(std::ostream &ostream,
@@ -29,27 +28,28 @@ protected:
LweKeyswitchKey &wrappedKsk);
public:
LweKeyswitchKey(LweKeyswitchKey_u64 *ksk) : ksk{ksk} {}
LweKeyswitchKey(LweKeyswitchKey64 *ksk) : ksk{ksk} {}
LweKeyswitchKey(LweKeyswitchKey &other) = delete;
LweKeyswitchKey(LweKeyswitchKey &&other) : ksk{other.ksk} {
other.ksk = nullptr;
}
~LweKeyswitchKey() {
if (this->ksk != nullptr) {
free_lwe_keyswitch_key_u64(this->ksk);
CAPI_ASSERT_ERROR(destroy_lwe_keyswitch_key_u64(this->ksk));
this->ksk = nullptr;
}
}
LweKeyswitchKey_u64 *get() { return this->ksk; }
LweKeyswitchKey64 *get() { return this->ksk; }
};
// =============================================
/// Wrapper for `LweBootstrapKey_u64` so that it cleans up properly.
/// Wrapper for `FftwFourierLweBootstrapKey64` so that it cleans up properly.
class LweBootstrapKey {
private:
LweBootstrapKey_u64 *bsk;
FftwFourierLweBootstrapKey64 *bsk;
protected:
friend std::ostream &operator<<(std::ostream &ostream,
@@ -58,19 +58,19 @@ protected:
LweBootstrapKey &wrappedBsk);
public:
LweBootstrapKey(LweBootstrapKey_u64 *bsk) : bsk{bsk} {}
LweBootstrapKey(FftwFourierLweBootstrapKey64 *bsk) : bsk{bsk} {}
LweBootstrapKey(LweBootstrapKey &other) = delete;
LweBootstrapKey(LweBootstrapKey &&other) : bsk{other.bsk} {
other.bsk = nullptr;
}
~LweBootstrapKey() {
if (this->bsk != nullptr) {
free_lwe_bootstrap_key_u64(this->bsk);
CAPI_ASSERT_ERROR(destroy_fftw_fourier_lwe_bootstrap_key_u64(this->bsk));
this->bsk = nullptr;
}
}
LweBootstrapKey_u64 *get() { return this->bsk; }
FftwFourierLweBootstrapKey64 *get() { return this->bsk; }
};
// =============================================
@@ -96,8 +96,8 @@ public:
std::shared_ptr<LweBootstrapKey> sharedBsk)
: sharedKsk{sharedKsk}, sharedBsk{sharedBsk} {}
LweKeyswitchKey_u64 *getKsk() { return this->sharedKsk->get(); }
LweBootstrapKey_u64 *getBsk() { return this->sharedBsk->get(); }
LweKeyswitchKey64 *getKsk() { return this->sharedKsk->get(); }
FftwFourierLweBootstrapKey64 *getBsk() { return this->sharedBsk->get(); }
};
// =============================================

View File

@@ -10,9 +10,7 @@
#include "boost/outcome.h"
extern "C" {
#include "concrete-ffi.h"
}
#include "concrete-core-ffi.h"
#include "concretelang/Runtime/DFRuntime.hpp"
#include "concretelang/Runtime/context.h"
@@ -102,9 +100,8 @@ public:
return EvaluationKeys();
}
const std::map<LweSecretKeyID,
std::pair<LweSecretKeyParam, LweSecretKey_u64 *>> &
getSecretKeys();
const std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey64 *>>
&getSecretKeys();
const std::map<LweSecretKeyID,
std::pair<BootstrapKeyParam, std::shared_ptr<LweBootstrapKey>>>
@@ -135,8 +132,10 @@ protected:
friend class KeySetCache;
private:
Engine *engine;
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey_u64 *>>
DefaultEngine *engine;
DefaultParallelEngine *par_engine;
FftwEngine *fftw_engine;
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey64 *>>
secretKeys;
std::map<LweSecretKeyID,
std::pair<BootstrapKeyParam, std::shared_ptr<LweBootstrapKey>>>
@@ -144,13 +143,13 @@ private:
std::map<LweSecretKeyID,
std::pair<KeyswitchKeyParam, std::shared_ptr<LweKeyswitchKey>>>
keyswitchKeys;
std::vector<std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey_u64 *>>
std::vector<std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey64 *>>
inputs;
std::vector<std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey_u64 *>>
std::vector<std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey64 *>>
outputs;
void setKeys(
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey_u64 *>>
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey64 *>>
secretKeys,
std::map<LweSecretKeyID,
std::pair<BootstrapKeyParam, std::shared_ptr<LweBootstrapKey>>>

View File

@@ -7,12 +7,9 @@
#define CONCRETELANG_CLIENTLIB_TYPES_H_
#include <cstdint>
#include <stddef.h>
#include <vector>
extern "C" {
#include "concrete-ffi.h"
}
namespace concretelang {
namespace clientlib {

View File

@@ -7,6 +7,12 @@
#include <string>
#define CAPI_ASSERT_ERROR(instr) \
{ \
int err = instr; \
assert(err == 0); \
}
namespace concretelang {
namespace error {

View File

@@ -6,35 +6,43 @@
#ifndef CONCRETELANG_RUNTIME_CONTEXT_H
#define CONCRETELANG_RUNTIME_CONTEXT_H
#include <assert.h>
#include <map>
#include <mutex>
#include <pthread.h>
#include "concretelang/ClientLib/EvaluationKeys.h"
#include "concretelang/Runtime/seeder.h"
extern "C" {
#include "concrete-ffi.h"
}
#include "concrete-core-ffi.h"
#include "concretelang/Common/Error.h"
namespace mlir {
namespace concretelang {
typedef struct RuntimeContext {
::concretelang::clientlib::EvaluationKeys evaluationKeys;
std::map<pthread_t, Engine *> engines;
DefaultEngine *default_engine;
std::map<pthread_t, FftwEngine *> fftw_engines;
std::mutex engines_map_guard;
RuntimeContext() {}
RuntimeContext() {
CAPI_ASSERT_ERROR(new_default_engine(best_seeder, &default_engine));
}
/// Ensure that the engines map is not copied
RuntimeContext(const RuntimeContext &ctx)
: evaluationKeys(ctx.evaluationKeys) {}
: evaluationKeys(ctx.evaluationKeys) {
CAPI_ASSERT_ERROR(new_default_engine(best_seeder, &default_engine));
}
RuntimeContext(const RuntimeContext &&other)
: evaluationKeys(other.evaluationKeys) {}
: evaluationKeys(other.evaluationKeys),
default_engine(other.default_engine) {}
~RuntimeContext() {
for (const auto &key : engines) {
free_engine(key.second);
CAPI_ASSERT_ERROR(destroy_default_engine(default_engine));
for (const auto &key : fftw_engines) {
CAPI_ASSERT_ERROR(destroy_fftw_engine(key.second));
}
}
@@ -48,12 +56,14 @@ typedef struct RuntimeContext {
} // namespace mlir
extern "C" {
LweKeyswitchKey_u64 *
LweKeyswitchKey64 *
get_keyswitch_key_u64(mlir::concretelang::RuntimeContext *context);
LweBootstrapKey_u64 *
FftwFourierLweBootstrapKey64 *
get_bootstrap_key_u64(mlir::concretelang::RuntimeContext *context);
Engine *get_engine(mlir::concretelang::RuntimeContext *context);
DefaultEngine *get_engine(mlir::concretelang::RuntimeContext *context);
FftwEngine *get_fftw_engine(mlir::concretelang::RuntimeContext *context);
}
#endif

View File

@@ -17,9 +17,8 @@
#include "concretelang/Runtime/DFRuntime.hpp"
#include "concretelang/Runtime/context.h"
extern "C" {
#include "concrete-ffi.h"
}
#include "concrete-core-ffi.h"
#include "concretelang/Common/Error.h"
namespace mlir {
namespace concretelang {
@@ -54,11 +53,30 @@ template <typename LweKeyType> struct KeyWrapper {
};
template <>
KeyWrapper<LweKeyswitchKey_u64>::KeyWrapper(LweKeyswitchKey_u64 *key)
: key(key), buffer(serialize_lwe_keyswitching_key_u64(key)) {}
KeyWrapper<LweKeyswitchKey64>::KeyWrapper(LweKeyswitchKey64 *key) : key(key) {
DefaultSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(
default_serialization_engine_serialize_lwe_keyswitch_key_u64(engine, key,
&buffer));
}
template <>
KeyWrapper<LweBootstrapKey_u64>::KeyWrapper(LweBootstrapKey_u64 *key)
: key(key), buffer(serialize_lwe_bootstrap_key_u64(key)) {}
KeyWrapper<FftwFourierLweBootstrapKey64>::KeyWrapper(
FftwFourierLweBootstrapKey64 *key)
: key(key) {
FftwSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_fftw_serialization_engine(&engine));
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(
fftw_serialization_engine_serialize_fftw_fourier_lwe_bootstrap_key_u64(
engine, key, &buffer));
}
template <typename LweKeyType>
bool operator==(const KeyWrapper<LweKeyType> &lhs,
@@ -68,36 +86,50 @@ bool operator==(const KeyWrapper<LweKeyType> &lhs,
template <>
template <class Archive>
void KeyWrapper<LweBootstrapKey_u64>::save(Archive &ar,
const unsigned int version) const {
void KeyWrapper<FftwFourierLweBootstrapKey64>::save(
Archive &ar, const unsigned int version) const {
ar << buffer.length;
ar << hpx::serialization::make_array(buffer.pointer, buffer.length);
}
template <>
template <class Archive>
void KeyWrapper<LweBootstrapKey_u64>::load(Archive &ar,
const unsigned int version) {
void KeyWrapper<FftwFourierLweBootstrapKey64>::load(
Archive &ar, const unsigned int version) {
FftwSerializationEngine *engine;
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(new_fftw_serialization_engine(&engine));
ar >> buffer.length;
buffer.pointer = new uint8_t[buffer.length];
ar >> hpx::serialization::make_array(buffer.pointer, buffer.length);
key = deserialize_lwe_bootstrap_key_u64({buffer.pointer, buffer.length});
CAPI_ASSERT_ERROR(
fftw_serialization_engine_deserialize_fftw_fourier_lwe_bootstrap_key_u64(
engine, {buffer.pointer, buffer.length}, &key));
}
template <>
template <class Archive>
void KeyWrapper<LweKeyswitchKey_u64>::save(Archive &ar,
const unsigned int version) const {
void KeyWrapper<LweKeyswitchKey64>::save(Archive &ar,
const unsigned int version) const {
ar << buffer.length;
ar << hpx::serialization::make_array(buffer.pointer, buffer.length);
}
template <>
template <class Archive>
void KeyWrapper<LweKeyswitchKey_u64>::load(Archive &ar,
const unsigned int version) {
void KeyWrapper<LweKeyswitchKey64>::load(Archive &ar,
const unsigned int version) {
DefaultSerializationEngine *engine;
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
ar >> buffer.length;
buffer.pointer = new uint8_t[buffer.length];
ar >> hpx::serialization::make_array(buffer.pointer, buffer.length);
key = deserialize_lwe_keyswitching_key_u64({buffer.pointer, buffer.length});
CAPI_ASSERT_ERROR(
default_serialization_engine_deserialize_lwe_keyswitch_key_u64(
engine, {buffer.pointer, buffer.length}, &key));
}
/************************/
@@ -122,23 +154,22 @@ struct RuntimeContextManager {
// instantiates a local RuntimeContext.
if (_dfr_is_root_node()) {
RuntimeContext *context = (RuntimeContext *)ctx;
LweKeyswitchKey_u64 *ksk = get_keyswitch_key_u64(context);
LweBootstrapKey_u64 *bsk = get_bootstrap_key_u64(context);
LweKeyswitchKey64 *ksk = get_keyswitch_key_u64(context);
FftwFourierLweBootstrapKey64 *bsk = get_bootstrap_key_u64(context);
KeyWrapper<LweKeyswitchKey_u64> kskw(ksk);
KeyWrapper<LweBootstrapKey_u64> bskw(bsk);
KeyWrapper<LweKeyswitchKey64> kskw(ksk);
KeyWrapper<FftwFourierLweBootstrapKey64> bskw(bsk);
hpx::collectives::broadcast_to("ksk_keystore", kskw);
hpx::collectives::broadcast_to("bsk_keystore", bskw);
} else {
auto kskFut =
hpx::collectives::broadcast_from<KeyWrapper<LweKeyswitchKey_u64>>(
hpx::collectives::broadcast_from<KeyWrapper<LweKeyswitchKey64>>(
"ksk_keystore");
auto bskFut =
hpx::collectives::broadcast_from<KeyWrapper<LweBootstrapKey_u64>>(
"bsk_keystore");
auto bskFut = hpx::collectives::broadcast_from<
KeyWrapper<FftwFourierLweBootstrapKey64>>("bsk_keystore");
KeyWrapper<LweKeyswitchKey_u64> kskw = kskFut.get();
KeyWrapper<LweBootstrapKey_u64> bskw = bskFut.get();
KeyWrapper<LweKeyswitchKey64> kskw = kskFut.get();
KeyWrapper<FftwFourierLweBootstrapKey64> bskw = bskFut.get();
context = new mlir::concretelang::RuntimeContext();
context->evaluationKeys = ::concretelang::clientlib::EvaluationKeys(
std::shared_ptr<::concretelang::clientlib::LweKeyswitchKey>(

View File

@@ -0,0 +1,13 @@
// Part of the Concrete Compiler Project, under the BSD3 License with Zama
// Exceptions. See
// https://github.com/zama-ai/concrete-compiler-internal/blob/main/LICENSE.txt
// for license information.
#ifndef CONCRETELANG_RUNTIME_SEEDER_H
#define CONCRETELANG_RUNTIME_SEEDER_H
#include "concrete-core-ffi.h"
extern SeederBuilder *best_seeder;
#endif

View File

@@ -9,7 +9,6 @@
#include "concretelang/Runtime/context.h"
extern "C" {
#include "concrete-ffi.h"
void memref_expand_lut_in_trivial_glwe_ct_u64(
uint64_t *glwe_ct_allocated, uint64_t *glwe_ct_aligned,

View File

@@ -5,6 +5,8 @@
#include "concretelang/ClientLib/KeySet.h"
#include "concretelang/ClientLib/CRT.h"
#include "concretelang/Common/Error.h"
#include "concretelang/Runtime/seeder.h"
#include "concretelang/Support/Error.h"
#define CAPI_ERR_TO_STRINGERROR(instr, msg) \
@@ -16,16 +18,49 @@
} \
}
int clone_transform_lwe_secret_key_to_glwe_secret_key_u64(
DefaultEngine *default_engine, LweSecretKey64 *output_lwe_sk,
size_t poly_size, GlweSecretKey64 **output_glwe_sk) {
LweSecretKey64 *output_lwe_sk_clone = NULL;
int lwe_out_sk_clone_ok =
clone_lwe_secret_key_u64(output_lwe_sk, &output_lwe_sk_clone);
if (lwe_out_sk_clone_ok != 0) {
return 1;
}
int glwe_sk_ok =
default_engine_transform_lwe_secret_key_to_glwe_secret_key_u64(
default_engine, &output_lwe_sk_clone, poly_size, output_glwe_sk);
if (glwe_sk_ok != 0) {
return 1;
}
if (output_lwe_sk_clone != NULL) {
return 1;
}
return 0;
}
namespace concretelang {
namespace clientlib {
KeySet::KeySet() : engine(new_engine()) {}
KeySet::KeySet() {
CAPI_ASSERT_ERROR(new_default_engine(best_seeder, &engine));
CAPI_ASSERT_ERROR(new_default_parallel_engine(best_seeder, &par_engine));
CAPI_ASSERT_ERROR(new_fftw_engine(&fftw_engine));
}
KeySet::~KeySet() {
for (auto it : secretKeys) {
free_lwe_secret_key_u64(it.second.second);
CAPI_ASSERT_ERROR(destroy_lwe_secret_key_u64(it.second.second));
}
free_engine(engine);
CAPI_ASSERT_ERROR(destroy_default_engine(engine));
CAPI_ASSERT_ERROR(destroy_fftw_engine(fftw_engine));
CAPI_ASSERT_ERROR(destroy_default_parallel_engine(par_engine));
}
outcome::checked<std::unique_ptr<KeySet>, StringError>
@@ -46,7 +81,7 @@ KeySet::setupEncryptionMaterial(ClientParameters &params, uint64_t seed_msb,
{
for (auto param : params.inputs) {
LweSecretKeyParam secretKeyParam = {0};
LweSecretKey_u64 *secretKey = nullptr;
LweSecretKey64 *secretKey = nullptr;
if (param.encryption.hasValue()) {
auto inputSk = this->secretKeys.find(param.encryption->secretKeyID);
if (inputSk == this->secretKeys.end()) {
@@ -56,13 +91,13 @@ KeySet::setupEncryptionMaterial(ClientParameters &params, uint64_t seed_msb,
secretKeyParam = inputSk->second.first;
secretKey = inputSk->second.second;
}
std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey_u64 *> input = {
std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey64 *> input = {
param, secretKeyParam, secretKey};
this->inputs.push_back(input);
}
for (auto param : params.outputs) {
LweSecretKeyParam secretKeyParam = {0};
LweSecretKey_u64 *secretKey = nullptr;
LweSecretKey64 *secretKey = nullptr;
if (param.encryption.hasValue()) {
auto outputSk = this->secretKeys.find(param.encryption->secretKeyID);
if (outputSk == this->secretKeys.end()) {
@@ -72,7 +107,7 @@ KeySet::setupEncryptionMaterial(ClientParameters &params, uint64_t seed_msb,
secretKeyParam = outputSk->second.first;
secretKey = outputSk->second.second;
}
std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey_u64 *> output = {
std::tuple<CircuitGate, LweSecretKeyParam, LweSecretKey64 *> output = {
param, secretKeyParam, secretKey};
this->outputs.push_back(output);
}
@@ -107,7 +142,7 @@ KeySet::generateKeysFromParams(ClientParameters &params, uint64_t seed_msb,
}
void KeySet::setKeys(
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey_u64 *>>
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey64 *>>
secretKeys,
std::map<LweSecretKeyID,
std::pair<BootstrapKeyParam, std::shared_ptr<LweBootstrapKey>>>
@@ -122,8 +157,9 @@ void KeySet::setKeys(
outcome::checked<void, StringError>
KeySet::generateSecretKey(LweSecretKeyID id, LweSecretKeyParam param) {
LweSecretKey_u64 *sk;
sk = generate_lwe_secret_key_u64(engine, param.dimension);
LweSecretKey64 *sk;
CAPI_ASSERT_ERROR(default_engine_generate_new_lwe_secret_key_u64(
engine, param.dimension, &sk));
secretKeys[id] = {param, sk};
@@ -142,7 +178,7 @@ KeySet::generateBootstrapKey(BootstrapKeyID id, BootstrapKeyParam param) {
return StringError("cannot find output key to generate bootstrap key");
}
// Allocate the bootstrap key
LweBootstrapKey_u64 *bsk;
LweBootstrapKey64 *bsk;
uint64_t total_dimension = outputSk->second.first.dimension;
@@ -150,12 +186,27 @@ KeySet::generateBootstrapKey(BootstrapKeyID id, BootstrapKeyParam param) {
uint64_t polynomialSize = total_dimension / param.glweDimension;
bsk = generate_lwe_bootstrap_key_u64(
engine, inputSk->second.second, outputSk->second.second, param.baseLog,
param.level, param.variance, param.glweDimension, polynomialSize);
GlweSecretKey64 *output_glwe_sk = nullptr;
// This is not part of the C FFI but rather is a C util exposed for
// convenience in tests.
CAPI_ASSERT_ERROR(clone_transform_lwe_secret_key_to_glwe_secret_key_u64(
engine, outputSk->second.second, polynomialSize, &output_glwe_sk));
CAPI_ASSERT_ERROR(default_parallel_engine_generate_new_lwe_bootstrap_key_u64(
par_engine, inputSk->second.second, output_glwe_sk, param.baseLog,
param.level, param.variance, &bsk));
FftwFourierLweBootstrapKey64 *fbsk;
CAPI_ASSERT_ERROR(
fftw_engine_convert_lwe_bootstrap_key_to_fftw_fourier_lwe_bootstrap_key_u64(
fftw_engine, bsk, &fbsk));
CAPI_ASSERT_ERROR(destroy_lwe_bootstrap_key_u64(bsk));
// Store the bootstrap key
bootstrapKeys[id] = {param, std::make_shared<LweBootstrapKey>(bsk)};
bootstrapKeys[id] = {param, std::make_shared<LweBootstrapKey>(fbsk)};
return outcome::success();
}
@@ -172,11 +223,11 @@ KeySet::generateKeyswitchKey(KeyswitchKeyID id, KeyswitchKeyParam param) {
return StringError("cannot find output key to generate keyswitch key");
}
// Allocate the keyswitch key
LweKeyswitchKey_u64 *ksk;
LweKeyswitchKey64 *ksk;
ksk = generate_lwe_keyswitch_key_u64(engine, inputSk->second.second,
outputSk->second.second, param.level,
param.baseLog, param.variance);
CAPI_ASSERT_ERROR(default_engine_generate_new_lwe_keyswitch_key_u64(
engine, inputSk->second.second, outputSk->second.second, param.level,
param.baseLog, param.variance, &ksk));
// Store the keyswitch key
keyswitchKeys[id] = {param, std::make_shared<LweKeyswitchKey>(ksk)};
@@ -236,8 +287,11 @@ KeySet::encrypt_lwe(size_t argPos, uint64_t *ciphertext, uint64_t input) {
auto product = crt::productOfModuli(crt);
for (auto modulus : crt) {
auto plaintext = crt::encode(input, modulus, product);
::encrypt_lwe_u64(engine, lweSecretKey, ciphertext, plaintext,
encryption->variance);
CAPI_ASSERT_ERROR(
default_engine_discard_encrypt_lwe_ciphertext_u64_raw_ptr_buffers(
engine, lweSecretKey, ciphertext, plaintext,
encryption->variance));
ciphertext = ciphertext + lweSecretKeyParam.lweSize();
}
return outcome::success();
@@ -245,8 +299,10 @@ KeySet::encrypt_lwe(size_t argPos, uint64_t *ciphertext, uint64_t input) {
// Simple TFHE integers - 1 blocks with one padding bits
// TODO we could check if the input value is in the right range
uint64_t plaintext = input << (64 - (encryption->encoding.precision + 1));
::encrypt_lwe_u64(engine, lweSecretKey, ciphertext, plaintext,
encryption->variance);
CAPI_ASSERT_ERROR(
default_engine_discard_encrypt_lwe_ciphertext_u64_raw_ptr_buffers(
engine, lweSecretKey, ciphertext, plaintext, encryption->variance));
return outcome::success();
}
@@ -268,7 +324,11 @@ KeySet::decrypt_lwe(size_t argPos, uint64_t *ciphertext, uint64_t &output) {
std::vector<int64_t> remainders;
// decrypt and decode remainders
for (auto modulus : crt) {
auto decrypted = ::decrypt_lwe_u64(engine, lweSecretKey, ciphertext);
uint64_t decrypted;
CAPI_ASSERT_ERROR(
default_engine_decrypt_lwe_ciphertext_u64_raw_ptr_buffers(
engine, lweSecretKey, ciphertext, &decrypted));
auto plaintext = crt::decode(decrypted, modulus);
remainders.push_back(plaintext);
ciphertext = ciphertext + lweSecretKeyParam.lweSize();
@@ -278,7 +338,11 @@ KeySet::decrypt_lwe(size_t argPos, uint64_t *ciphertext, uint64_t &output) {
return outcome::success();
}
// Simple TFHE integers - 1 blocks with one padding bits
uint64_t plaintext = ::decrypt_lwe_u64(engine, lweSecretKey, ciphertext);
uint64_t plaintext;
CAPI_ASSERT_ERROR(default_engine_decrypt_lwe_ciphertext_u64_raw_ptr_buffers(
engine, lweSecretKey, ciphertext, &plaintext));
// Decode
uint64_t precision = encryption->encoding.precision;
output = plaintext >> (64 - precision - 2);
@@ -289,8 +353,8 @@ KeySet::decrypt_lwe(size_t argPos, uint64_t *ciphertext, uint64_t &output) {
return outcome::success();
}
const std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey_u64 *>>
&KeySet::getSecretKeys() {
const std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey64 *>> &
KeySet::getSecretKeys() {
return secretKeys;
}

View File

@@ -16,18 +16,17 @@
#include <string>
#include <utime.h>
extern "C" {
#include "concrete-ffi.h"
}
#include "concrete-core-ffi.h"
namespace concretelang {
namespace clientlib {
using StringError = concretelang::error::StringError;
template <class Key>
outcome::checked<Key *, StringError> load(llvm::SmallString<0> &path,
Key *(*deser)(BufferView buffer)) {
template <class Engine, class Key>
outcome::checked<Key *, StringError>
load(llvm::SmallString<0> &path,
int (*deser)(Engine *, BufferView buffer, Key **), Engine *engine) {
std::ifstream in((std::string)path, std::ofstream::binary);
if (in.fail()) {
return StringError("Cannot access " + (std::string)path);
@@ -39,8 +38,11 @@ outcome::checked<Key *, StringError> load(llvm::SmallString<0> &path,
}
auto content = sbuffer.str();
BufferView buffer = {(const uint8_t *)content.c_str(), content.length()};
auto result = deser(buffer);
if (result == nullptr) {
Key *result = nullptr;
int error_code = deser(engine, buffer, &result);
if (result == nullptr || error_code != 0) {
return StringError("Cannot deserialize " + (std::string)path);
}
return result;
@@ -52,35 +54,81 @@ static void writeFile(llvm::SmallString<0> &path, Buffer content) {
out.close();
}
outcome::checked<LweSecretKey_u64 *, StringError>
outcome::checked<LweSecretKey64 *, StringError>
loadSecretKey(llvm::SmallString<0> &path) {
return load(path, deserialize_lwe_secret_key_u64);
DefaultSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
return load(path, default_serialization_engine_deserialize_lwe_secret_key_u64,
engine);
}
outcome::checked<LweKeyswitchKey_u64 *, StringError>
outcome::checked<LweKeyswitchKey64 *, StringError>
loadKeyswitchKey(llvm::SmallString<0> &path) {
return load(path, deserialize_lwe_keyswitching_key_u64);
DefaultSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
return load(path,
default_serialization_engine_deserialize_lwe_keyswitch_key_u64,
engine);
}
outcome::checked<LweBootstrapKey_u64 *, StringError>
outcome::checked<FftwFourierLweBootstrapKey64 *, StringError>
loadBootstrapKey(llvm::SmallString<0> &path) {
return load(path, deserialize_lwe_bootstrap_key_u64);
FftwSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_fftw_serialization_engine(&engine));
return load(
path,
fftw_serialization_engine_deserialize_fftw_fourier_lwe_bootstrap_key_u64,
engine);
}
void saveSecretKey(llvm::SmallString<0> &path, LweSecretKey_u64 *key) {
Buffer buffer = serialize_lwe_secret_key_u64(key);
void saveSecretKey(llvm::SmallString<0> &path, LweSecretKey64 *key) {
DefaultSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
Buffer buffer;
CAPI_ASSERT_ERROR(default_serialization_engine_serialize_lwe_secret_key_u64(
engine, key, &buffer));
writeFile(path, buffer);
free(buffer.pointer);
}
void saveBootstrapKey(llvm::SmallString<0> &path, LweBootstrapKey_u64 *key) {
Buffer buffer = serialize_lwe_bootstrap_key_u64(key);
void saveBootstrapKey(llvm::SmallString<0> &path,
FftwFourierLweBootstrapKey64 *key) {
FftwSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_fftw_serialization_engine(&engine));
Buffer buffer;
CAPI_ASSERT_ERROR(
fftw_serialization_engine_serialize_fftw_fourier_lwe_bootstrap_key_u64(
engine, key, &buffer));
writeFile(path, buffer);
free(buffer.pointer);
}
void saveKeyswitchKey(llvm::SmallString<0> &path, LweKeyswitchKey_u64 *key) {
Buffer buffer = serialize_lwe_keyswitching_key_u64(key);
void saveKeyswitchKey(llvm::SmallString<0> &path, LweKeyswitchKey64 *key) {
DefaultSerializationEngine *engine;
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
Buffer buffer;
CAPI_ASSERT_ERROR(
default_serialization_engine_serialize_lwe_keyswitch_key_u64(engine, key,
&buffer));
writeFile(path, buffer);
free(buffer.pointer);
}
@@ -94,7 +142,7 @@ KeySetCache::loadKeys(ClientParameters &params, uint64_t seed_msb,
// e.g. so the CI can do some cleanup of unused keys.
utime(folderPath.c_str(), nullptr);
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey_u64 *>>
std::map<LweSecretKeyID, std::pair<LweSecretKeyParam, LweSecretKey64 *>>
secretKeys;
std::map<LweSecretKeyID,
std::pair<BootstrapKeyParam, std::shared_ptr<LweBootstrapKey>>>
@@ -109,7 +157,7 @@ KeySetCache::loadKeys(ClientParameters &params, uint64_t seed_msb,
auto param = secretKeyParam.second;
llvm::SmallString<0> path(folderPath);
llvm::sys::path::append(path, "secretKey_" + id);
OUTCOME_TRY(LweSecretKey_u64 * sk, loadSecretKey(path));
OUTCOME_TRY(LweSecretKey64 * sk, loadSecretKey(path));
secretKeys[id] = {param, sk};
}
// Load bootstrap keys
@@ -118,7 +166,7 @@ KeySetCache::loadKeys(ClientParameters &params, uint64_t seed_msb,
auto param = bootstrapKeyParam.second;
llvm::SmallString<0> path(folderPath);
llvm::sys::path::append(path, "pbsKey_" + id);
OUTCOME_TRY(LweBootstrapKey_u64 * bsk, loadBootstrapKey(path));
OUTCOME_TRY(FftwFourierLweBootstrapKey64 * bsk, loadBootstrapKey(path));
bootstrapKeys[id] = {param, std::make_shared<LweBootstrapKey>(bsk)};
}
// Load keyswitch keys
@@ -127,7 +175,7 @@ KeySetCache::loadKeys(ClientParameters &params, uint64_t seed_msb,
auto param = keyswitchParam.second;
llvm::SmallString<0> path(folderPath);
llvm::sys::path::append(path, "ksKey_" + id);
OUTCOME_TRY(LweKeyswitchKey_u64 * ksk, loadKeyswitchKey(path));
OUTCOME_TRY(LweKeyswitchKey64 * ksk, loadKeyswitchKey(path));
keyswitchKeys[id] = {param, std::make_shared<LweKeyswitchKey>(ksk)};
}

View File

@@ -6,10 +6,6 @@
#include <iostream>
#include <stdlib.h>
extern "C" {
#include "concrete-ffi.h"
}
#include "concretelang/ClientLib/PublicArguments.h"
#include "concretelang/ClientLib/Serializers.h"

View File

@@ -7,18 +7,19 @@
#include <iostream>
#include <stdlib.h>
extern "C" {
#include "concrete-ffi.h"
}
#include "concrete-core-ffi.h"
#include "concretelang/ClientLib/PublicArguments.h"
#include "concretelang/ClientLib/Serializers.h"
#include "concretelang/Common/Error.h"
namespace concretelang {
namespace clientlib {
template <typename Result>
Result read_deser(std::istream &istream, Result (*deser)(BufferView)) {
template <typename Engine, typename Result>
Result read_deser(std::istream &istream,
int (*deser)(Engine *, BufferView, Result *),
Engine *engine) {
size_t length;
readSize(istream, length);
// buffer is too big to be allocated on stack
@@ -26,7 +27,11 @@ Result read_deser(std::istream &istream, Result (*deser)(BufferView)) {
std::vector<uint8_t> buffer(length);
istream.read((char *)buffer.data(), length);
assert(istream.good());
return deser({buffer.data(), length});
Result result;
CAPI_ASSERT_ERROR(deser(engine, {buffer.data(), length}, &result));
return result;
}
template <typename BufferLike>
@@ -37,9 +42,18 @@ std::ostream &writeBufferLike(std::ostream &ostream, BufferLike &buffer) {
return ostream;
}
std::ostream &operator<<(std::ostream &ostream,
const LweKeyswitchKey_u64 *key) {
Buffer b = serialize_lwe_keyswitching_key_u64(key);
std::ostream &operator<<(std::ostream &ostream, const LweKeyswitchKey64 *key) {
DefaultSerializationEngine *engine;
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
Buffer b;
CAPI_ASSERT_ERROR(
default_serialization_engine_serialize_lwe_keyswitch_key_u64(engine, key,
&b));
writeBufferLike(ostream, b);
free((void *)b.pointer);
b.pointer = nullptr;
@@ -47,21 +61,47 @@ std::ostream &operator<<(std::ostream &ostream,
}
std::ostream &operator<<(std::ostream &ostream,
const LweBootstrapKey_u64 *key) {
Buffer b = serialize_lwe_bootstrap_key_u64(key);
const FftwFourierLweBootstrapKey64 *key) {
FftwSerializationEngine *engine;
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(new_fftw_serialization_engine(&engine));
Buffer b;
CAPI_ASSERT_ERROR(
fftw_serialization_engine_serialize_fftw_fourier_lwe_bootstrap_key_u64(
engine, key, &b))
writeBufferLike(ostream, b);
free((void *)b.pointer);
b.pointer = nullptr;
return ostream;
}
std::istream &operator>>(std::istream &istream, LweKeyswitchKey_u64 *&key) {
key = read_deser(istream, deserialize_lwe_keyswitching_key_u64);
std::istream &operator>>(std::istream &istream, LweKeyswitchKey64 *&key) {
DefaultSerializationEngine *engine;
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(new_default_serialization_engine(&engine));
key = read_deser(
istream, default_serialization_engine_deserialize_lwe_keyswitch_key_u64,
engine);
return istream;
}
std::istream &operator>>(std::istream &istream, LweBootstrapKey_u64 *&key) {
key = read_deser(istream, deserialize_lwe_bootstrap_key_u64);
std::istream &operator>>(std::istream &istream,
FftwFourierLweBootstrapKey64 *&key) {
FftwSerializationEngine *engine;
// No Freeing as it doesn't allocate anything.
CAPI_ASSERT_ERROR(new_fftw_serialization_engine(&engine));
key = read_deser(
istream,
fftw_serialization_engine_deserialize_fftw_fourier_lwe_bootstrap_key_u64,
engine);
return istream;
}

View File

@@ -2,6 +2,7 @@ add_library(ConcretelangRuntime SHARED
context.cpp
wrappers.cpp
DFRuntime.cpp
seeder.cpp
)
if(CONCRETELANG_DATAFLOW_EXECUTION_ENABLED)

View File

@@ -3,29 +3,38 @@
// https://github.com/zama-ai/concrete-compiler-internal/blob/main/LICENSE.txt
// for license information.
#include "concretelang/Runtime/context.h"
#include "concretelang/Common/Error.h"
#include "concretelang/Runtime/seeder.h"
#include <assert.h>
#include <concretelang/Runtime/context.h>
#include <stdio.h>
LweKeyswitchKey_u64 *
LweKeyswitchKey64 *
get_keyswitch_key_u64(mlir::concretelang::RuntimeContext *context) {
return context->evaluationKeys.getKsk();
}
LweBootstrapKey_u64 *
FftwFourierLweBootstrapKey64 *
get_bootstrap_key_u64(mlir::concretelang::RuntimeContext *context) {
return context->evaluationKeys.getBsk();
}
/// Instantiate one engine per thread on demand
Engine *get_engine(mlir::concretelang::RuntimeContext *context) {
DefaultEngine *get_engine(mlir::concretelang::RuntimeContext *context) {
return context->default_engine;
}
FftwEngine *get_fftw_engine(mlir::concretelang::RuntimeContext *context) {
pthread_t threadId = pthread_self();
std::lock_guard<std::mutex> guard(context->engines_map_guard);
auto engineIt = context->engines.find(threadId);
if (engineIt == context->engines.end()) {
auto engineIt = context->fftw_engines.find(threadId);
if (engineIt == context->fftw_engines.end()) {
FftwEngine *fftw_engine = nullptr;
CAPI_ASSERT_ERROR(new_fftw_engine(&fftw_engine));
engineIt =
context->engines
.insert(std::pair<pthread_t, Engine *>(threadId, new_engine()))
context->fftw_engines
.insert(std::pair<pthread_t, FftwEngine *>(threadId, fftw_engine))
.first;
}
assert(engineIt->second && "No engine available in context");

View File

@@ -0,0 +1,43 @@
// Part of the Concrete Compiler Project, under the BSD3 License with Zama
// Exceptions. See
// https://github.com/zama-ai/concrete-compiler-internal/blob/main/LICENSE.txt
// for license information.
#include "concretelang/Runtime/seeder.h"
#include <cassert>
#include <iostream>
#include "concrete-core-ffi.h"
#include "concretelang/Common/Error.h"
SeederBuilder *get_best_seeder() {
SeederBuilder *builder = NULL;
bool rdseed_seeder_available = false;
CAPI_ASSERT_ERROR(rdseed_seeder_is_available(&rdseed_seeder_available));
if (rdseed_seeder_available) {
CAPI_ASSERT_ERROR(get_rdseed_seeder_builder(&builder));
std::cout << "Using rdseed seeder." << std::endl;
return builder;
}
bool unix_seeder_available = false;
CAPI_ASSERT_ERROR(unix_seeder_is_available(&unix_seeder_available));
if (unix_seeder_available) {
// Security depends on /dev/random security
uint64_t secret_high_64 = 0;
uint64_t secret_low_64 = 0;
CAPI_ASSERT_ERROR(
get_unix_seeder_builder(secret_high_64, secret_low_64, &builder));
std::cout << "Using Unix /dev/random seeder without an additionnal secret."
<< std::endl;
return builder;
}
std::cout << "No available seeder." << std::endl;
return builder;
}
SeederBuilder *best_seeder = get_best_seeder();

View File

@@ -3,9 +3,54 @@
// https://github.com/zama-ai/concrete-compiler-internal/blob/main/LICENSE.txt
// for license information.
#include "concretelang/Runtime/wrappers.h"
#include "concretelang/Common/Error.h"
#include "concretelang/Runtime/seeder.h"
#include <assert.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
static DefaultEngine *levelled_engine = nullptr;
DefaultEngine *get_levelled_engine() {
if (levelled_engine == nullptr) {
CAPI_ASSERT_ERROR(new_default_engine(best_seeder, &levelled_engine));
}
return levelled_engine;
}
// This helper function expands the input LUT into output, duplicating values as
// needed to fill mega cases, taking care of the encoding and the half mega case
// shift in the process as well. All sizes should be powers of 2.
void encode_and_expand_lut(uint64_t *output, size_t output_size,
size_t out_MESSAGE_BITS, const uint64_t *lut,
size_t lut_size) {
assert((output_size % lut_size) == 0);
size_t mega_case_size = output_size / lut_size;
assert((mega_case_size % 2) == 0);
for (size_t idx = 0; idx < mega_case_size / 2; ++idx) {
output[idx] = lut[0] << (64 - out_MESSAGE_BITS - 1);
}
for (size_t idx = (lut_size - 1) * mega_case_size + mega_case_size / 2;
idx < output_size; ++idx) {
output[idx] = -(lut[0] << (64 - out_MESSAGE_BITS - 1));
}
for (size_t lut_idx = 1; lut_idx < lut_size; ++lut_idx) {
uint64_t lut_value = lut[lut_idx] << (64 - out_MESSAGE_BITS - 1);
size_t start = mega_case_size * (lut_idx - 1) + mega_case_size / 2;
for (size_t output_idx = start; output_idx < start + mega_case_size;
++output_idx) {
output[output_idx] = lut_value;
}
}
}
#include "concretelang/ClientLib/CRT.h"
#include "concretelang/Runtime/wrappers.h"
@@ -23,8 +68,17 @@ void memref_expand_lut_in_trivial_glwe_ct_u64(
assert(glwe_ct_stride == 1 && "Runtime: stride not equal to 1, check "
"memref_expand_lut_in_trivial_glwe_ct_u64");
expand_lut_in_trivial_glwe_ct_u64(glwe_ct_aligned, poly_size, glwe_dimension,
out_precision, lut_aligned, lut_size);
assert(glwe_ct_size == poly_size * (glwe_dimension + 1));
std::vector<uint64_t> expanded_tabulated_function_array(poly_size);
encode_and_expand_lut(expanded_tabulated_function_array.data(), poly_size,
out_precision, lut_aligned + lut_offset, lut_size);
CAPI_ASSERT_ERROR(
default_engine_discard_trivially_encrypt_glwe_ciphertext_u64_raw_ptr_buffers(
get_levelled_engine(), glwe_ct_aligned + glwe_ct_offset, glwe_ct_size,
expanded_tabulated_function_array.data(), poly_size));
return;
}
@@ -38,9 +92,10 @@ void memref_add_lwe_ciphertexts_u64(
assert(out_size == ct0_size && out_size == ct1_size &&
"size of lwe buffer are incompatible");
size_t lwe_dimension = {out_size - 1};
add_two_lwe_ciphertexts_u64(out_aligned + out_offset,
ct0_aligned + ct0_offset,
ct1_aligned + ct1_offset, lwe_dimension);
CAPI_ASSERT_ERROR(
default_engine_discard_add_lwe_ciphertext_u64_raw_ptr_buffers(
get_levelled_engine(), out_aligned + out_offset,
ct0_aligned + ct0_offset, ct1_aligned + ct1_offset, lwe_dimension));
}
void memref_add_plaintext_lwe_ciphertext_u64(
@@ -50,9 +105,10 @@ void memref_add_plaintext_lwe_ciphertext_u64(
uint64_t ct0_stride, uint64_t plaintext) {
assert(out_size == ct0_size && "size of lwe buffer are incompatible");
size_t lwe_dimension = {out_size - 1};
add_plaintext_to_lwe_ciphertext_u64(out_aligned + out_offset,
ct0_aligned + ct0_offset, plaintext,
lwe_dimension);
CAPI_ASSERT_ERROR(
default_engine_discard_add_lwe_ciphertext_plaintext_u64_raw_ptr_buffers(
get_levelled_engine(), out_aligned + out_offset,
ct0_aligned + ct0_offset, lwe_dimension, plaintext));
}
void memref_mul_cleartext_lwe_ciphertext_u64(
@@ -62,9 +118,10 @@ void memref_mul_cleartext_lwe_ciphertext_u64(
uint64_t ct0_stride, uint64_t cleartext) {
assert(out_size == ct0_size && "size of lwe buffer are incompatible");
size_t lwe_dimension = {out_size - 1};
mul_cleartext_lwe_ciphertext_u64(out_aligned + out_offset,
ct0_aligned + ct0_offset, cleartext,
lwe_dimension);
CAPI_ASSERT_ERROR(
default_engine_discard_mul_lwe_ciphertext_cleartext_u64_raw_ptr_buffers(
get_levelled_engine(), out_aligned + out_offset,
ct0_aligned + ct0_offset, lwe_dimension, cleartext));
}
void memref_negate_lwe_ciphertext_u64(
@@ -74,8 +131,10 @@ void memref_negate_lwe_ciphertext_u64(
uint64_t ct0_stride) {
assert(out_size == ct0_size && "size of lwe buffer are incompatible");
size_t lwe_dimension = {out_size - 1};
neg_lwe_ciphertext_u64(out_aligned + out_offset, ct0_aligned + ct0_offset,
lwe_dimension);
CAPI_ASSERT_ERROR(
default_engine_discard_opp_lwe_ciphertext_u64_raw_ptr_buffers(
get_levelled_engine(), out_aligned + out_offset,
ct0_aligned + ct0_offset, lwe_dimension));
}
void memref_keyswitch_lwe_u64(uint64_t *out_allocated, uint64_t *out_aligned,
@@ -84,8 +143,10 @@ void memref_keyswitch_lwe_u64(uint64_t *out_allocated, uint64_t *out_aligned,
uint64_t *ct0_aligned, uint64_t ct0_offset,
uint64_t ct0_size, uint64_t ct0_stride,
mlir::concretelang::RuntimeContext *context) {
keyswitch_lwe_u64(get_engine(context), get_keyswitch_key_u64(context),
out_aligned + out_offset, ct0_aligned + ct0_offset);
CAPI_ASSERT_ERROR(
default_engine_discard_keyswitch_lwe_ciphertext_u64_raw_ptr_buffers(
get_engine(context), get_keyswitch_key_u64(context),
out_aligned + out_offset, ct0_aligned + ct0_offset));
}
void memref_bootstrap_lwe_u64(
@@ -95,9 +156,11 @@ void memref_bootstrap_lwe_u64(
uint64_t ct0_stride, uint64_t *glwe_ct_allocated, uint64_t *glwe_ct_aligned,
uint64_t glwe_ct_offset, uint64_t glwe_ct_size, uint64_t glwe_ct_stride,
mlir::concretelang::RuntimeContext *context) {
bootstrap_lwe_u64(get_engine(context), get_bootstrap_key_u64(context),
out_aligned + out_offset, ct0_aligned + ct0_offset,
glwe_ct_aligned + glwe_ct_offset);
CAPI_ASSERT_ERROR(
fftw_engine_lwe_ciphertext_discarding_bootstrap_u64_raw_ptr_buffers(
get_fftw_engine(context), get_engine(context),
get_bootstrap_key_u64(context), out_aligned + out_offset,
ct0_aligned + ct0_offset, glwe_ct_aligned + glwe_ct_offset));
}
uint64_t encode_crt(int64_t plaintext, uint64_t modulus, uint64_t product) {