Kaynağa Gözat

Merge pull request #110 from openfheorg/dev

Updates main to v0.8.5
yspolyakov 9 ay önce
ebeveyn
işleme
43a8440651
10 değiştirilmiş dosya ile 261 ekleme ve 5 silme
  1. 7 1
      .gitignore
  2. 1 1
      CMakeLists.txt
  3. 7 2
      README.md
  4. 51 0
      build_package.sh
  5. 54 0
      docker/Dockerfile
  6. 52 0
      docker/README.md
  7. 1 0
      docs/requirements.txt
  8. 1 0
      openfhe/__init__.py
  9. 78 0
      setup.py
  10. 9 1
      src/lib/pke/serialization.cpp

+ 7 - 1
.gitignore

@@ -10,4 +10,10 @@ build/
 *.pyc
 .settings/
 docs/
-demoData/
+demoData/
+dist/
+openfhe/openfhe.so
+openfhe/*.pyi
+openfhe.egg-info/
+stubs/
+.venv/

+ 1 - 1
CMakeLists.txt

@@ -4,7 +4,7 @@ project (OpenFHE-Python)
 
 set(OPENFHE_PYTHON_VERSION_MAJOR 0)
 set(OPENFHE_PYTHON_VERSION_MINOR 8)
-set(OPENFHE_PYTHON_VERSION_PATCH 4)
+set(OPENFHE_PYTHON_VERSION_PATCH 5)
 set(OPENFHE_PYTHON_VERSION ${OPENFHE_PYTHON_VERSION_MAJOR}.${OPENFHE_PYTHON_VERSION_MINOR}.${OPENFHE_PYTHON_VERSION_PATCH})
 
 set(CMAKE_CXX_STANDARD 17)

+ 7 - 2
README.md

@@ -2,7 +2,8 @@
 
 ## Table of Contents
 
-- [Building](#building)
+- [Running from Docker](#running-from-docker)
+- [Building from Source](#building-from-source)
   - [Prerequisites](#requirements)
   - [Linux Install](#linux)
     - [Installing directly on your system](#system-level-installation)
@@ -11,7 +12,11 @@
 - [OpenFHE Python Wrapper Documentation](#openfhe-python-wrapper-documentation)
 - [Contributing Guide](#contributing-guide)
 
-## Building
+## Running from Docker
+
+Please see [Instructions for the Docker setup](docker/README.md)
+
+## Building from Source
 
 ### Requirements
 

+ 51 - 0
build_package.sh

@@ -0,0 +1,51 @@
+#!/bin/bash
+# Exit on any error
+set -e
+
+# Find the venv directory
+if [ -d ".venv" ]; then
+    VENV_DIR=".venv"
+elif [ -d "../.venv" ]; then
+    VENV_DIR="../.venv"
+else
+    echo "The virtual environment does not exist. Please run 'python -m venv .venv' to create it." >&2
+    exit 1
+fi
+
+# Activate the virtual environment
+source $VENV_DIR/bin/activate
+
+# Install pybind11-stubgen
+if ! pip show pybind11-stubgen > /dev/null; then
+    pip install pybind11-stubgen
+fi
+
+# Check if the virtual environment has the openfhe package installed
+if ! pip show openfhe > /dev/null; then
+    echo "The openfhe package is not installed in the virtual environment. Please run 'pip install -e .' to install it." >&2
+    exit 1
+fi
+
+# Generate stub files using pybind11-stubgen
+echo "Generating stub files..."
+pybind11-stubgen openfhe
+
+# Check if stub generation was successful
+if [ $? -eq 0 ]; then
+    echo "Stub files generated successfully."
+else
+    echo "Stub generation failed." >&2
+    exit 1
+fi
+
+# Move the generated stub files to the openfhe package directory
+echo "Moving the generated stub files to the openfhe package directory..."
+mv stubs/openfhe/* openfhe/
+rm -r -d stubs
+
+# Build the source distribution and wheel distribution
+echo "Building the sdist and bdist_wheel..."
+python setup.py sdist bdist_wheel
+
+# Indicate where the distributions were saved
+echo "The distributions have been built and are located in the 'dist' directory. You can install the package using 'pip install dist/<distribution_file>'."

+ 54 - 0
docker/Dockerfile

@@ -0,0 +1,54 @@
+# Use the official Ubuntu base image
+FROM ubuntu:22.04
+
+# Set environment variables to non-interactive (this prevents some prompts)
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Install necessary dependencies for OpenFHE and JupyterLab
+RUN apt-get update && apt-get install -y \
+    git \
+    cmake \
+    build-essential \
+    python3 \
+    python3-dev \
+    python3-pip \
+    python3-venv \
+    sudo \
+    && apt-get clean && rm -rf /var/lib/apt/lists/*
+
+# Install PyBind11
+RUN pip3 install "pybind11[global]"
+	
+# Install JupyterLab
+RUN python3 -m pip install --no-cache-dir jupyterlab
+
+# Clone and build OpenFHE-development
+RUN git clone https://github.com/openfheorg/openfhe-development.git \
+    && cd openfhe-development \
+    && mkdir build \
+    && cd build \
+    && cmake -DBUILD_UNITTESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_BENCHMARKS=OFF .. \
+    && make -j$(nproc) \
+    && make install
+
+# Assume that OpenFHE installs libraries into /usr/local/lib
+# Update LD_LIBRARY_PATH to include this directory
+ENV LD_LIBRARY_PATH=/usr/local/lib:${LD_LIBRARY_PATH}
+
+# Clone and build OpenFHE-Python
+RUN git clone https://github.com/openfheorg/openfhe-python.git \
+    && cd openfhe-python \
+    && mkdir build \
+    && cd build \
+    && cmake .. \
+    && make -j$(nproc) \
+    && make install
+
+# Expose the port JupyterLab will listen on
+EXPOSE 8888
+
+# Set the working directory
+WORKDIR /workspace
+
+# Start JupyterLab without token authentication
+CMD ["jupyter-lab", "--ip=0.0.0.0", "--no-browser", "--allow-root", "--NotebookApp.token=''", "--NotebookApp.allow_origin='*'", "--NotebookApp.password=''", "--NotebookApp.password_required=False"]

+ 52 - 0
docker/README.md

@@ -0,0 +1,52 @@
+# Readme
+
+### Command to build the docker image:
+
+```docker
+docker build -t openfhe-docker .
+```
+Make sure you run this command from the same folder where the Dockerfile is located (in the "docker" folder of the openfhe-python repository).
+
+### Command to check if the image is built:
+
+```docker
+docker images
+```
+
+You should see a "openfhe-docker" in the list
+
+### Command to create the container from the image:
+
+```docker
+docker run -d -p 8888:8888 openfhe-docker
+```
+
+### Command to check if the container is running:
+
+```docker
+docker ps
+```
+
+You should see openfhe-docker running
+
+### This openfhe-docker has jupyterlab installed in it which has access to openfhe installation and is accessible via localhost. To run the jupyterlab use:
+
+```docker
+[http://localhost:8888](http://localhost:8888/)
+```
+
+All the code can be executed through this jupyterlab now
+
+## Alternate way to execute the code in this docker:
+
+### Go inside the docker, use:
+
+```docker
+docker exec -it <container-name> /bin/bash
+```
+
+replace the <container-name> with the name that you see when you use the command "docker run -d -p 8888:8888 openfhe-docker"
+
+This takes you to a terminal interface inside the container which has all the dependencies installed.
+
+You can now clone a github repo that depends on OpenFHE and run the code.

+ 1 - 0
docs/requirements.txt

@@ -17,6 +17,7 @@ Pygments==2.11.2
 pyparsing==3.0.7
 pytz==2021.3
 requests==2.27.1
+setuptools==69.0.3
 snowballstemmer==2.2.0
 Sphinx==4.4.0
 sphinx-rtd-theme==1.0.0

+ 1 - 0
openfhe/__init__.py

@@ -0,0 +1 @@
+from .openfhe import *

+ 78 - 0
setup.py

@@ -0,0 +1,78 @@
+import os
+import subprocess
+import sys
+from setuptools import setup, Extension
+from setuptools.command.sdist import sdist as _sdist
+from setuptools.command.build_ext import build_ext as _build_ext
+from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
+import glob
+import shutil
+
+__version__ = '0.8.4'
+
+class CMakeExtension(Extension):
+    def __init__(self, name, sourcedir=''):
+        super().__init__(name, sources=[])
+        self.sourcedir = os.path.abspath(sourcedir)
+
+class CMakeBuild(_build_ext):
+
+    def run(self):
+        for ext in self.extensions:
+            self.build_cmake(ext)
+
+    def build_cmake(self, ext):
+        if os.path.exists('openfhe/openfhe.so'):
+            return
+        extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
+        print(extdir)
+        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
+                      '-DPYTHON_EXECUTABLE=' + sys.executable]
+
+        cfg = 'Debug' if self.debug else 'Release'
+        build_args = ['--config', cfg]
+
+        build_temp = os.path.abspath(self.build_temp)
+        os.makedirs(build_temp, exist_ok=True)
+
+        num_cores = os.cpu_count() or 1
+        build_args += ['--parallel', str(num_cores)]
+
+        subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=build_temp)
+        subprocess.check_call(['cmake', '--build', '.', '--target', ext.name] + build_args, cwd=build_temp)
+
+        so_files = glob.glob(os.path.join(extdir, '*.so'))
+        if not so_files:
+            raise RuntimeError("Cannot find any built .so file in " + extdir)
+
+        src_file = so_files[0] 
+        dst_file = os.path.join('openfhe', 'openfhe.so')
+        shutil.move(src_file, dst_file)
+
+# Run build_ext before sdist
+class SDist(_sdist):
+    def run(self):
+        if os.path.exists('openfhe/openfhe.so'):
+            os.remove('openfhe/openfhe.so')
+        self.run_command('build_ext')
+        super().run()
+
+setup(
+    name='openfhe',
+    version=__version__,
+    description='Python wrapper for OpenFHE C++ library.',
+    author='OpenFHE Team',
+    author_email='contact@openfhe.org',
+    url='https://github.com/openfheorg/openfhe-python',
+    license='BSD-2-Clause',
+    packages=['openfhe'],
+    package_data={'openfhe': ['*.so', '*.pyi']},
+    ext_modules=[CMakeExtension('openfhe', sourcedir='')],
+    cmdclass={
+        'build_ext': CMakeBuild,
+        'sdist': SDist
+    },
+    include_package_data=True,
+    python_requires=">=3.6",
+    install_requires=['pybind11', 'pybind11-global', 'pybind11-stubgen']
+)

+ 9 - 1
src/lib/pke/serialization.cpp

@@ -106,6 +106,10 @@ void bind_serialization(pybind11::module &m) {
           py::arg("filename"), py::arg("obj"), py::arg("sertype"));
     m.def("DeserializeCiphertext", static_cast<std::tuple<Ciphertext<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<Ciphertext<DCRTPoly>, SerType::SERJSON>),
           py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const EvalKey<DCRTPoly>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<EvalKey<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeEvalKey", static_cast<std::tuple<EvalKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<EvalKey<DCRTPoly>, SerType::SERJSON>),
+          py::arg("filename"), py::arg("sertype"));
     // Binary Serialization
     m.def("SerializeToFile", static_cast<bool (*)(const std::string&,const CryptoContext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<DCRTPoly>),
           py::arg("filename"), py::arg("obj"), py::arg("sertype"));
@@ -122,7 +126,11 @@ void bind_serialization(pybind11::module &m) {
     m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const Ciphertext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<Ciphertext<DCRTPoly>>),
           py::arg("filename"), py::arg("obj"), py::arg("sertype"));
     m.def("DeserializeCiphertext", static_cast<std::tuple<Ciphertext<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<Ciphertext<DCRTPoly>, SerType::SERBINARY>),
-            py::arg("filename"), py::arg("sertype"));   
+            py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const EvalKey<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<EvalKey<DCRTPoly>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeEvalKey", static_cast<std::tuple<EvalKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<EvalKey<DCRTPoly>, SerType::SERBINARY>),
+            py::arg("filename"), py::arg("sertype"));  
     
 }