// Part of the Concrete Compiler Project, under the BSD3 License with Zama // Exceptions. See // https://github.com/zama-ai/concrete-compiler-internal/blob/master/LICENSE.txt // for license information. #ifndef CONCRETELANG_CLIENTLIB_ENCRYPTED_ARGS_H #define CONCRETELANG_CLIENTLIB_ENCRYPTED_ARGS_H #include #include "boost/outcome.h" #include "../Common/Error.h" #include "concretelang/ClientLib/ClientParameters.h" #include "concretelang/ClientLib/KeySet.h" #include "concretelang/ClientLib/Types.h" #include "concretelang/Common/BitsSize.h" namespace concretelang { namespace clientlib { using concretelang::error::StringError; class PublicArguments; class EncryptedArguments { /// Temporary object used to hold and encrypt parameters before calling a /// ClientLambda. Use preferably TypeClientLambda and serializeCall(Args...). /// Otherwise convert it to a PublicArguments and use /// serializeCall(PublicArguments, KeySet). public: EncryptedArguments() : currentPos(0) {} /// Encrypts args thanks the given KeySet and pack the encrypted arguments to /// an EncryptedArguments template static outcome::checked, StringError> create(std::shared_ptr keySet, Args... args) { auto arguments = std::make_unique(); OUTCOME_TRYV(arguments->pushArgs(keySet, args...)); return arguments; } /// Export encrypted arguments as public arguments, reset the encrypted /// arguments, i.e. move all buffers to the PublicArguments and reset the /// positional counter. outcome::checked, StringError> exportPublicArguments(ClientParameters clientParameters, RuntimeContext runtimeContext); public: /// Add a uint8_t scalar argument. outcome::checked pushArg(uint8_t arg, std::shared_ptr keySet); // Add a uint64_t scalar argument. outcome::checked pushArg(uint64_t arg, std::shared_ptr keySet); /// Add a vector-tensor argument. outcome::checked pushArg(std::vector arg, std::shared_ptr keySet); /// Add a 1D tensor argument. template outcome::checked pushArg(std::array arg, std::shared_ptr keySet) { return pushArg(8, (void *)arg.data(), {size}, keySet); } /// Add a 2D tensor argument. template outcome::checked pushArg(std::array, size0> arg, std::shared_ptr keySet) { return pushArg(8, (void *)arg.data(), {size0, size1}, keySet); } /// Add a 3D tensor argument. template outcome::checked pushArg(std::array, size1>, size0> arg, std::shared_ptr keySet) { return pushArg(8, (void *)arg.data(), {size0, size1, size2}, keySet); } // Generalize by computing shape by template recursion // Set a argument at the given pos as a 1D tensor of T. template outcome::checked pushArg(T *data, size_t dim1, std::shared_ptr keySet) { return pushArg(data, llvm::ArrayRef(&dim1, 1), keySet); } // Set a argument at the given pos as a tensor of T. template outcome::checked pushArg(T *data, llvm::ArrayRef shape, std::shared_ptr keySet) { return pushArg(8 * sizeof(T), static_cast(data), shape, keySet); } outcome::checked pushArg(size_t width, void *data, llvm::ArrayRef shape, std::shared_ptr keySet); /// Push a variadic list of arguments. template outcome::checked pushArgs(std::shared_ptr keySet, Arg0 arg0, OtherArgs... others) { OUTCOME_TRYV(pushArg(arg0, keySet)); return pushArgs(keySet, others...); } // Terminal case of pushArgs outcome::checked pushArgs(std::shared_ptr keySet) { return checkAllArgs(keySet); } private: outcome::checked checkPushTooManyArgs(std::shared_ptr keySet); outcome::checked checkAllArgs(std::shared_ptr keySet); private: // Position of the next pushed argument size_t currentPos; std::vector preparedArgs; // Store buffers of ciphertexts std::vector ciphertextBuffers; }; } // namespace clientlib } // namespace concretelang #endif