From 5ad59651bc2574be19a15b36862e512346509fcb Mon Sep 17 00:00:00 2001 From: York Jasper Niebuhr Date: Fri, 21 Nov 2025 19:15:14 +0100 Subject: [PATCH] BFV context API --- include/bfv.hpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/include/bfv.hpp b/include/bfv.hpp index 10488b8..d0e9961 100644 --- a/include/bfv.hpp +++ b/include/bfv.hpp @@ -1,15 +1,84 @@ #pragma once +#include +#include +#include +#include namespace homcert::bfv { +constexpr std::size_t VECSIZE = 8192; +constexpr std::size_t PLAINMOD = 16760833; // 8192*2*1023+1 and prime + +template +struct smallest_uint; + +template +struct smallest_uint> { + using type = std::uint8_t; +}; + +template +struct smallest_uint> { + using type = std::uint16_t; +}; + +template +struct smallest_uint> { + using type = std::uint32_t; +}; + +template +struct smallest_uint> { + using type = std::uint64_t; +}; + +struct plaintext { + using coefficient = typename smallest_uint::type; + + std::array coefficients; + + // Arithmetic... +}; + +using ciphertext = int; + +// Inheriting from context class allows pluggability of implementations (e.g. SEAL vs. GPU) + +class context { +public: + context(const context& other) = delete; + context(context&& other) noexcept; + context& operator=(const context& other) = delete; + context& operator=(context&& other) noexcept; + + context(); + virtual ~context(); + + virtual bool allocate(ciphertext& ct) = 0; + virtual bool free(ciphertext ct) = 0; + virtual bool serialize(ciphertext ct, void* buf, std::size_t& n) = 0; + virtual bool deserialize(ciphertext ct, const void* buf, std::size_t n) = 0; + virtual bool encrypt(const plaintext& pt, ciphertext ct) = 0; + virtual bool decrypt(ciphertext ct, plaintext& pt) = 0; + virtual bool add_cipher_plain(ciphertext a, const plaintext& b, ciphertext res) = 0; + virtual bool add_cipher_cipher(ciphertext a, ciphertext b, ciphertext res) = 0; + virtual bool sub_cipher_plain(ciphertext a, const plaintext& b, ciphertext res) = 0; + virtual bool sub_cipher_cipher(ciphertext a, ciphertext b, ciphertext res) = 0; + virtual bool mul_cipher_plain(ciphertext a, const plaintext& b, ciphertext res) = 0; + virtual bool mul_cipher_cipher(ciphertext a, ciphertext b, ciphertext res) = 0; + virtual bool rot_cipher_rows(ciphertext ct, int r, ciphertext res) = 0; + virtual bool swap_cipher_rows(ciphertext ct, ciphertext res) = 0; + virtual bool noise_budget(ciphertext ct, std::size_t& budget) = 0; +}; + /* -TODO -Device handles pluggability of implementations (e.g. SEAL vs. GPU) -Operations are queued on device so the device can parallelize ops +NOTE -> Implementations may defer operations or not wait for them to finish +For example, GPU implementations may dispatch multiplications when they arive +Additionally, a graph of running operations is maintained to handle data dependencies +Only when data is required to actually be present (e.g. decrypt), does the implementation wait */ /* -No device class at all, just the context class which is handed to system as shared_ptr activate_context(std::shared_ptr ctx) -> thread local pointer is set Raw ciphertext and plaintext classes always have the full 8192 coefficients (defined in context as static constexpr) bfv::vector<...> @@ -32,6 +101,7 @@ Programs are defined TWICE -> local stuff is executed -> remote stuff is hosted (e.g. bootstrapping server) -> defined once from each side (differ e.g. in the plaintext inputs etc.) + -> program base class may be used to handle context setting */ }