mirror of
https://github.com/zama-ai/concrete.git
synced 2026-02-08 19:44:57 -05:00
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:
2
compiler/.gitignore
vendored
2
compiler/.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
.dependencies/
|
||||
build/
|
||||
*.mlir.script
|
||||
*.lit_test_times.txt
|
||||
concrete-core-ffi*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(); }
|
||||
};
|
||||
|
||||
// =============================================
|
||||
|
||||
@@ -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>>>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#define CAPI_ASSERT_ERROR(instr) \
|
||||
{ \
|
||||
int err = instr; \
|
||||
assert(err == 0); \
|
||||
}
|
||||
|
||||
namespace concretelang {
|
||||
namespace error {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>(
|
||||
|
||||
13
compiler/include/concretelang/Runtime/seeder.h
Normal file
13
compiler/include/concretelang/Runtime/seeder.h
Normal 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
|
||||
@@ -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,
|
||||
|
||||
@@ -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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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)};
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ add_library(ConcretelangRuntime SHARED
|
||||
context.cpp
|
||||
wrappers.cpp
|
||||
DFRuntime.cpp
|
||||
seeder.cpp
|
||||
)
|
||||
|
||||
if(CONCRETELANG_DATAFLOW_EXECUTION_ENABLED)
|
||||
|
||||
@@ -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");
|
||||
|
||||
43
compiler/lib/Runtime/seeder.cpp
Normal file
43
compiler/lib/Runtime/seeder.cpp
Normal 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();
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user