Browse Source

Adding serialization/deserialization

Hovsep Papoyan 10 months ago
parent
commit
71fed67612
7 changed files with 1074 additions and 701 deletions
  1. 2 7
      .gitignore
  2. 6 5
      build.rs
  3. 551 0
      src/bindings.cc
  4. 243 0
      src/bindings.hpp
  5. 0 64
      src/direct.cc
  6. 0 255
      src/direct.hpp
  7. 272 370
      src/lib.rs

+ 2 - 7
.gitignore

@@ -1,14 +1,9 @@
 # Generated by Cargo
-# will have compiled files and executables
-debug/
+
 target/
 
 # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
 # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
-Cargo.lock
 
-# These are backup files generated by rustfmt
-**/*.rs.bk
+Cargo.lock
 
-# MSVC Windows builds of rustc generate these, which store debugging information
-*.pdb

+ 6 - 5
build.rs

@@ -1,7 +1,7 @@
 fn main()
 {
-    cxx_build::bridge("src/main.rs")
-        .file("src/direct.cc")
+    cxx_build::bridge("src/lib.rs")
+        .file("src/bindings.cc")
         .include("/usr/local/include/openfhe")
         .include("/usr/local/include/openfhe/third-party/include")
         .include("/usr/local/include/openfhe/core")
@@ -18,11 +18,12 @@ fn main()
         .flag_if_supported("-fPIE")
         .flag_if_supported("-Wno-unused-parameter") // [-Wunused-parameter]
         .flag_if_supported("-Wno-missing-field-initializers") // [-Wmissing-field-initializers]
+        .flag_if_supported("-Wno-unused-function") // [-Wunused-function]
         .compile("openfhe_rs_dev");
 
-    println!("cargo::rerun-if-changed=src/main.rs");
-    println!("cargo::rerun-if-changed=src/direct.hpp");
-    println!("cargo::rerun-if-changed=src/direct.cc");
+    println!("cargo::rerun-if-changed=src/lib.rs");
+    println!("cargo::rerun-if-changed=src/bindings.hpp");
+    println!("cargo::rerun-if-changed=src/bindings.cc");
 
     // linking additional shared libraries
     println!("cargo::rustc-link-arg=-L/usr/local/lib");

+ 551 - 0
src/bindings.cc

@@ -0,0 +1,551 @@
+#include "openfhe_rs_dev/src/lib.rs.h"
+
+#include "openfhe/pke/gen-cryptocontext.h"
+
+namespace openfhe_rs_dev
+{
+PublicKeyDCRTPoly::PublicKeyDCRTPoly()
+    : m_publicKey(std::make_shared<PublicKeyImpl>())
+{ }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+KeyPairDCRTPoly::KeyPairDCRTPoly(lbcrypto::KeyPair<lbcrypto::DCRTPoly> keyPair)
+    : m_publicKey(keyPair.publicKey)
+    , m_privateKey(keyPair.secretKey)
+{ }
+std::shared_ptr<PublicKeyImpl> KeyPairDCRTPoly::GetPublicKey() const
+{
+    return m_publicKey;
+}
+std::shared_ptr<PrivateKeyImpl> KeyPairDCRTPoly::GetPrivateKey() const
+{
+    return m_privateKey;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+Plaintext::Plaintext(std::shared_ptr<PlaintextImpl> plaintext)
+    : m_plaintext(plaintext)
+{ }
+Plaintext& Plaintext::operator=(std::shared_ptr<PlaintextImpl> plaintext)
+{
+    m_plaintext = plaintext;
+    return *this;
+}
+std::shared_ptr<PlaintextImpl> Plaintext::GetPlainText() const
+{
+    return m_plaintext;
+}
+void Plaintext::SetLength(const size_t newSize) const
+{
+    m_plaintext->SetLength(newSize);
+}
+double Plaintext::GetLogPrecision() const
+{
+    return m_plaintext->GetLogPrecision();
+}
+rust::String Plaintext::GetString() const
+{
+    std::stringstream stream;
+    stream << *m_plaintext;
+    return rust::String(stream.str());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+CiphertextDCRTPoly::CiphertextDCRTPoly()
+    : m_ciphertext(std::make_shared<CiphertextImpl>())
+{ }
+CiphertextDCRTPoly::CiphertextDCRTPoly(std::shared_ptr<CiphertextImpl> ciphertext)
+    : m_ciphertext(ciphertext)
+{ }
+std::shared_ptr<CiphertextImpl> CiphertextDCRTPoly::GetCipherText() const
+{
+    return m_ciphertext;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+CryptoContextDCRTPoly::CryptoContextDCRTPoly(const ParamsBFVRNS& params)
+    : m_cryptoContextImplSharedPtr(lbcrypto::GenCryptoContext(params))
+{ }
+CryptoContextDCRTPoly::CryptoContextDCRTPoly(const ParamsBGVRNS& params)
+    : m_cryptoContextImplSharedPtr(lbcrypto::GenCryptoContext(params))
+{ }
+CryptoContextDCRTPoly::CryptoContextDCRTPoly(const ParamsCKKSRNS& params)
+    : m_cryptoContextImplSharedPtr(lbcrypto::GenCryptoContext(params))
+{ }
+std::unique_ptr<Plaintext> CryptoContextDCRTPoly::MakeCKKSPackedPlaintextByVectorOfComplex(
+    const std::vector<SharedComplex>& value, const size_t scaleDeg, const uint32_t level,
+    const std::shared_ptr<DCRTPolyParams> params, const uint32_t slots) const
+{
+    std::vector<Complex> v;
+    v.reserve(value.size());
+    for (const SharedComplex& elem : value)
+    {
+        v.push_back(std::move(*elem.ptr));
+    }
+    return std::make_unique<Plaintext>(m_cryptoContextImplSharedPtr->MakeCKKSPackedPlaintext(
+        v, scaleDeg, level, params, slots));
+}
+void CryptoContextDCRTPoly::Enable(const PKESchemeFeature feature) const
+{
+    m_cryptoContextImplSharedPtr->Enable(feature);
+}
+std::unique_ptr<KeyPairDCRTPoly> CryptoContextDCRTPoly::KeyGen() const
+{
+    return std::make_unique<KeyPairDCRTPoly>(m_cryptoContextImplSharedPtr->KeyGen());
+}
+void CryptoContextDCRTPoly::EvalMultKeyGen(const std::shared_ptr<PrivateKeyImpl> key) const
+{
+    m_cryptoContextImplSharedPtr->EvalMultKeyGen(key);
+}
+void CryptoContextDCRTPoly::EvalRotateKeyGen(
+    const std::shared_ptr<PrivateKeyImpl> privateKey, const std::vector<int32_t>& indexList,
+    const std::shared_ptr<PublicKeyImpl> publicKey) const
+{
+    m_cryptoContextImplSharedPtr->EvalRotateKeyGen(privateKey, indexList, publicKey);
+}
+std::unique_ptr<Plaintext> CryptoContextDCRTPoly::MakePackedPlaintext(
+    const std::vector<int64_t>& value, const size_t noiseScaleDeg,
+    const uint32_t level) const
+{
+    return std::make_unique<Plaintext>(m_cryptoContextImplSharedPtr->MakePackedPlaintext(
+        value, noiseScaleDeg, level));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::Encrypt(
+    const std::shared_ptr<lbcrypto::PublicKeyImpl<lbcrypto::DCRTPoly>> publicKey,
+    std::shared_ptr<PlaintextImpl> plaintext) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->Encrypt(
+        publicKey, plaintext));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalAdd(
+    std::shared_ptr<CiphertextImpl> ciphertext1, std::shared_ptr<CiphertextImpl> ciphertext2) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalAdd(
+        ciphertext1, ciphertext2));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalSub(
+    std::shared_ptr<CiphertextImpl> ciphertext1, std::shared_ptr<CiphertextImpl> ciphertext2) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalSub(
+        ciphertext1, ciphertext2));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalMult(
+    std::shared_ptr<CiphertextImpl> ciphertext1, std::shared_ptr<CiphertextImpl> ciphertext2) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalMult(
+        ciphertext1, ciphertext2));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalMultByConst(
+    std::shared_ptr<CiphertextImpl> ciphertext, const double constant) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalMult(
+        ciphertext, constant));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalRotate(
+    std::shared_ptr<CiphertextImpl> ciphertext, const int32_t index) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(
+        m_cryptoContextImplSharedPtr->EvalRotate(ciphertext, index));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalChebyshevSeries(
+    std::shared_ptr<CiphertextImpl> ciphertext, const std::vector<double>& coefficients,
+    const double a, const double b) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalChebyshevSeries(
+        ciphertext, coefficients, a, b));
+}
+std::unique_ptr<DecryptResult> CryptoContextDCRTPoly::Decrypt(
+    const std::shared_ptr<PrivateKeyImpl> privateKey,
+    std::shared_ptr<CiphertextImpl> ciphertext, Plaintext& plaintext) const
+{
+    std::shared_ptr<PlaintextImpl> res;
+    std::unique_ptr<DecryptResult> result = std::make_unique<DecryptResult>(
+        m_cryptoContextImplSharedPtr->Decrypt(privateKey, ciphertext, &res));
+    plaintext = res;
+    return result;
+}
+uint32_t CryptoContextDCRTPoly::GetRingDimension() const
+{
+    return m_cryptoContextImplSharedPtr->GetRingDimension();
+}
+std::unique_ptr<Plaintext> CryptoContextDCRTPoly::MakeCKKSPackedPlaintext(
+    const std::vector<double>& value, const size_t scaleDeg, const uint32_t level,
+    const std::shared_ptr<DCRTPolyParams> params, const uint32_t slots) const
+{
+    return std::make_unique<Plaintext>(m_cryptoContextImplSharedPtr->MakeCKKSPackedPlaintext(
+        value, scaleDeg, level, params, slots));
+}
+std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalPoly(
+    std::shared_ptr<CiphertextImpl> ciphertext, const std::vector<double>& coefficients) const
+{
+    return std::make_unique<CiphertextDCRTPoly>(
+        m_cryptoContextImplSharedPtr->EvalPoly(ciphertext, coefficients));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+std::unique_ptr<std::vector<SharedComplex>> GenVectorOfComplex(
+    const std::vector<ComplexPair>& vals)
+{
+    std::vector<SharedComplex> result;
+    result.reserve(vals.size());
+    for (const ComplexPair& p : vals)
+    {
+        SharedComplex temp;
+        temp.ptr = std::make_shared<Complex>(p.re, p.im);
+        result.emplace_back(std::move(temp));
+    }
+    return std::make_unique<std::vector<SharedComplex>>(std::move(result));
+}
+std::unique_ptr<Params> GetParamsByScheme(const SCHEME scheme)
+{
+    return std::make_unique<Params>(scheme);
+}
+std::unique_ptr<Params> GetParamsByVectorOfString(const std::vector<std::string>& vals)
+{
+    return std::make_unique<Params>(vals);
+}
+std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNS()
+{
+    return std::make_unique<ParamsBFVRNS>();
+}
+std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNSbyVectorOfString(const std::vector<std::string>& vals)
+{
+    return std::make_unique<ParamsBFVRNS>(vals);
+}
+std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNS()
+{
+    return std::make_unique<ParamsBGVRNS>();
+}
+std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNSbyVectorOfString(const std::vector<std::string>& vals)
+{
+    return std::make_unique<ParamsBGVRNS>(vals);
+}
+std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNS()
+{
+    return std::make_unique<ParamsCKKSRNS>();
+}
+std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNSbyVectorOfString(const std::vector<std::string>& vals)
+{
+    return std::make_unique<ParamsCKKSRNS>(vals);
+}
+std::unique_ptr<Plaintext> GenEmptyPlainText()
+{
+    return std::make_unique<Plaintext>();
+}
+std::unique_ptr<CryptoContextDCRTPoly> GenEmptyCryptoContext()
+{
+    return std::make_unique<CryptoContextDCRTPoly>();
+}
+std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBFVRNS(const ParamsBFVRNS& params)
+{
+    return std::make_unique<CryptoContextDCRTPoly>(params);
+}
+std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBGVRNS(const ParamsBGVRNS& params)
+{
+    return std::make_unique<CryptoContextDCRTPoly>(params);
+}
+std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsCKKSRNS(const ParamsCKKSRNS& params)
+{
+    return std::make_unique<CryptoContextDCRTPoly>(params);
+}
+std::unique_ptr<PublicKeyDCRTPoly> GenDefaultConstructedPublicKey()
+{
+    return std::make_unique<PublicKeyDCRTPoly>();
+}
+std::unique_ptr<CiphertextDCRTPoly> GenDefaultConstructedCiphertext()
+{
+    return std::make_unique<CiphertextDCRTPoly>();
+}
+bool SerializeCryptoContextToFile(const std::string& ccLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
+{
+    if (serialMode == SerialMode::BINARY)
+    {
+        return lbcrypto::Serial::SerializeToFile(ccLocation,
+            cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::BINARY);
+    }
+    if (serialMode == SerialMode::JSON)
+    {
+        return lbcrypto::Serial::SerializeToFile(ccLocation,
+            cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::JSON);
+    }
+    return false;
+}
+bool DeserializeCryptoContextFromFile(const std::string& ccLocation,
+    CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
+{
+    if (serialMode == SerialMode::BINARY)
+    {
+        return lbcrypto::Serial::DeserializeFromFile(ccLocation,
+            cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::BINARY);
+    }
+    if (serialMode == SerialMode::JSON)
+    {
+        return lbcrypto::Serial::DeserializeFromFile(ccLocation,
+            cryptoContext.m_cryptoContextImplSharedPtr, lbcrypto::SerType::JSON);
+    }
+    return false;
+}
+bool SerializeEvalMultKeyToFile(const std::string& multKeyLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
+{
+    const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
+    const std::unique_ptr<std::ofstream, decltype(close)> ofs(
+        new std::ofstream(multKeyLocation, std::ios::out | std::ios::binary), close);
+
+    if (ofs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalMultKey(
+                *ofs, lbcrypto::SerType::BINARY, cryptoContext.m_cryptoContextImplSharedPtr);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalMultKey(
+                *ofs, lbcrypto::SerType::JSON, cryptoContext.m_cryptoContextImplSharedPtr);
+        }
+    }
+    return false;
+}
+bool SerializeEvalMultKeyByIdToFile(const std::string& multKeyLocation,
+    const SerialMode serialMode, const std::string& id)
+{
+    const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
+    const std::unique_ptr<std::ofstream, decltype(close)> ofs(
+        new std::ofstream(multKeyLocation, std::ios::out | std::ios::binary), close);
+
+    if (ofs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalMultKey(
+                *ofs, lbcrypto::SerType::BINARY, id);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalMultKey(
+                *ofs, lbcrypto::SerType::JSON, id);
+        }
+    }
+    return false;
+}
+bool DeserializeEvalMultKeyFromFile(const std::string& multKeyLocation,
+    const SerialMode serialMode)
+{
+    const auto close = [](std::ifstream* const ifs){ if (ifs->is_open()) { ifs->close(); } };
+    const std::unique_ptr<std::ifstream, decltype(close)> ifs(
+        new std::ifstream(multKeyLocation, std::ios::in | std::ios::binary), close);
+
+    if (ifs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::DeserializeEvalMultKey(
+                *ifs, lbcrypto::SerType::BINARY);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::DeserializeEvalMultKey(
+                *ifs, lbcrypto::SerType::JSON);
+        }
+    }
+    return false;
+}
+bool SerializeEvalSumKeyToFile(const std::string& sumKeyLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
+{
+    const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
+    const std::unique_ptr<std::ofstream, decltype(close)> ofs(
+        new std::ofstream(sumKeyLocation, std::ios::out | std::ios::binary), close);
+
+    if (ofs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalAutomorphismKey(
+                *ofs, lbcrypto::SerType::BINARY, cryptoContext.m_cryptoContextImplSharedPtr);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalAutomorphismKey(
+                *ofs, lbcrypto::SerType::JSON, cryptoContext.m_cryptoContextImplSharedPtr);
+        }
+    }
+    return false;
+}
+bool SerializeEvalSumKeyByIdToFile(const std::string& sumKeyLocation,
+    const SerialMode serialMode, const std::string& id)
+{
+    const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
+    const std::unique_ptr<std::ofstream, decltype(close)> ofs(
+        new std::ofstream(sumKeyLocation, std::ios::out | std::ios::binary), close);
+
+    if (ofs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalSumKey(
+                *ofs, lbcrypto::SerType::BINARY, id);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalSumKey(
+                *ofs, lbcrypto::SerType::JSON, id);
+        }
+    }
+    return false;
+}
+bool DeserializeEvalSumKeyFromFile(const std::string& sumKeyLocation, const SerialMode serialMode)
+{
+    const auto close = [](std::ifstream* const ifs){ if (ifs->is_open()) { ifs->close(); } };
+    const std::unique_ptr<std::ifstream, decltype(close)> ifs(
+        new std::ifstream(sumKeyLocation, std::ios::in | std::ios::binary), close);
+
+    if (ifs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::DeserializeEvalAutomorphismKey(
+                *ifs, lbcrypto::SerType::BINARY);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::DeserializeEvalAutomorphismKey(
+                *ifs, lbcrypto::SerType::JSON);
+        }
+    }
+    return false;
+}
+bool SerializeEvalAutomorphismKeyToFile(const std::string& automorphismKeyLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode)
+{
+    const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
+    const std::unique_ptr<std::ofstream, decltype(close)> ofs(
+        new std::ofstream(automorphismKeyLocation, std::ios::out | std::ios::binary), close);
+
+    if (ofs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalAutomorphismKey(
+                *ofs, lbcrypto::SerType::BINARY, cryptoContext.m_cryptoContextImplSharedPtr);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalAutomorphismKey(
+                *ofs, lbcrypto::SerType::JSON, cryptoContext.m_cryptoContextImplSharedPtr);
+        }
+    }
+    return false;
+}
+bool SerializeEvalAutomorphismKeyByIdToFile(const std::string& automorphismKeyLocation,
+    const SerialMode serialMode, const std::string& id)
+{
+    const auto close = [](std::ofstream* const ofs){ if (ofs->is_open()) { ofs->close(); } };
+    const std::unique_ptr<std::ofstream, decltype(close)> ofs(
+        new std::ofstream(automorphismKeyLocation, std::ios::out | std::ios::binary), close);
+
+    if (ofs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalAutomorphismKey(
+                *ofs, lbcrypto::SerType::BINARY, id);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::SerializeEvalAutomorphismKey(
+                *ofs, lbcrypto::SerType::JSON, id);
+        }
+    }
+    return false;
+}
+bool DeserializeEvalAutomorphismKeyFromFile(const std::string& automorphismKeyLocation,
+    const SerialMode serialMode)
+{
+    const auto close = [](std::ifstream* const ifs){ if (ifs->is_open()) { ifs->close(); } };
+    const std::unique_ptr<std::ifstream, decltype(close)> ifs(
+        new std::ifstream(automorphismKeyLocation, std::ios::in | std::ios::binary), close);
+
+    if (ifs->is_open())
+    {
+        if (serialMode == SerialMode::BINARY)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::DeserializeEvalAutomorphismKey(
+                *ifs, lbcrypto::SerType::BINARY);
+        }
+        if (serialMode == SerialMode::JSON)
+        {
+            return lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>::DeserializeEvalAutomorphismKey(
+                *ifs, lbcrypto::SerType::JSON);
+        }
+    }
+    return false;
+}
+bool SerializeCiphertextToFile(const std::string& ciphertextLocation,
+    const CiphertextDCRTPoly& ciphertext, const SerialMode serialMode)
+{
+    if (serialMode == SerialMode::BINARY)
+    {
+        return lbcrypto::Serial::SerializeToFile(ciphertextLocation,
+            ciphertext.m_ciphertext, lbcrypto::SerType::BINARY);
+    }
+    if (serialMode == SerialMode::JSON)
+    {
+        return lbcrypto::Serial::SerializeToFile(ciphertextLocation,
+            ciphertext.m_ciphertext, lbcrypto::SerType::JSON);
+    }
+    return false;
+}
+bool DeserializeCiphertextFromFile(const std::string& ciphertextLocation,
+    CiphertextDCRTPoly& ciphertext, const SerialMode serialMode)
+{
+    if (serialMode == SerialMode::BINARY)
+    {
+        return lbcrypto::Serial::DeserializeFromFile(ciphertextLocation,
+            ciphertext.m_ciphertext, lbcrypto::SerType::BINARY);
+    }
+    if (serialMode == SerialMode::JSON)
+    {
+        return lbcrypto::Serial::DeserializeFromFile(ciphertextLocation,
+            ciphertext.m_ciphertext, lbcrypto::SerType::JSON);
+    }
+    return false;
+}
+bool SerializePublicKeyToFile(const std::string& publicKeyLocation,
+    const PublicKeyDCRTPoly& publicKey, const SerialMode serialMode)
+{
+    if (serialMode == SerialMode::BINARY)
+    {
+        return lbcrypto::Serial::SerializeToFile(publicKeyLocation,
+            publicKey.m_publicKey, lbcrypto::SerType::BINARY);
+    }
+    if (serialMode == SerialMode::JSON)
+    {
+        return lbcrypto::Serial::SerializeToFile(publicKeyLocation,
+            publicKey.m_publicKey, lbcrypto::SerType::JSON);
+    }
+    return false;
+}
+bool DeserializePublicKeyFromFile(const std::string& publicKeyLocation,
+    PublicKeyDCRTPoly& publicKey, const SerialMode serialMode)
+{
+    if (serialMode == SerialMode::BINARY)
+    {
+        return lbcrypto::Serial::DeserializeFromFile(publicKeyLocation,
+            publicKey.m_publicKey, lbcrypto::SerType::BINARY);
+    }
+    if (serialMode == SerialMode::JSON)
+    {
+        return lbcrypto::Serial::DeserializeFromFile(publicKeyLocation,
+            publicKey.m_publicKey, lbcrypto::SerType::JSON);
+    }
+    return false;
+}
+} // openfhe_rs_dev

+ 243 - 0
src/bindings.hpp

@@ -0,0 +1,243 @@
+#pragma once
+
+#include "openfhe/pke/scheme/ckksrns/gen-cryptocontext-ckksrns.h"
+#include "openfhe/pke/scheme/bfvrns/gen-cryptocontext-bfvrns.h"
+#include "openfhe/pke/scheme/bgvrns/gen-cryptocontext-bgvrns.h"
+
+#include "rust/cxx.h" // rust::String
+
+enum SerialMode
+{
+    BINARY = 0,
+    JSON = 1,
+};
+
+namespace openfhe_rs_dev
+{
+using ParamsBFVRNS = lbcrypto::CCParams<lbcrypto::CryptoContextBFVRNS>;
+using ParamsBGVRNS = lbcrypto::CCParams<lbcrypto::CryptoContextBGVRNS>;
+using ParamsCKKSRNS = lbcrypto::CCParams<lbcrypto::CryptoContextCKKSRNS>;
+using Params = lbcrypto::Params;
+using SCHEME = lbcrypto::SCHEME;
+using SecretKeyDist = lbcrypto::SecretKeyDist;
+using ProxyReEncryptionMode = lbcrypto::ProxyReEncryptionMode;
+using MultipartyMode = lbcrypto::MultipartyMode;
+using ExecutionMode = lbcrypto::ExecutionMode;
+using DecryptionNoiseMode = lbcrypto::DecryptionNoiseMode;
+using KeySwitchTechnique = lbcrypto::KeySwitchTechnique;
+using ScalingTechnique = lbcrypto::ScalingTechnique;
+using SecurityLevel = lbcrypto::SecurityLevel;
+using EncryptionTechnique = lbcrypto::EncryptionTechnique;
+using MultiplicationTechnique = lbcrypto::MultiplicationTechnique;
+using COMPRESSION_LEVEL = lbcrypto::COMPRESSION_LEVEL;
+using PKESchemeFeature = lbcrypto::PKESchemeFeature;
+using PublicKeyImpl = lbcrypto::PublicKeyImpl<lbcrypto::DCRTPoly>;
+using PrivateKeyImpl = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>;
+using PlaintextImpl = lbcrypto::PlaintextImpl;
+using CiphertextImpl = lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>;
+using DecryptResult = lbcrypto::DecryptResult;
+using DCRTPolyParams = lbcrypto::DCRTPoly::Params;
+using ::SerialMode;
+struct ComplexPair;
+using Complex = std::complex<double>;
+struct SharedComplex;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class PublicKeyDCRTPoly final
+{
+    std::shared_ptr<PublicKeyImpl> m_publicKey;
+public:
+    friend bool SerializePublicKeyToFile(const std::string& publicKeyLocation,
+        const PublicKeyDCRTPoly& publicKey, const SerialMode serialMode);
+    friend bool DeserializePublicKeyFromFile(const std::string& publicKeyLocation,
+        PublicKeyDCRTPoly& publicKey, const SerialMode serialMode);
+
+    explicit PublicKeyDCRTPoly();
+    PublicKeyDCRTPoly(const PublicKeyDCRTPoly&) = delete;
+    PublicKeyDCRTPoly(PublicKeyDCRTPoly&&) = delete;
+    PublicKeyDCRTPoly& operator=(const PublicKeyDCRTPoly&) = delete;
+    PublicKeyDCRTPoly& operator=(PublicKeyDCRTPoly&&) = delete;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class KeyPairDCRTPoly final
+{
+    std::shared_ptr<PublicKeyImpl> m_publicKey;
+    std::shared_ptr<PrivateKeyImpl> m_privateKey;
+public:
+    explicit KeyPairDCRTPoly(lbcrypto::KeyPair<lbcrypto::DCRTPoly> keyPair);
+    KeyPairDCRTPoly(const KeyPairDCRTPoly&) = delete;
+    KeyPairDCRTPoly(KeyPairDCRTPoly&&) = delete;
+    KeyPairDCRTPoly& operator=(const KeyPairDCRTPoly&) = delete;
+    KeyPairDCRTPoly& operator=(KeyPairDCRTPoly&&) = delete;
+
+    [[nodiscard]] std::shared_ptr<PublicKeyImpl> GetPublicKey() const;
+    [[nodiscard]] std::shared_ptr<PrivateKeyImpl> GetPrivateKey() const;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class Plaintext final
+{
+    std::shared_ptr<PlaintextImpl> m_plaintext;
+public:
+    explicit Plaintext() = default;
+    explicit Plaintext(std::shared_ptr<PlaintextImpl> plaintext);
+    Plaintext(const Plaintext&) = delete;
+    Plaintext(Plaintext&&) = delete;
+    Plaintext& operator=(const Plaintext&) = delete;
+    Plaintext& operator=(Plaintext&&) = delete;
+    Plaintext& operator=(std::shared_ptr<PlaintextImpl> plaintext);
+
+    [[nodiscard]] std::shared_ptr<PlaintextImpl> GetPlainText() const;
+    void SetLength(const size_t newSize) const;
+    [[nodiscard]] double GetLogPrecision() const;
+    [[nodiscard]] rust::String GetString() const;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CiphertextDCRTPoly final
+{
+    std::shared_ptr<CiphertextImpl> m_ciphertext;
+public:
+    friend bool SerializeCiphertextToFile(const std::string& ciphertextLocation,
+        const CiphertextDCRTPoly& ciphertext, const SerialMode serialMode);
+    friend bool DeserializeCiphertextFromFile(const std::string& ciphertextLocation,
+        CiphertextDCRTPoly& ciphertext, const SerialMode serialMode);
+
+    explicit CiphertextDCRTPoly();
+    explicit CiphertextDCRTPoly(std::shared_ptr<CiphertextImpl> ciphertext);
+    CiphertextDCRTPoly(const CiphertextDCRTPoly&) = delete;
+    CiphertextDCRTPoly(CiphertextDCRTPoly&&) = delete;
+    CiphertextDCRTPoly& operator=(const CiphertextDCRTPoly&) = delete;
+    CiphertextDCRTPoly& operator=(CiphertextDCRTPoly&&) = delete;
+
+    [[nodiscard]] std::shared_ptr<CiphertextImpl> GetCipherText() const;
+};
+
+class CryptoContextDCRTPoly final
+{
+    std::shared_ptr<lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>> m_cryptoContextImplSharedPtr;
+public:
+    friend bool SerializeCryptoContextToFile(const std::string& ccLocation,
+        const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+    friend bool DeserializeCryptoContextFromFile(const std::string& ccLocation,
+        CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+    friend bool SerializeEvalMultKeyToFile(const std::string& multKeyLocation,
+        const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+    friend bool SerializeEvalSumKeyToFile(const std::string& sumKeyLocation,
+        const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+    friend bool SerializeEvalAutomorphismKeyToFile(const std::string& automorphismKeyLocation,
+        const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+
+    explicit CryptoContextDCRTPoly() = default;
+    explicit CryptoContextDCRTPoly(const ParamsBFVRNS& params);
+    explicit CryptoContextDCRTPoly(const ParamsBGVRNS& params);
+    explicit CryptoContextDCRTPoly(const ParamsCKKSRNS& params);
+    CryptoContextDCRTPoly(const CryptoContextDCRTPoly&) = delete;
+    CryptoContextDCRTPoly(CryptoContextDCRTPoly&&) = delete;
+    CryptoContextDCRTPoly& operator=(const CryptoContextDCRTPoly&) = delete;
+    CryptoContextDCRTPoly& operator=(CryptoContextDCRTPoly&&) = delete;
+
+    void Enable(const PKESchemeFeature feature) const;
+    [[nodiscard]] std::unique_ptr<KeyPairDCRTPoly> KeyGen() const;
+    void EvalMultKeyGen(const std::shared_ptr<PrivateKeyImpl> key) const;
+    void EvalRotateKeyGen(
+        const std::shared_ptr<PrivateKeyImpl> privateKey, const std::vector<int32_t>& indexList,
+        const std::shared_ptr<PublicKeyImpl> publicKey /* nullptr */) const;
+    [[nodiscard]] uint32_t GetRingDimension() const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> Encrypt(
+        const std::shared_ptr<PublicKeyImpl> publicKey,
+        std::shared_ptr<lbcrypto::PlaintextImpl> plaintext) const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalAdd(
+        std::shared_ptr<CiphertextImpl> ciphertext1,
+        std::shared_ptr<CiphertextImpl> ciphertext2) const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalSub(
+        std::shared_ptr<CiphertextImpl> ciphertext1,
+        std::shared_ptr<CiphertextImpl> ciphertext2) const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalMult(
+        std::shared_ptr<CiphertextImpl> ciphertext1,
+        std::shared_ptr<CiphertextImpl> ciphertext2) const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalMultByConst(
+        std::shared_ptr<CiphertextImpl> ciphertext, const double constant) const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalRotate(
+        std::shared_ptr<CiphertextImpl> ciphertext, const int32_t index) const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalPoly(
+        std::shared_ptr<CiphertextImpl> ciphertext, const std::vector<double>& coefficients) const;
+    [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalChebyshevSeries(
+        std::shared_ptr<CiphertextImpl> ciphertext, const std::vector<double>& coefficients,
+        const double a, const double b) const;
+    [[nodiscard]] std::unique_ptr<DecryptResult> Decrypt(
+        const std::shared_ptr<PrivateKeyImpl> privateKey,
+        std::shared_ptr<CiphertextImpl> ciphertext, Plaintext& plaintext) const;
+    [[nodiscard]] std::unique_ptr<Plaintext> MakePackedPlaintext(
+        const std::vector<int64_t>& value, const size_t noiseScaleDeg /* 1 */,
+        const uint32_t level /* 0 */) const;
+    [[nodiscard]] std::unique_ptr<Plaintext> MakeCKKSPackedPlaintext(
+        const std::vector<double>& value, const size_t scaleDeg /* 1 */,
+        const uint32_t level /* 0 */, const std::shared_ptr<DCRTPolyParams> params /* nullptr */,
+        const uint32_t slots /* 0 */) const;
+    [[nodiscard]] std::unique_ptr<Plaintext> MakeCKKSPackedPlaintextByVectorOfComplex(
+        const std::vector<SharedComplex>& value, const size_t scaleDeg /* 1 */,
+        const uint32_t level /* 0 */, const std::shared_ptr<DCRTPolyParams> params /* nullptr */,
+        const uint32_t slots /* 0 */) const;
+};
+
+[[nodiscard]] std::unique_ptr<std::vector<SharedComplex>> GenVectorOfComplex(
+    const std::vector<ComplexPair>& vals);
+[[nodiscard]] std::unique_ptr<Params> GetParamsByScheme(const SCHEME scheme);
+[[nodiscard]] std::unique_ptr<Params> GetParamsByVectorOfString(
+    const std::vector<std::string>& vals);
+[[nodiscard]] std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNS();
+[[nodiscard]] std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNSbyVectorOfString(
+    const std::vector<std::string>& vals);
+[[nodiscard]] std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNS();
+[[nodiscard]] std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNSbyVectorOfString(
+    const std::vector<std::string>& vals);
+[[nodiscard]] std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNS();
+[[nodiscard]] std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNSbyVectorOfString(
+    const std::vector<std::string>& vals);
+[[nodiscard]] std::unique_ptr<Plaintext> GenEmptyPlainText();
+[[nodiscard]] std::unique_ptr<CryptoContextDCRTPoly> GenEmptyCryptoContext();
+[[nodiscard]] std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBFVRNS(
+    const ParamsBFVRNS& params);
+[[nodiscard]] std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBGVRNS(
+    const ParamsBGVRNS& params);
+[[nodiscard]] std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsCKKSRNS(
+    const ParamsCKKSRNS& params);
+[[nodiscard]] std::unique_ptr<PublicKeyDCRTPoly> GenDefaultConstructedPublicKey();
+[[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> GenDefaultConstructedCiphertext();
+
+bool SerializeCryptoContextToFile(const std::string& ccLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+bool DeserializeCryptoContextFromFile(const std::string& ccLocation,
+    CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+bool SerializeEvalMultKeyToFile(const std::string& multKeyLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+bool SerializeEvalMultKeyByIdToFile(const std::string& multKeyLocation,
+    const SerialMode serialMode, const std::string& id);
+bool DeserializeEvalMultKeyFromFile(const std::string& multKeyLocation,
+    const SerialMode serialMode);
+bool SerializeEvalSumKeyToFile(const std::string& sumKeyLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+bool SerializeEvalSumKeyByIdToFile(const std::string& sumKeyLocation,
+    const SerialMode serialMode, const std::string& id);
+bool DeserializeEvalSumKeyFromFile(const std::string& sumKeyLocation, const SerialMode serialMode);
+bool SerializeEvalAutomorphismKeyToFile(const std::string& automorphismKeyLocation,
+    const CryptoContextDCRTPoly& cryptoContext, const SerialMode serialMode);
+bool SerializeEvalAutomorphismKeyByIdToFile(const std::string& automorphismKeyLocation,
+    const SerialMode serialMode, const std::string& id);
+bool DeserializeEvalAutomorphismKeyFromFile(const std::string& automorphismKeyLocation,
+    const SerialMode serialMode);
+bool SerializeCiphertextToFile(const std::string& ciphertextLocation,
+    const CiphertextDCRTPoly& ciphertext, const SerialMode serialMode);
+bool DeserializeCiphertextFromFile(const std::string& ciphertextLocation,
+    CiphertextDCRTPoly& ciphertext, const SerialMode serialMode);
+bool SerializePublicKeyToFile(const std::string& publicKeyLocation,
+    const PublicKeyDCRTPoly& publicKey, const SerialMode serialMode);
+bool DeserializePublicKeyFromFile(const std::string& publicKeyLocation,
+    PublicKeyDCRTPoly& publicKey, const SerialMode serialMode);
+} // openfhe_rs_dev

+ 0 - 64
src/direct.cc

@@ -1,64 +0,0 @@
-#include "openfhe_rs_dev/src/main.rs.h"
-
-namespace openfhe_rs_dev
-{
-std::unique_ptr<VectorOfComplexNumbers> GenVectorOfComplexNumbers(const std::vector<ComplexPair>& vals)
-{
-    std::vector<std::complex<double>> result;
-    result.reserve(vals.size());
-    for (const ComplexPair& p : vals)
-    {
-        result.emplace_back(p.re, p.im);
-    }
-    return std::make_unique<VectorOfComplexNumbers>(std::move(result));
-}
-std::unique_ptr<Params> GetParamsByScheme(const SCHEME scheme)
-{
-    return std::make_unique<Params>(scheme);
-}
-std::unique_ptr<Params> GetParamsByVectorOfString(const std::vector<std::string>& vals)
-{
-    return std::make_unique<Params>(vals);
-}
-std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNS()
-{
-    return std::make_unique<ParamsBFVRNS>();
-}
-std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNSbyVectorOfString(const std::vector<std::string>& vals)
-{
-    return std::make_unique<ParamsBFVRNS>(vals);
-}
-std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNS()
-{
-    return std::make_unique<ParamsBGVRNS>();
-}
-std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNSbyVectorOfString(const std::vector<std::string>& vals)
-{
-    return std::make_unique<ParamsBGVRNS>(vals);
-}
-std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNS()
-{
-    return std::make_unique<ParamsCKKSRNS>();
-}
-std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNSbyVectorOfString(const std::vector<std::string>& vals)
-{
-    return std::make_unique<ParamsCKKSRNS>(vals);
-}
-std::unique_ptr<Plaintext> GenEmptyPlainText()
-{
-    return std::make_unique<Plaintext>();
-}
-std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBFVRNS(const ParamsBFVRNS& params)
-{
-    return std::make_unique<CryptoContextDCRTPoly>(params);
-}
-std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBGVRNS(const ParamsBGVRNS& params)
-{
-    return std::make_unique<CryptoContextDCRTPoly>(params);
-}
-std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsCKKSRNS(const ParamsCKKSRNS& params)
-{
-    return std::make_unique<CryptoContextDCRTPoly>(params);
-}
-} // openfhe_rs_dev
-

+ 0 - 255
src/direct.hpp

@@ -1,255 +0,0 @@
-#pragma once
-
-#include <memory>
-#include <sstream>
-#include "rust/cxx.h" // rust::String
-
-#include "openfhe/pke/scheme/gen-cryptocontext-params.h"
-#include "openfhe/pke/scheme/bfvrns/gen-cryptocontext-bfvrns-params.h"
-#include "openfhe/pke/scheme/bgvrns/gen-cryptocontext-bgvrns-params.h"
-#include "openfhe/pke/scheme/ckksrns/gen-cryptocontext-ckksrns-params.h"
-
-#include "openfhe/pke/gen-cryptocontext.h"
-#include "openfhe/pke/scheme/bfvrns/gen-cryptocontext-bfvrns.h"
-#include "openfhe/pke/scheme/bgvrns/gen-cryptocontext-bgvrns.h"
-#include "openfhe/pke/scheme/ckksrns/gen-cryptocontext-ckksrns.h"
-
-#include "openfhe/pke/scheme/scheme-id.h" // enums
-#include "openfhe/core/lattice/constants-lattice.h" // enums
-#include "openfhe/pke/constants-fwd.h" // enumss
-#include "openfhe/core/lattice/stdlatticeparms.h" // enums
-#include "openfhe/pke/key/keypair.h"
-#include "openfhe/core/utils/inttypes.h"
-
-#include "openfhe/pke/key/keypair.h"
-#include "openfhe/pke/key/privatekey.h"
-#include "openfhe/pke/key/publickey.h"
-
-#include "openfhe/pke/ciphertext.h"
-#include "openfhe/pke/encoding/plaintext.h"
-#include "openfhe/pke/schemebase/decrypt-result.h"
-
-namespace openfhe_rs_dev
-{
-    using ParamsBFVRNS = lbcrypto::CCParams<lbcrypto::CryptoContextBFVRNS>;
-    using ParamsBGVRNS = lbcrypto::CCParams<lbcrypto::CryptoContextBGVRNS>;
-    using ParamsCKKSRNS = lbcrypto::CCParams<lbcrypto::CryptoContextCKKSRNS>;
-    using Params = lbcrypto::Params;
-    using SCHEME = lbcrypto::SCHEME;
-    using SecretKeyDist = lbcrypto::SecretKeyDist;
-    using ProxyReEncryptionMode = lbcrypto::ProxyReEncryptionMode;
-    using MultipartyMode = lbcrypto::MultipartyMode;
-    using ExecutionMode = lbcrypto::ExecutionMode;
-    using DecryptionNoiseMode = lbcrypto::DecryptionNoiseMode;
-    using KeySwitchTechnique = lbcrypto::KeySwitchTechnique;
-    using ScalingTechnique = lbcrypto::ScalingTechnique;
-    using SecurityLevel = lbcrypto::SecurityLevel;
-    using EncryptionTechnique = lbcrypto::EncryptionTechnique;
-    using MultiplicationTechnique = lbcrypto::MultiplicationTechnique;
-    using COMPRESSION_LEVEL = lbcrypto::COMPRESSION_LEVEL;
-    using PKESchemeFeature = lbcrypto::PKESchemeFeature;
-    using PublicKeyImpl = lbcrypto::PublicKeyImpl<lbcrypto::DCRTPoly>;
-    using PrivateKeyImpl = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>;
-    using PlaintextImpl = lbcrypto::PlaintextImpl;
-    using CiphertextImpl = lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>;
-    using DecryptResult = lbcrypto::DecryptResult;
-    using DCRTPolyParams = lbcrypto::DCRTPoly::Params;
-    struct ComplexPair;
-    using VectorOfComplexNumbers = std::vector<std::complex<double>>;
-
-    class KeyPairDCRTPoly final
-    {
-    private:
-        std::shared_ptr<PublicKeyImpl> m_publicKey;
-        std::shared_ptr<PrivateKeyImpl> m_privateKey;
-
-    public:
-        // TODO: think about all special functions of class
-        explicit KeyPairDCRTPoly(lbcrypto::KeyPair<lbcrypto::DCRTPoly> keyPair)
-            : m_publicKey(keyPair.publicKey)
-            , m_privateKey(keyPair.secretKey)
-        { }
-        std::shared_ptr<PublicKeyImpl> GetPublicKey() const
-        {
-            return m_publicKey;
-        }
-        std::shared_ptr<PrivateKeyImpl> GetPrivateKey() const
-        {
-            return m_privateKey;
-        }
-        // TODO: implement necessary member functions
-    };
-
-    class Plaintext final
-    {
-    private:
-        std::shared_ptr<lbcrypto::PlaintextImpl> m_plaintext;
-
-    public:
-        // TODO: think about all special functions of class
-        explicit Plaintext() = default;
-        explicit Plaintext(std::shared_ptr<lbcrypto::PlaintextImpl> plaintext)
-            : m_plaintext(plaintext)
-        { }
-        Plaintext& operator=(std::shared_ptr<lbcrypto::PlaintextImpl> plaintext)
-        {
-            m_plaintext = plaintext;
-            return *this;
-        }
-        std::shared_ptr<lbcrypto::PlaintextImpl> GetPlainText() const
-        {
-            return m_plaintext;
-        }
-        void SetLength(const size_t newSize) const
-        {
-            if (m_plaintext)
-            {
-                m_plaintext->SetLength(newSize);
-            }
-        }
-        double GetLogPrecision() const
-        {
-            return m_plaintext->GetLogPrecision();
-        }
-        rust::String GetString() const
-        {
-            if (m_plaintext)
-            {
-                std::stringstream stream;
-                stream << *m_plaintext;
-                return rust::String(stream.str());
-            }
-            return rust::String();
-        }
-        // TODO: implement necessary member functions
-    };
-
-
-
-    class CiphertextDCRTPoly final
-    {
-    private:
-        std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> m_ciphertext;
-
-    public:
-        // TODO: think about all special functions of class
-        explicit CiphertextDCRTPoly(std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext)
-            : m_ciphertext(ciphertext)
-        { }
-        std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> GetCipherText() const
-        {
-            return m_ciphertext;
-        }
-        // TODO: implement necessary member functions
-    };
-
-    class CryptoContextDCRTPoly final
-    {
-    private:
-        std::shared_ptr<lbcrypto::CryptoContextImpl<lbcrypto::DCRTPoly>> m_cryptoContextImplSharedPtr;
-
-    public:
-        // TODO: think about all special functions of class
-        explicit CryptoContextDCRTPoly(const ParamsBFVRNS& params)
-            : m_cryptoContextImplSharedPtr(lbcrypto::GenCryptoContext(params))
-        { }
-        explicit CryptoContextDCRTPoly(const ParamsBGVRNS& params)
-            : m_cryptoContextImplSharedPtr(lbcrypto::GenCryptoContext(params))
-        { }
-        explicit CryptoContextDCRTPoly(const ParamsCKKSRNS& params)
-            : m_cryptoContextImplSharedPtr(lbcrypto::GenCryptoContext(params))
-        { }
-        void Enable(const PKESchemeFeature feature) const
-        {
-            m_cryptoContextImplSharedPtr->Enable(feature);
-        }
-        std::unique_ptr<KeyPairDCRTPoly> KeyGen() const
-        {
-            return std::make_unique<KeyPairDCRTPoly>(m_cryptoContextImplSharedPtr->KeyGen());
-        }
-        void EvalMultKeyGen(const std::shared_ptr<lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>> key) const
-        {
-            m_cryptoContextImplSharedPtr->EvalMultKeyGen(key);
-        }
-        void EvalRotateKeyGen(const std::shared_ptr<lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>> privateKey, const std::vector<int32_t>& indexList,
-							                const std::shared_ptr<lbcrypto::PublicKeyImpl<lbcrypto::DCRTPoly>> publicKey) const // publicKey = nullptr in original. Rust don't support default args.
-        {
-            m_cryptoContextImplSharedPtr->EvalRotateKeyGen(privateKey, indexList, publicKey);
-        }
-        std::unique_ptr<Plaintext> MakePackedPlaintext(const std::vector<int64_t>& value, const size_t noiseScaleDeg, const uint32_t level) const // noiseScaleDeg = 1, level = 0
-        {
-            return std::make_unique<Plaintext>(m_cryptoContextImplSharedPtr->MakePackedPlaintext(value, noiseScaleDeg, level));
-        }
-        std::unique_ptr<CiphertextDCRTPoly> Encrypt(const std::shared_ptr<lbcrypto::PublicKeyImpl<lbcrypto::DCRTPoly>> publicKey, std::shared_ptr<lbcrypto::PlaintextImpl> plaintext) const
-        {
-            return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->Encrypt(publicKey, plaintext));
-        }
-        std::unique_ptr<CiphertextDCRTPoly> EvalAdd(std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext1,
-                                                    std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext2) const
-        {
-            return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalAdd(ciphertext1, ciphertext2));
-        }
-        std::unique_ptr<CiphertextDCRTPoly> EvalSub(std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext1,
-                                                    std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext2) const
-        {
-            return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalSub(ciphertext1, ciphertext2));
-        }
-
-        std::unique_ptr<CiphertextDCRTPoly> EvalMult(std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext1,
-                                                     std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext2) const
-        {
-            return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalMult(ciphertext1, ciphertext2));
-        }
-        std::unique_ptr<CiphertextDCRTPoly> EvalMultByConst(std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext, const double constant) const
-        {
-            return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalMult(ciphertext, constant));
-        }
-        std::unique_ptr<CiphertextDCRTPoly> EvalRotate(std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext, const int32_t index) const
-        {
-            return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalRotate(ciphertext, index));
-        }
-        std::unique_ptr<DecryptResult> Decrypt(const std::shared_ptr<lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>> privateKey,
-                                               std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext, Plaintext& plaintext) const
-        {
-            std::shared_ptr<lbcrypto::PlaintextImpl> res;
-            std::unique_ptr<DecryptResult> result = std::make_unique<DecryptResult>(m_cryptoContextImplSharedPtr->Decrypt(privateKey, ciphertext, &res));
-            plaintext = res;
-            return result;
-        }
-        uint32_t GetRingDimension() const
-        {
-            return m_cryptoContextImplSharedPtr->GetRingDimension();
-        }
-        std::unique_ptr<Plaintext> MakeCKKSPackedPlaintext(const std::vector<double>& value, const size_t scaleDeg, const uint32_t level,
-                                                           const std::shared_ptr<DCRTPolyParams> params, const uint32_t slots) const
-                                                           // scaleDeg = 1, level = 0, params = nullptr, slots = 0
-        {
-            return std::make_unique<Plaintext>(m_cryptoContextImplSharedPtr->MakeCKKSPackedPlaintext(value, scaleDeg, level, params, slots));
-        }
-        std::unique_ptr<Plaintext> MakeCKKSPackedPlaintextByVectorOfComplexNumbers(const std::vector<std::complex<double>>& value, const size_t scaleDeg, const uint32_t level,
-                                                                                   const std::shared_ptr<DCRTPolyParams> params, const uint32_t slots) const
-                                                                                   // scaleDeg = 1, level = 0, params = nullptr, slots = 0
-        {
-            return std::make_unique<Plaintext>(m_cryptoContextImplSharedPtr->MakeCKKSPackedPlaintext(value, scaleDeg, level, params, slots));
-        }
-        std::unique_ptr<CiphertextDCRTPoly> EvalPoly(std::shared_ptr<lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>> ciphertext, const std::vector<double>& coefficients) const
-        {
-            return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->EvalPoly(ciphertext, coefficients));
-        }
-    };
-
-    std::unique_ptr<VectorOfComplexNumbers> GenVectorOfComplexNumbers(const std::vector<ComplexPair>& vals);
-    std::unique_ptr<Params> GetParamsByScheme(const SCHEME scheme);
-    std::unique_ptr<Params> GetParamsByVectorOfString(const std::vector<std::string>& vals);
-    std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNS();
-    std::unique_ptr<ParamsBFVRNS> GetParamsBFVRNSbyVectorOfString(const std::vector<std::string>& vals);
-    std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNS();
-    std::unique_ptr<ParamsBGVRNS> GetParamsBGVRNSbyVectorOfString(const std::vector<std::string>& vals);
-    std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNS();
-    std::unique_ptr<ParamsCKKSRNS> GetParamsCKKSRNSbyVectorOfString(const std::vector<std::string>& vals);
-    std::unique_ptr<Plaintext> GenEmptyPlainText();
-    std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBFVRNS(const ParamsBFVRNS& params);
-    std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsBGVRNS(const ParamsBGVRNS& params);
-    std::unique_ptr<CryptoContextDCRTPoly> GenCryptoContextByParamsCKKSRNS(const ParamsCKKSRNS& params);
-} // openfhe_rs_dev
-

+ 272 - 370
src/main.rs → src/lib.rs

@@ -1,8 +1,8 @@
 #![allow(non_snake_case)]
 #![allow(dead_code)]
+#![allow(unused_imports)]
 
-use cxx::{CxxVector, SharedPtr};
-use std::time::Instant;
+use cxx::{CxxVector, SharedPtr, let_cxx_string};
 
 #[cxx::bridge(namespace = "openfhe_rs_dev")]
 mod ffi
@@ -110,10 +110,16 @@ mod ffi
         FHE          = 0x40,
         SCHEMESWITCH = 0x80,
     }
+    #[repr(i32)]
+    enum SerialMode
+    {
+        BINARY = 0,
+        JSON = 1,
+    }
 
     unsafe extern "C++"
     {
-        include!("openfhe_rs_dev/src/direct.hpp");
+        include!("openfhe_rs_dev/src/bindings.hpp");
         type SCHEME;
         type Params;
         type SecretKeyDist;
@@ -141,6 +147,9 @@ mod ffi
         type CiphertextDCRTPoly;
         type DecryptResult;
         type DCRTPolyParams;
+        type SerialMode;
+        type PublicKeyDCRTPoly;
+        type Complex;
     }
 
     // Params
@@ -151,8 +160,8 @@ mod ffi
 
         // getters
         fn GetScheme(self: &Params) -> SCHEME;
-        fn GetPlaintextModulus(self: &Params) -> u64; // PlaintextModulus
-        fn GetDigitSize(self: &Params) -> u32; // usint
+        fn GetPlaintextModulus(self: &Params) -> u64;
+        fn GetDigitSize(self: &Params) -> u32;
         fn GetStandardDeviation(self: &Params) -> f32;
         fn GetSecretKeyDist(self: &Params) -> SecretKeyDist;
         fn GetMaxRelinSkDeg(self: &Params) -> u32;
@@ -181,7 +190,7 @@ mod ffi
         fn GetMultiHopModSize(self: &Params) -> u32;
         fn GetInteractiveBootCompressionLevel(self: &Params) -> COMPRESSION_LEVEL;
         // setters
-        fn SetPlaintextModulus(self: Pin<&mut Params>, ptModulus0: u64); // PlaintextModulus
+        fn SetPlaintextModulus(self: Pin<&mut Params>, ptModulus0: u64);
         fn SetDigitSize(self: Pin<&mut Params>, digitSize0: u32);
         fn SetStandardDeviation(self: Pin<&mut Params>, standardDeviation0: f32);
         fn SetSecretKeyDist(self: Pin<&mut Params>, secretKeyDist0: SecretKeyDist);
@@ -189,7 +198,8 @@ mod ffi
         fn SetPREMode(self: Pin<&mut Params>, PREMode0: ProxyReEncryptionMode);
         fn SetMultipartyMode(self: Pin<&mut Params>, multipartyMode0: MultipartyMode);
         fn SetExecutionMode(self: Pin<&mut Params>, executionMode0: ExecutionMode);
-        fn SetDecryptionNoiseMode(self: Pin<&mut Params>, decryptionNoiseMode0: DecryptionNoiseMode);
+        fn SetDecryptionNoiseMode(self: Pin<&mut Params>,
+                                  decryptionNoiseMode0: DecryptionNoiseMode);
         fn SetNoiseEstimate(self: Pin<&mut Params>, noiseEstimate0: f64);
         fn SetDesiredPrecision(self: Pin<&mut Params>, desiredPrecision0: f64);
         fn SetStatisticalSecurity(self: Pin<&mut Params>, statisticalSecurity0: u32);
@@ -206,10 +216,13 @@ mod ffi
         fn SetRingDim(self: Pin<&mut Params>, ringDim0: u32);
         fn SetEvalAddCount(self: Pin<&mut Params>, evalAddCount0: u32);
         fn SetKeySwitchCount(self: Pin<&mut Params>, keySwitchCount0: u32);
-        fn SetEncryptionTechnique(self: Pin<&mut Params>, encryptionTechnique0: EncryptionTechnique);
-        fn SetMultiplicationTechnique(self: Pin<&mut Params>, multiplicationTechnique0: MultiplicationTechnique);
+        fn SetEncryptionTechnique(self: Pin<&mut Params>,
+                                  encryptionTechnique0: EncryptionTechnique);
+        fn SetMultiplicationTechnique(self: Pin<&mut Params>,
+                                      multiplicationTechnique0: MultiplicationTechnique);
         fn SetMultiHopModSize(self: Pin<&mut Params>, multiHopModSize0: u32);
-        fn SetInteractiveBootCompressionLevel(self: Pin<&mut Params>, interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
+        fn SetInteractiveBootCompressionLevel(self: Pin<&mut Params>,
+                                              interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
     }
 
     // ParamsBFVRNS
@@ -219,8 +232,8 @@ mod ffi
         fn GetParamsBFVRNSbyVectorOfString(vals: &CxxVector<CxxString>) -> UniquePtr<ParamsBFVRNS>;
         // getters
         fn GetScheme(self: &ParamsBFVRNS) -> SCHEME;
-        fn GetPlaintextModulus(self: &ParamsBFVRNS) -> u64; // PlaintextModulus
-        fn GetDigitSize(self: &ParamsBFVRNS) -> u32; // usint
+        fn GetPlaintextModulus(self: &ParamsBFVRNS) -> u64;
+        fn GetDigitSize(self: &ParamsBFVRNS) -> u32;
         fn GetStandardDeviation(self: &ParamsBFVRNS) -> f32;
         fn GetSecretKeyDist(self: &ParamsBFVRNS) -> SecretKeyDist;
         fn GetMaxRelinSkDeg(self: &ParamsBFVRNS) -> u32;
@@ -249,7 +262,7 @@ mod ffi
         fn GetMultiHopModSize(self: &ParamsBFVRNS) -> u32;
         fn GetInteractiveBootCompressionLevel(self: &ParamsBFVRNS) -> COMPRESSION_LEVEL;
         // setters
-        fn SetPlaintextModulus(self: Pin<&mut ParamsBFVRNS>, ptModulus0: u64); // PlaintextModulus
+        fn SetPlaintextModulus(self: Pin<&mut ParamsBFVRNS>, ptModulus0: u64);
         fn SetDigitSize(self: Pin<&mut ParamsBFVRNS>, digitSize0: u32);
         fn SetStandardDeviation(self: Pin<&mut ParamsBFVRNS>, standardDeviation0: f32);
         fn SetSecretKeyDist(self: Pin<&mut ParamsBFVRNS>, secretKeyDist0: SecretKeyDist);
@@ -257,7 +270,8 @@ mod ffi
         fn SetPREMode(self: Pin<&mut ParamsBFVRNS>, PREMode0: ProxyReEncryptionMode);
         fn SetMultipartyMode(self: Pin<&mut ParamsBFVRNS>, multipartyMode0: MultipartyMode);
         fn SetExecutionMode(self: Pin<&mut ParamsBFVRNS>, executionMode0: ExecutionMode);
-        fn SetDecryptionNoiseMode(self: Pin<&mut ParamsBFVRNS>, decryptionNoiseMode0: DecryptionNoiseMode);
+        fn SetDecryptionNoiseMode(self: Pin<&mut ParamsBFVRNS>,
+                                  decryptionNoiseMode0: DecryptionNoiseMode);
         fn SetNoiseEstimate(self: Pin<&mut ParamsBFVRNS>, noiseEstimate0: f64);
         fn SetDesiredPrecision(self: Pin<&mut ParamsBFVRNS>, desiredPrecision0: f64);
         fn SetStatisticalSecurity(self: Pin<&mut ParamsBFVRNS>, statisticalSecurity0: u32);
@@ -274,10 +288,13 @@ mod ffi
         fn SetRingDim(self: Pin<&mut ParamsBFVRNS>, ringDim0: u32);
         fn SetEvalAddCount(self: Pin<&mut ParamsBFVRNS>, evalAddCount0: u32);
         fn SetKeySwitchCount(self: Pin<&mut ParamsBFVRNS>, keySwitchCount0: u32);
-        fn SetEncryptionTechnique(self: Pin<&mut ParamsBFVRNS>, encryptionTechnique0: EncryptionTechnique);
-        fn SetMultiplicationTechnique(self: Pin<&mut ParamsBFVRNS>, multiplicationTechnique0: MultiplicationTechnique);
+        fn SetEncryptionTechnique(self: Pin<&mut ParamsBFVRNS>,
+                                  encryptionTechnique0: EncryptionTechnique);
+        fn SetMultiplicationTechnique(self: Pin<&mut ParamsBFVRNS>,
+                                      multiplicationTechnique0: MultiplicationTechnique);
         fn SetMultiHopModSize(self: Pin<&mut ParamsBFVRNS>, multiHopModSize0: u32);
-        fn SetInteractiveBootCompressionLevel(self: Pin<&mut ParamsBFVRNS>, interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
+        fn SetInteractiveBootCompressionLevel(self: Pin<&mut ParamsBFVRNS>,
+                                              interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
     }
 
     // ParamsBGVRNS
@@ -287,8 +304,8 @@ mod ffi
         fn GetParamsBGVRNSbyVectorOfString(vals: &CxxVector<CxxString>) -> UniquePtr<ParamsBGVRNS>;
         // getters
         fn GetScheme(self: &ParamsBGVRNS) -> SCHEME;
-        fn GetPlaintextModulus(self: &ParamsBGVRNS) -> u64; // PlaintextModulus
-        fn GetDigitSize(self: &ParamsBGVRNS) -> u32; // usint
+        fn GetPlaintextModulus(self: &ParamsBGVRNS) -> u64;
+        fn GetDigitSize(self: &ParamsBGVRNS) -> u32;
         fn GetStandardDeviation(self: &ParamsBGVRNS) -> f32;
         fn GetSecretKeyDist(self: &ParamsBGVRNS) -> SecretKeyDist;
         fn GetMaxRelinSkDeg(self: &ParamsBGVRNS) -> u32;
@@ -317,7 +334,7 @@ mod ffi
         fn GetMultiHopModSize(self: &ParamsBGVRNS) -> u32;
         fn GetInteractiveBootCompressionLevel(self: &ParamsBGVRNS) -> COMPRESSION_LEVEL;
         // setters
-        fn SetPlaintextModulus(self: Pin<&mut ParamsBGVRNS>, ptModulus0: u64); // PlaintextModulus
+        fn SetPlaintextModulus(self: Pin<&mut ParamsBGVRNS>, ptModulus0: u64);
         fn SetDigitSize(self: Pin<&mut ParamsBGVRNS>, digitSize0: u32);
         fn SetStandardDeviation(self: Pin<&mut ParamsBGVRNS>, standardDeviation0: f32);
         fn SetSecretKeyDist(self: Pin<&mut ParamsBGVRNS>, secretKeyDist0: SecretKeyDist);
@@ -325,7 +342,8 @@ mod ffi
         fn SetPREMode(self: Pin<&mut ParamsBGVRNS>, PREMode0: ProxyReEncryptionMode);
         fn SetMultipartyMode(self: Pin<&mut ParamsBGVRNS>, multipartyMode0: MultipartyMode);
         fn SetExecutionMode(self: Pin<&mut ParamsBGVRNS>, executionMode0: ExecutionMode);
-        fn SetDecryptionNoiseMode(self: Pin<&mut ParamsBGVRNS>, decryptionNoiseMode0: DecryptionNoiseMode);
+        fn SetDecryptionNoiseMode(self: Pin<&mut ParamsBGVRNS>,
+                                  decryptionNoiseMode0: DecryptionNoiseMode);
         fn SetNoiseEstimate(self: Pin<&mut ParamsBGVRNS>, noiseEstimate0: f64);
         fn SetDesiredPrecision(self: Pin<&mut ParamsBGVRNS>, desiredPrecision0: f64);
         fn SetStatisticalSecurity(self: Pin<&mut ParamsBGVRNS>, statisticalSecurity0: u32);
@@ -342,21 +360,25 @@ mod ffi
         fn SetRingDim(self: Pin<&mut ParamsBGVRNS>, ringDim0: u32);
         fn SetEvalAddCount(self: Pin<&mut ParamsBGVRNS>, evalAddCount0: u32);
         fn SetKeySwitchCount(self: Pin<&mut ParamsBGVRNS>, keySwitchCount0: u32);
-        fn SetEncryptionTechnique(self: Pin<&mut ParamsBGVRNS>, encryptionTechnique0: EncryptionTechnique);
-        fn SetMultiplicationTechnique(self: Pin<&mut ParamsBGVRNS>, multiplicationTechnique0: MultiplicationTechnique);
+        fn SetEncryptionTechnique(self: Pin<&mut ParamsBGVRNS>,
+                                  encryptionTechnique0: EncryptionTechnique);
+        fn SetMultiplicationTechnique(self: Pin<&mut ParamsBGVRNS>,
+                                      multiplicationTechnique0: MultiplicationTechnique);
         fn SetMultiHopModSize(self: Pin<&mut ParamsBGVRNS>, multiHopModSize0: u32);
-        fn SetInteractiveBootCompressionLevel(self: Pin<&mut ParamsBGVRNS>, interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
+        fn SetInteractiveBootCompressionLevel(self: Pin<&mut ParamsBGVRNS>,
+                                              interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
     }
 
     // ParamsCKKSRNS
     unsafe extern "C++"
     {
         fn GetParamsCKKSRNS() -> UniquePtr<ParamsCKKSRNS>;
-        fn GetParamsCKKSRNSbyVectorOfString(vals: &CxxVector<CxxString>) -> UniquePtr<ParamsCKKSRNS>;
+        fn GetParamsCKKSRNSbyVectorOfString(vals: &CxxVector<CxxString>)
+                                            -> UniquePtr<ParamsCKKSRNS>;
         // getters
         fn GetScheme(self: &ParamsCKKSRNS) -> SCHEME;
-        fn GetPlaintextModulus(self: &ParamsCKKSRNS) -> u64; // PlaintextModulus
-        fn GetDigitSize(self: &ParamsCKKSRNS) -> u32; // usint
+        fn GetPlaintextModulus(self: &ParamsCKKSRNS) -> u64;
+        fn GetDigitSize(self: &ParamsCKKSRNS) -> u32;
         fn GetStandardDeviation(self: &ParamsCKKSRNS) -> f32;
         fn GetSecretKeyDist(self: &ParamsCKKSRNS) -> SecretKeyDist;
         fn GetMaxRelinSkDeg(self: &ParamsCKKSRNS) -> u32;
@@ -385,7 +407,7 @@ mod ffi
         fn GetMultiHopModSize(self: &ParamsCKKSRNS) -> u32;
         fn GetInteractiveBootCompressionLevel(self: &ParamsCKKSRNS) -> COMPRESSION_LEVEL;
         // setters
-        fn SetPlaintextModulus(self: Pin<&mut ParamsCKKSRNS>, ptModulus0: u64); // PlaintextModulus
+        fn SetPlaintextModulus(self: Pin<&mut ParamsCKKSRNS>, ptModulus0: u64);
         fn SetDigitSize(self: Pin<&mut ParamsCKKSRNS>, digitSize0: u32);
         fn SetStandardDeviation(self: Pin<&mut ParamsCKKSRNS>, standardDeviation0: f32);
         fn SetSecretKeyDist(self: Pin<&mut ParamsCKKSRNS>, secretKeyDist0: SecretKeyDist);
@@ -393,7 +415,8 @@ mod ffi
         fn SetPREMode(self: Pin<&mut ParamsCKKSRNS>, PREMode0: ProxyReEncryptionMode);
         fn SetMultipartyMode(self: Pin<&mut ParamsCKKSRNS>, multipartyMode0: MultipartyMode);
         fn SetExecutionMode(self: Pin<&mut ParamsCKKSRNS>, executionMode0: ExecutionMode);
-        fn SetDecryptionNoiseMode(self: Pin<&mut ParamsCKKSRNS>, decryptionNoiseMode0: DecryptionNoiseMode);
+        fn SetDecryptionNoiseMode(self: Pin<&mut ParamsCKKSRNS>,
+                                  decryptionNoiseMode0: DecryptionNoiseMode);
         fn SetNoiseEstimate(self: Pin<&mut ParamsCKKSRNS>, noiseEstimate0: f64);
         fn SetDesiredPrecision(self: Pin<&mut ParamsCKKSRNS>, desiredPrecision0: f64);
         fn SetStatisticalSecurity(self: Pin<&mut ParamsCKKSRNS>, statisticalSecurity0: u32);
@@ -410,10 +433,19 @@ mod ffi
         fn SetRingDim(self: Pin<&mut ParamsCKKSRNS>, ringDim0: u32);
         fn SetEvalAddCount(self: Pin<&mut ParamsCKKSRNS>, evalAddCount0: u32);
         fn SetKeySwitchCount(self: Pin<&mut ParamsCKKSRNS>, keySwitchCount0: u32);
-        fn SetEncryptionTechnique(self: Pin<&mut ParamsCKKSRNS>, encryptionTechnique0: EncryptionTechnique);
-        fn SetMultiplicationTechnique(self: Pin<&mut ParamsCKKSRNS>, multiplicationTechnique0: MultiplicationTechnique);
+        fn SetEncryptionTechnique(self: Pin<&mut ParamsCKKSRNS>,
+                                  encryptionTechnique0: EncryptionTechnique);
+        fn SetMultiplicationTechnique(self: Pin<&mut ParamsCKKSRNS>,
+                                      multiplicationTechnique0: MultiplicationTechnique);
         fn SetMultiHopModSize(self: Pin<&mut ParamsCKKSRNS>, multiHopModSize0: u32);
-        fn SetInteractiveBootCompressionLevel(self: Pin<&mut ParamsCKKSRNS>, interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
+        fn SetInteractiveBootCompressionLevel(self: Pin<&mut ParamsCKKSRNS>,
+                                              interactiveBootCompressionLevel0: COMPRESSION_LEVEL);
+    }
+
+    // PublicKeyDCRTPoly
+    unsafe extern "C++"
+    {
+        fn GenDefaultConstructedPublicKey() -> UniquePtr<PublicKeyDCRTPoly>;
     }
 
     // KeyPairDCRTPoly
@@ -437,6 +469,7 @@ mod ffi
     unsafe extern "C++"
     {
         fn GetCipherText(self: &CiphertextDCRTPoly) -> SharedPtr<CiphertextImpl>;
+        fn GenDefaultConstructedCiphertext() -> UniquePtr<CiphertextDCRTPoly>;
     }
 
     // ComplexPair
@@ -445,360 +478,229 @@ mod ffi
         re: f64,
         im: f64,
     }
-
-    // VectorOfComplexNumbers
+    // SharedComplex
+    struct SharedComplex
+    {
+        ptr: SharedPtr<Complex>,
+    }
+    // Vector of SharedComplex
     unsafe extern "C++"
     {
-        type VectorOfComplexNumbers;
-        fn GenVectorOfComplexNumbers(vals: &CxxVector<ComplexPair>) -> UniquePtr<VectorOfComplexNumbers>;
+        fn GenVectorOfComplex(vals: &CxxVector<ComplexPair>)
+                              -> UniquePtr<CxxVector<SharedComplex>>;
     }
 
     // CryptoContextDCRTPoly
     unsafe extern "C++"
     {
-        fn GenCryptoContextByParamsBFVRNS(params: &ParamsBFVRNS) -> UniquePtr<CryptoContextDCRTPoly>;
-        fn GenCryptoContextByParamsBGVRNS(params: &ParamsBGVRNS) -> UniquePtr<CryptoContextDCRTPoly>;
-        fn GenCryptoContextByParamsCKKSRNS(params: &ParamsCKKSRNS) -> UniquePtr<CryptoContextDCRTPoly>;
+        fn GenEmptyCryptoContext() -> UniquePtr<CryptoContextDCRTPoly>;
+        fn GenCryptoContextByParamsBFVRNS(params: &ParamsBFVRNS)
+                                          -> UniquePtr<CryptoContextDCRTPoly>;
+        fn GenCryptoContextByParamsBGVRNS(params: &ParamsBGVRNS)
+                                          -> UniquePtr<CryptoContextDCRTPoly>;
+        fn GenCryptoContextByParamsCKKSRNS(params: &ParamsCKKSRNS)
+                                           -> UniquePtr<CryptoContextDCRTPoly>;
 
         fn Enable(self: &CryptoContextDCRTPoly, feature: PKESchemeFeature);
         fn KeyGen(self: &CryptoContextDCRTPoly) -> UniquePtr<KeyPairDCRTPoly>;
         fn EvalMultKeyGen(self: &CryptoContextDCRTPoly, key: SharedPtr<PrivateKeyImpl>);
-        fn EvalRotateKeyGen(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>, indexList: &CxxVector<i32>, publicKey: SharedPtr<PublicKeyImpl>);
-        fn MakePackedPlaintext(self: &CryptoContextDCRTPoly, value: &CxxVector<i64>, noiseScaleDeg: usize, level: u32) -> UniquePtr<Plaintext>; // noiseScaleDeg = 1, level = 0
-        fn Encrypt(self: &CryptoContextDCRTPoly, publicKey: SharedPtr<PublicKeyImpl>, plaintext: SharedPtr<PlaintextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
-        fn EvalAdd(self: &CryptoContextDCRTPoly, ciphertext1: SharedPtr<CiphertextImpl>, ciphertext2: SharedPtr<CiphertextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
-        fn EvalSub(self: &CryptoContextDCRTPoly, ciphertext1: SharedPtr<CiphertextImpl>, ciphertext2: SharedPtr<CiphertextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
-        fn EvalMult(self: &CryptoContextDCRTPoly, ciphertext1: SharedPtr<CiphertextImpl>, ciphertext2: SharedPtr<CiphertextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
-        fn EvalMultByConst(self: &CryptoContextDCRTPoly, ciphertext: SharedPtr<CiphertextImpl>, constant: f64) -> UniquePtr<CiphertextDCRTPoly>;
-        fn EvalRotate(self: &CryptoContextDCRTPoly, ciphertext: SharedPtr<CiphertextImpl>, index: i32) -> UniquePtr<CiphertextDCRTPoly>;
-        fn Decrypt(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>, ciphertext: SharedPtr<CiphertextImpl>,
-                   plaintext: Pin<&mut Plaintext>) -> UniquePtr<DecryptResult>;
+        fn EvalRotateKeyGen(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+                            indexList: &CxxVector<i32>, publicKey: SharedPtr<PublicKeyImpl>);
+        fn MakePackedPlaintext(self: &CryptoContextDCRTPoly, value: &CxxVector<i64>,
+                               noiseScaleDeg: /* 1 */ usize, level: /* 0 */ u32)
+                               -> UniquePtr<Plaintext>;
+        fn Encrypt(self: &CryptoContextDCRTPoly, publicKey: SharedPtr<PublicKeyImpl>,
+                   plaintext: SharedPtr<PlaintextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
+        fn EvalAdd(self: &CryptoContextDCRTPoly, ciphertext1: SharedPtr<CiphertextImpl>,
+                   ciphertext2: SharedPtr<CiphertextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
+        fn EvalSub(self: &CryptoContextDCRTPoly, ciphertext1: SharedPtr<CiphertextImpl>,
+                   ciphertext2: SharedPtr<CiphertextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
+        fn EvalMult(self: &CryptoContextDCRTPoly, ciphertext1: SharedPtr<CiphertextImpl>,
+                    ciphertext2: SharedPtr<CiphertextImpl>) -> UniquePtr<CiphertextDCRTPoly>;
+        fn EvalMultByConst(self: &CryptoContextDCRTPoly, ciphertext: SharedPtr<CiphertextImpl>,
+                           constant: f64) -> UniquePtr<CiphertextDCRTPoly>;
+        fn EvalRotate(self: &CryptoContextDCRTPoly, ciphertext: SharedPtr<CiphertextImpl>,
+                      index: i32) -> UniquePtr<CiphertextDCRTPoly>;
+        fn EvalChebyshevSeries(self: &CryptoContextDCRTPoly, ciphertext: SharedPtr<CiphertextImpl>,
+                               coefficients: &CxxVector<f64>, a: f64, b: f64)
+                               -> UniquePtr<CiphertextDCRTPoly>;
+        fn Decrypt(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+                   ciphertext: SharedPtr<CiphertextImpl>, plaintext: Pin<&mut Plaintext>)
+                   -> UniquePtr<DecryptResult>;
         fn GetRingDimension(self: &CryptoContextDCRTPoly) -> u32;
-        fn MakeCKKSPackedPlaintext(self: &CryptoContextDCRTPoly, value: &CxxVector<f64>, scaleDeg: usize, level: u32,
-                                   params: SharedPtr<DCRTPolyParams>, slots: u32) -> UniquePtr<Plaintext>; // scaleDeg = 1, level = 0, params = nullptr, slots = 0
-        fn MakeCKKSPackedPlaintextByVectorOfComplexNumbers(self: &CryptoContextDCRTPoly, value: &VectorOfComplexNumbers, scaleDeg: usize, level: u32,
-                                   params: SharedPtr<DCRTPolyParams>, slots: u32) -> UniquePtr<Plaintext>; // scaleDeg = 1, level = 0, params = nullptr, slots = 0
-        fn EvalPoly(self: &CryptoContextDCRTPoly, ciphertext: SharedPtr<CiphertextImpl>, coefficients: &CxxVector<f64>) -> UniquePtr<CiphertextDCRTPoly>;
+        fn MakeCKKSPackedPlaintext(self: &CryptoContextDCRTPoly, value: &CxxVector<f64>,
+                                   scaleDeg: /* 1 */ usize, level: /* 0 */ u32,
+                                   params: /* null() */ SharedPtr<DCRTPolyParams>,
+                                   slots: /* 0 */ u32) -> UniquePtr<Plaintext>;
+        fn MakeCKKSPackedPlaintextByVectorOfComplex(self: &CryptoContextDCRTPoly,
+                                                    value: &CxxVector<SharedComplex>,
+                                                    scaleDeg: /* 1 */ usize, level: /* 0 */ u32,
+                                                    params: /* null() */ SharedPtr<DCRTPolyParams>,
+                                                    slots: /* 0 */ u32) -> UniquePtr<Plaintext>;
+        fn EvalPoly(self: &CryptoContextDCRTPoly, ciphertext: SharedPtr<CiphertextImpl>,
+                    coefficients: &CxxVector<f64>) -> UniquePtr<CiphertextDCRTPoly>;
     }
-}
 
-fn PolynomialEvaluationExample()
-{
-    println!("\n======EXAMPLE FOR EVALPOLY========\n");
-
-    let mut _cc_params_ckksrns = ffi::GetParamsCKKSRNS();
-    _cc_params_ckksrns.pin_mut().SetMultiplicativeDepth(6);
-    _cc_params_ckksrns.pin_mut().SetScalingModSize(50);
-
-    let mut _cc = ffi::GenCryptoContextByParamsCKKSRNS(&_cc_params_ckksrns);
-    _cc.Enable(ffi::PKESchemeFeature::PKE);
-    _cc.Enable(ffi::PKESchemeFeature::KEYSWITCH);
-    _cc.Enable(ffi::PKESchemeFeature::LEVELEDSHE);
-    _cc.Enable(ffi::PKESchemeFeature::ADVANCEDSHE);
-
-    let mut _vals = CxxVector::<ffi::ComplexPair>::new();
-    _vals.pin_mut().push(ffi::ComplexPair{re: 0.5, im: 0.0});
-    _vals.pin_mut().push(ffi::ComplexPair{re: 0.7, im: 0.0});
-    _vals.pin_mut().push(ffi::ComplexPair{re: 0.9, im: 0.0});
-    _vals.pin_mut().push(ffi::ComplexPair{re: 0.95, im: 0.0});
-    _vals.pin_mut().push(ffi::ComplexPair{re: 0.93, im: 0.0});
-    let _input = ffi::GenVectorOfComplexNumbers(&_vals);
-    let _encoded_length = _vals.len(); // no len() funtion implemented for _input
-
-    let mut _coefficients_1 = CxxVector::<f64>::new();
-    _coefficients_1.pin_mut().push(0.15);
-    _coefficients_1.pin_mut().push(0.75);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(1.25);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(1.0);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(1.0);
-    _coefficients_1.pin_mut().push(2.0);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(1.0);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(0.0);
-    _coefficients_1.pin_mut().push(1.0);
-
-    let mut _coefficients_2 = CxxVector::<f64>::new();
-    _coefficients_2.pin_mut().push(1.0);
-    _coefficients_2.pin_mut().push(2.0);
-    _coefficients_2.pin_mut().push(3.0);
-    _coefficients_2.pin_mut().push(4.0);
-    _coefficients_2.pin_mut().push(5.0);
-    _coefficients_2.pin_mut().push(-1.0);
-    _coefficients_2.pin_mut().push(-2.0);
-    _coefficients_2.pin_mut().push(-3.0);
-    _coefficients_2.pin_mut().push(-4.0);
-    _coefficients_2.pin_mut().push(-5.0);
-    _coefficients_2.pin_mut().push(0.1);
-    _coefficients_2.pin_mut().push(0.2);
-    _coefficients_2.pin_mut().push(0.3);
-    _coefficients_2.pin_mut().push(0.4);
-    _coefficients_2.pin_mut().push(0.5);
-    _coefficients_2.pin_mut().push(-0.1);
-    _coefficients_2.pin_mut().push(-0.2);
-    _coefficients_2.pin_mut().push(-0.3);
-    _coefficients_2.pin_mut().push(-0.4);
-    _coefficients_2.pin_mut().push(-0.5);
-    _coefficients_2.pin_mut().push(0.1);
-    _coefficients_2.pin_mut().push(0.2);
-    _coefficients_2.pin_mut().push(0.3);
-    _coefficients_2.pin_mut().push(0.4);
-    _coefficients_2.pin_mut().push(0.5);
-    _coefficients_2.pin_mut().push(-0.1);
-    _coefficients_2.pin_mut().push(-0.2);
-    _coefficients_2.pin_mut().push(-0.3);
-    _coefficients_2.pin_mut().push(-0.4);
-    _coefficients_2.pin_mut().push(-0.5);
-
-    let mut _plain_text_1 = _cc.MakeCKKSPackedPlaintextByVectorOfComplexNumbers(&_input, 1, 0, SharedPtr::<ffi::DCRTPolyParams>::null(), 0);
-    let mut _key_pair = _cc.KeyGen();
-    print!("Generating evaluation key for homomorphic multiplication...");
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
-    println!("Completed.\n");
-    let mut _cipher_text_1 = _cc.Encrypt(_key_pair.GetPublicKey(), _plain_text_1.GetPlainText());
-
-    let mut _start = Instant::now();
-    let mut _result = _cc.EvalPoly(_cipher_text_1.GetCipherText(), &_coefficients_1);
-    let _time_eval_poly_1 = _start.elapsed();
-
-    _start = Instant::now();
-    let mut _result_2 = _cc.EvalPoly(_cipher_text_1.GetCipherText(), &_coefficients_2);
-    let _time_eval_poly_2 = _start.elapsed();
-
-    let mut _plain_text_dec = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _result.GetCipherText(), _plain_text_dec.pin_mut());
-    _plain_text_dec.SetLength(_encoded_length);
-    let mut _plain_text_dec_2 = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _result_2.GetCipherText(), _plain_text_dec_2.pin_mut());
-    _plain_text_dec_2.SetLength(_encoded_length);
-
-    println!("\n Original Plaintext #1:");
-    println!("{}", _plain_text_1.GetString());
-    println!("\n Result of evaluating a polynomial with coefficients [{} ]", _coefficients_1.iter().fold(String::new(), |acc, &arg| acc + " " + &arg.to_string()));
-    println!("{}", _plain_text_dec.GetString());
-    println!("\n Expected result: (0.70519107, 1.38285078, 3.97211180, 5.60215665, 4.86357575)");
-    println!("\n Evaluation time: {:.0?}", _time_eval_poly_1);
-    println!("\n Result of evaluating a polynomial with coefficients [{} ]", _coefficients_2.iter().fold(String::new(), |acc, &arg| acc + " " + &arg.to_string()));
-    println!("{}\n", _plain_text_dec_2.GetString());
-    println!(" Expected result: (3.4515092326, 5.3752765397, 4.8993108833, 3.2495023573, 4.0485229982)");
-    print!("\n Evaluation time: {:.0?}\n", _time_eval_poly_2);
-}
-
-fn SimpleRealNumbersExample()
-{
-    let _mult_depth: u32 = 1;
-    let _scale_mod_size: u32 = 50;
-    let _batch_size: u32 = 8;
-
-    let mut _cc_params_ckksrns = ffi::GetParamsCKKSRNS();
-    _cc_params_ckksrns.pin_mut().SetMultiplicativeDepth(_mult_depth);
-    _cc_params_ckksrns.pin_mut().SetScalingModSize(_scale_mod_size);
-    _cc_params_ckksrns.pin_mut().SetBatchSize(_batch_size);
-
-    let mut _cc = ffi::GenCryptoContextByParamsCKKSRNS(&_cc_params_ckksrns);
-    _cc.Enable(ffi::PKESchemeFeature::PKE);
-    _cc.Enable(ffi::PKESchemeFeature::KEYSWITCH);
-    _cc.Enable(ffi::PKESchemeFeature::LEVELEDSHE);
-
-    println!("CKKS scheme is using ring dimension {}\n", _cc.GetRingDimension());
-
-    let mut _key_pair = _cc.KeyGen();
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
-    let mut _index_list = CxxVector::<i32>::new();
-    _index_list.pin_mut().push(1);
-    _index_list.pin_mut().push(-2);
-    _cc.EvalRotateKeyGen(_key_pair.GetPrivateKey(), &_index_list, SharedPtr::<ffi::PublicKeyImpl>::null());
-
-    let mut _x_1 = CxxVector::<f64>::new();
-    _x_1.pin_mut().push(0.25);
-    _x_1.pin_mut().push(0.5);
-    _x_1.pin_mut().push(0.75);
-    _x_1.pin_mut().push(1.0);
-    _x_1.pin_mut().push(2.0);
-    _x_1.pin_mut().push(3.0);
-    _x_1.pin_mut().push(4.0);
-    _x_1.pin_mut().push(5.0);
-
-    let mut _x_2 = CxxVector::<f64>::new();
-    _x_2.pin_mut().push(5.0);
-    _x_2.pin_mut().push(4.0);
-    _x_2.pin_mut().push(3.0);
-    _x_2.pin_mut().push(2.0);
-    _x_2.pin_mut().push(1.0);
-    _x_2.pin_mut().push(0.75);
-    _x_2.pin_mut().push(0.5);
-    _x_2.pin_mut().push(0.25);
-
-    let mut _p_txt_1 = _cc.MakeCKKSPackedPlaintext(&_x_1, 1, 0, SharedPtr::<ffi::DCRTPolyParams>::null(), 0);
-    let mut _p_txt_2 = _cc.MakeCKKSPackedPlaintext(&_x_2, 1, 0, SharedPtr::<ffi::DCRTPolyParams>::null(), 0);
-
-    println!("Input x1: {}", _p_txt_1.GetString());
-    println!("Input x2: {}", _p_txt_2.GetString());
-
-    let mut _c1 = _cc.Encrypt(_key_pair.GetPublicKey(), _p_txt_1.GetPlainText());
-    let mut _c2 = _cc.Encrypt(_key_pair.GetPublicKey(), _p_txt_2.GetPlainText());
-
-    let mut _c_add = _cc.EvalAdd(_c1.GetCipherText(), _c2.GetCipherText());
-    let mut _c_sub = _cc.EvalSub(_c1.GetCipherText(), _c2.GetCipherText());
-    let mut _c_scalar = _cc.EvalMultByConst(_c1.GetCipherText(), 4.0);
-    let mut _c_mul = _cc.EvalMult(_c1.GetCipherText(), _c2.GetCipherText());
-    let mut _c_rot_1 = _cc.EvalRotate(_c1.GetCipherText(), 1);
-    let mut _c_rot_2 = _cc.EvalRotate(_c1.GetCipherText(), -2);
-
-    let mut _result = ffi::GenEmptyPlainText();
-    println!("\nResults of homomorphic computations:");
-
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _c1.GetCipherText(), _result.pin_mut());
-    _result.SetLength(_batch_size.try_into().unwrap());
-    println!("x1 = {}Estimated precision in bits: {}", _result.GetString(), _result.GetLogPrecision());
-
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _c_add.GetCipherText(), _result.pin_mut());
-    _result.SetLength(_batch_size.try_into().unwrap());
-    println!("x1 + x2 = {}Estimated precision in bits: {}",_result.GetString(), _result.GetLogPrecision());
-
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _c_sub.GetCipherText(), _result.pin_mut());
-    _result.SetLength(_batch_size.try_into().unwrap());
-    println!("x1 - x2 = {}", _result.GetString());
-
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _c_scalar.GetCipherText(), _result.pin_mut());
-    _result.SetLength(_batch_size.try_into().unwrap());
-    println!("4 * x1 = {}", _result.GetString());
-
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _c_mul.GetCipherText(), _result.pin_mut());
-    _result.SetLength(_batch_size.try_into().unwrap());
-    println!("x1 * x2 = {}", _result.GetString());
-
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _c_rot_1.GetCipherText(), _result.pin_mut());
-    _result.SetLength(_batch_size.try_into().unwrap());
-    println!("\nIn rotations, very small outputs (~10^-10 here) correspond to 0's:");
-    println!("x1 rotate by 1 = {}", _result.GetString());
-
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _c_rot_2.GetCipherText(), _result.pin_mut());
-    _result.SetLength(_batch_size.try_into().unwrap());
-    println!("x1 rotate by -2 = {}", _result.GetString());
+    // Serialize / Deserialize
+    unsafe extern "C++"
+    {
+        fn SerializeCryptoContextToFile(ccLocation: &CxxString,
+                                        cryptoContext: &CryptoContextDCRTPoly,
+                                        serialMode: SerialMode) -> bool;
+        fn DeserializeCryptoContextFromFile(ccLocation: &CxxString,
+                                            cryptoContext: Pin<&mut CryptoContextDCRTPoly>,
+                                            serialMode: SerialMode) -> bool;
+        fn SerializeEvalMultKeyToFile(multKeyLocation: &CxxString,
+                                      cryptoContext: &CryptoContextDCRTPoly,
+                                      serialMode: SerialMode) -> bool;
+        fn SerializeEvalMultKeyByIdToFile(multKeyLocation: &CxxString, serialMode: SerialMode,
+                                          id: &CxxString) -> bool;
+        fn DeserializeEvalMultKeyFromFile(multKeyLocation: &CxxString, serialMode: SerialMode)
+                                          -> bool;
+        fn SerializeEvalSumKeyToFile(sumKeyLocation: &CxxString,
+                                     cryptoContext: &CryptoContextDCRTPoly, serialMode: SerialMode)
+                                     -> bool;
+        fn SerializeEvalSumKeyByIdToFile(sumKeyLocation: &CxxString, serialMode: SerialMode,
+                                         id: &CxxString) -> bool;
+        fn DeserializeEvalSumKeyFromFile(sumKeyLocation: &CxxString, serialMode: SerialMode)
+                                         -> bool;
+        fn SerializeEvalAutomorphismKeyToFile(automorphismKeyLocation: &CxxString,
+                                              cryptoContext: &CryptoContextDCRTPoly,
+                                              serialMode: SerialMode) -> bool;
+        fn SerializeEvalAutomorphismKeyByIdToFile(automorphismKeyLocation: &CxxString,
+                                                  serialMode: SerialMode, id: &CxxString) -> bool;
+        fn DeserializeEvalAutomorphismKeyFromFile(automorphismKeyLocation: &CxxString,
+                                                  serialMode: SerialMode) -> bool;
+        fn SerializeCiphertextToFile(ciphertextLocation: &CxxString,
+                                     ciphertext: &CiphertextDCRTPoly, serialMode: SerialMode)
+                                     -> bool;
+        fn DeserializeCiphertextFromFile(ciphertextLocation: &CxxString,
+                                         ciphertext: Pin<&mut CiphertextDCRTPoly>,
+                                         serialMode: SerialMode) -> bool;
+        fn SerializePublicKeyToFile(publicKeyLocation: &CxxString, publicKey: &PublicKeyDCRTPoly,
+                                    serialMode: SerialMode) -> bool;
+        fn DeserializePublicKeyFromFile(publicKeyLocation: &CxxString,
+                                        publicKey: Pin<&mut PublicKeyDCRTPoly>,
+                                        serialMode: SerialMode) -> bool;
+    }
 }
 
-fn SimpleIntegersExample()
+#[cfg(test)]
+mod tests
 {
-    let mut _cc_params_bfvrns = ffi::GetParamsBFVRNS();
-    _cc_params_bfvrns.pin_mut().SetPlaintextModulus(65537);
-    _cc_params_bfvrns.pin_mut().SetMultiplicativeDepth(2);
-
-    let mut _cc = ffi::GenCryptoContextByParamsBFVRNS(&_cc_params_bfvrns);
-    _cc.Enable(ffi::PKESchemeFeature::PKE);
-    _cc.Enable(ffi::PKESchemeFeature::KEYSWITCH);
-    _cc.Enable(ffi::PKESchemeFeature::LEVELEDSHE);
-    
-    let mut _key_pair = _cc.KeyGen();
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
-    
-    let mut _index_list = CxxVector::<i32>::new();
-    _index_list.pin_mut().push(1);
-    _index_list.pin_mut().push(2);
-    _index_list.pin_mut().push(-1);
-    _index_list.pin_mut().push(-2);    
-    _cc.EvalRotateKeyGen(_key_pair.GetPrivateKey(), &_index_list, SharedPtr::<ffi::PublicKeyImpl>::null());
-    
-    let mut _vector_of_ints_1 = CxxVector::<i64>::new();
-    _vector_of_ints_1.pin_mut().push(1);
-    _vector_of_ints_1.pin_mut().push(2);
-    _vector_of_ints_1.pin_mut().push(3);
-    _vector_of_ints_1.pin_mut().push(4);
-    _vector_of_ints_1.pin_mut().push(5);
-    _vector_of_ints_1.pin_mut().push(6);    
-    _vector_of_ints_1.pin_mut().push(7);
-    _vector_of_ints_1.pin_mut().push(8);
-    _vector_of_ints_1.pin_mut().push(9);
-    _vector_of_ints_1.pin_mut().push(10);
-    _vector_of_ints_1.pin_mut().push(11);
-    _vector_of_ints_1.pin_mut().push(12);    
-    let mut _plain_text_1 = _cc.MakePackedPlaintext(&_vector_of_ints_1, 1, 0);
-    
-    let mut _vector_of_ints_2 = CxxVector::<i64>::new();
-    _vector_of_ints_2.pin_mut().push(3);
-    _vector_of_ints_2.pin_mut().push(2);
-    _vector_of_ints_2.pin_mut().push(1);
-    _vector_of_ints_2.pin_mut().push(4);
-    _vector_of_ints_2.pin_mut().push(5);
-    _vector_of_ints_2.pin_mut().push(6);    
-    _vector_of_ints_2.pin_mut().push(7);
-    _vector_of_ints_2.pin_mut().push(8);
-    _vector_of_ints_2.pin_mut().push(9);
-    _vector_of_ints_2.pin_mut().push(10);
-    _vector_of_ints_2.pin_mut().push(11);
-    _vector_of_ints_2.pin_mut().push(12);    
-    let mut _plain_text_2 = _cc.MakePackedPlaintext(&_vector_of_ints_2, 1, 0); 
-    
-    let mut _vector_of_ints_3 = CxxVector::<i64>::new();
-    _vector_of_ints_3.pin_mut().push(1);
-    _vector_of_ints_3.pin_mut().push(2);
-    _vector_of_ints_3.pin_mut().push(5);
-    _vector_of_ints_3.pin_mut().push(2);
-    _vector_of_ints_3.pin_mut().push(5);
-    _vector_of_ints_3.pin_mut().push(6);    
-    _vector_of_ints_3.pin_mut().push(7);
-    _vector_of_ints_3.pin_mut().push(8);
-    _vector_of_ints_3.pin_mut().push(9);
-    _vector_of_ints_3.pin_mut().push(10);
-    _vector_of_ints_3.pin_mut().push(11);
-    _vector_of_ints_3.pin_mut().push(12);    
-    let mut _plain_text_3 = _cc.MakePackedPlaintext(&_vector_of_ints_3, 1, 0);
-
-    let mut _cipher_text_1 = _cc.Encrypt(_key_pair.GetPublicKey(), _plain_text_1.GetPlainText());
-    let mut _cipher_text_2 = _cc.Encrypt(_key_pair.GetPublicKey(), _plain_text_2.GetPlainText());
-    let mut _cipher_text_3 = _cc.Encrypt(_key_pair.GetPublicKey(), _plain_text_3.GetPlainText());    
-
-    let mut _cipher_text_add_1_2 = _cc.EvalAdd(_cipher_text_1.GetCipherText(), _cipher_text_2.GetCipherText());
-    let mut _cipher_text_add_result = _cc.EvalAdd(_cipher_text_add_1_2.GetCipherText(), _cipher_text_3.GetCipherText());
-
-    let mut _cipher_text_mul_1_2 = _cc.EvalMult(_cipher_text_1.GetCipherText(), _cipher_text_2.GetCipherText());
-    let mut _cipher_text_mult_result = _cc.EvalMult(_cipher_text_mul_1_2.GetCipherText(), _cipher_text_3.GetCipherText());
-    
-    let mut _cipher_text_rot_1 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), 1);
-    let mut _cipher_text_rot_2 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), 2);
-    let mut _cipher_text_rot_3 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), -1);
-    let mut _cipher_text_rot_4 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), -2);
-    
-    let mut _plain_text_add_result = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_add_result.GetCipherText(), _plain_text_add_result.pin_mut());
-    let mut _plain_text_mult_result = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_mult_result.GetCipherText(), _plain_text_mult_result.pin_mut());
-    let mut _plain_text_rot_1 = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_1.GetCipherText(), _plain_text_rot_1.pin_mut());
-    let mut _plain_text_rot_2 = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_2.GetCipherText(), _plain_text_rot_2.pin_mut()); 
-    let mut _plain_text_rot_3 = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_3.GetCipherText(), _plain_text_rot_3.pin_mut());     
-    let mut _plain_text_rot_4 = ffi::GenEmptyPlainText();
-    _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_4.GetCipherText(), _plain_text_rot_4.pin_mut());     
-
-    _plain_text_rot_1.SetLength(_vector_of_ints_1.len());
-    _plain_text_rot_2.SetLength(_vector_of_ints_1.len());
-    _plain_text_rot_3.SetLength(_vector_of_ints_1.len());
-    _plain_text_rot_4.SetLength(_vector_of_ints_1.len());
-
-    println!("Plaintext #1: {}", _plain_text_1.GetString());
-    println!("Plaintext #2: {}", _plain_text_2.GetString());
-    println!("Plaintext #3: {}", _plain_text_3.GetString());
-
-    println!("\nResults of homomorphic computations");
-    println!("#1 + #2 + #3: {}", _plain_text_add_result.GetString());
-    println!("#1 * #2 * #3: {}", _plain_text_mult_result.GetString());
-    println!("Left rotation of #1 by 1: {}", _plain_text_rot_1.GetString());
-    println!("Left rotation of #1 by 2: {}", _plain_text_rot_2.GetString());
-    println!("Right rotation of #1 by -1: {}", _plain_text_rot_3.GetString());
-    println!("Right rotation of #1 by -2: {}", _plain_text_rot_4.GetString());	
-}
+    use super::*;
 
-fn main()
-{
-    SimpleIntegersExample();
-    SimpleRealNumbersExample();
-    PolynomialEvaluationExample();
+    // TODO: add more tests
+    #[test]
+    fn SimpleIntegersExample()
+    {
+        let mut _cc_params_bfvrns = ffi::GetParamsBFVRNS();
+        _cc_params_bfvrns.pin_mut().SetPlaintextModulus(65537);
+        _cc_params_bfvrns.pin_mut().SetMultiplicativeDepth(2);
+
+        let mut _cc = ffi::GenCryptoContextByParamsBFVRNS(&_cc_params_bfvrns);
+        _cc.Enable(ffi::PKESchemeFeature::PKE);
+        _cc.Enable(ffi::PKESchemeFeature::KEYSWITCH);
+        _cc.Enable(ffi::PKESchemeFeature::LEVELEDSHE);
+
+        let mut _key_pair = _cc.KeyGen();
+        _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+
+        let mut _index_list = CxxVector::<i32>::new();
+        _index_list.pin_mut().push(1);
+        _index_list.pin_mut().push(2);
+        _index_list.pin_mut().push(-1);
+        _index_list.pin_mut().push(-2);
+        _cc.EvalRotateKeyGen(_key_pair.GetPrivateKey(), &_index_list, SharedPtr::<ffi::PublicKeyImpl>::null());
+
+        let mut _vector_of_ints_1 = CxxVector::<i64>::new();
+        _vector_of_ints_1.pin_mut().push(1);
+        _vector_of_ints_1.pin_mut().push(2);
+        _vector_of_ints_1.pin_mut().push(3);
+        _vector_of_ints_1.pin_mut().push(4);
+        _vector_of_ints_1.pin_mut().push(5);
+        _vector_of_ints_1.pin_mut().push(6);
+        _vector_of_ints_1.pin_mut().push(7);
+        _vector_of_ints_1.pin_mut().push(8);
+        _vector_of_ints_1.pin_mut().push(9);
+        _vector_of_ints_1.pin_mut().push(10);
+        _vector_of_ints_1.pin_mut().push(11);
+        _vector_of_ints_1.pin_mut().push(12);
+        let mut _plain_text_1 = _cc.MakePackedPlaintext(&_vector_of_ints_1, 1, 0);
+
+        let mut _vector_of_ints_2 = CxxVector::<i64>::new();
+        _vector_of_ints_2.pin_mut().push(3);
+        _vector_of_ints_2.pin_mut().push(2);
+        _vector_of_ints_2.pin_mut().push(1);
+        _vector_of_ints_2.pin_mut().push(4);
+        _vector_of_ints_2.pin_mut().push(5);
+        _vector_of_ints_2.pin_mut().push(6);
+        _vector_of_ints_2.pin_mut().push(7);
+        _vector_of_ints_2.pin_mut().push(8);
+        _vector_of_ints_2.pin_mut().push(9);
+        _vector_of_ints_2.pin_mut().push(10);
+        _vector_of_ints_2.pin_mut().push(11);
+        _vector_of_ints_2.pin_mut().push(12);
+        let mut _plain_text_2 = _cc.MakePackedPlaintext(&_vector_of_ints_2, 1, 0);
+
+        let mut _vector_of_ints_3 = CxxVector::<i64>::new();
+        _vector_of_ints_3.pin_mut().push(1);
+        _vector_of_ints_3.pin_mut().push(2);
+        _vector_of_ints_3.pin_mut().push(5);
+        _vector_of_ints_3.pin_mut().push(2);
+        _vector_of_ints_3.pin_mut().push(5);
+        _vector_of_ints_3.pin_mut().push(6);
+        _vector_of_ints_3.pin_mut().push(7);
+        _vector_of_ints_3.pin_mut().push(8);
+        _vector_of_ints_3.pin_mut().push(9);
+        _vector_of_ints_3.pin_mut().push(10);
+        _vector_of_ints_3.pin_mut().push(11);
+        _vector_of_ints_3.pin_mut().push(12);
+        let mut _plain_text_3 = _cc.MakePackedPlaintext(&_vector_of_ints_3, 1, 0);
+
+        let mut _cipher_text_1 = _cc.Encrypt(_key_pair.GetPublicKey(), _plain_text_1.GetPlainText());
+        let mut _cipher_text_2 = _cc.Encrypt(_key_pair.GetPublicKey(), _plain_text_2.GetPlainText());
+        let mut _cipher_text_3 = _cc.Encrypt(_key_pair.GetPublicKey(), _plain_text_3.GetPlainText());
+
+        let mut _cipher_text_add_1_2 = _cc.EvalAdd(_cipher_text_1.GetCipherText(), _cipher_text_2.GetCipherText());
+        let mut _cipher_text_add_result = _cc.EvalAdd(_cipher_text_add_1_2.GetCipherText(), _cipher_text_3.GetCipherText());
+
+        let mut _cipher_text_mul_1_2 = _cc.EvalMult(_cipher_text_1.GetCipherText(), _cipher_text_2.GetCipherText());
+        let mut _cipher_text_mult_result = _cc.EvalMult(_cipher_text_mul_1_2.GetCipherText(), _cipher_text_3.GetCipherText());
+
+        let mut _cipher_text_rot_1 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), 1);
+        let mut _cipher_text_rot_2 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), 2);
+        let mut _cipher_text_rot_3 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), -1);
+        let mut _cipher_text_rot_4 = _cc.EvalRotate(_cipher_text_1.GetCipherText(), -2);
+
+        let mut _plain_text_add_result = ffi::GenEmptyPlainText();
+        _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_add_result.GetCipherText(), _plain_text_add_result.pin_mut());
+        let mut _plain_text_mult_result = ffi::GenEmptyPlainText();
+        _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_mult_result.GetCipherText(), _plain_text_mult_result.pin_mut());
+        let mut _plain_text_rot_1 = ffi::GenEmptyPlainText();
+        _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_1.GetCipherText(), _plain_text_rot_1.pin_mut());
+        let mut _plain_text_rot_2 = ffi::GenEmptyPlainText();
+        _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_2.GetCipherText(), _plain_text_rot_2.pin_mut());
+        let mut _plain_text_rot_3 = ffi::GenEmptyPlainText();
+        _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_3.GetCipherText(), _plain_text_rot_3.pin_mut());
+        let mut _plain_text_rot_4 = ffi::GenEmptyPlainText();
+        _cc.Decrypt(_key_pair.GetPrivateKey(), _cipher_text_rot_4.GetCipherText(), _plain_text_rot_4.pin_mut());
+
+        _plain_text_rot_1.SetLength(_vector_of_ints_1.len());
+        _plain_text_rot_2.SetLength(_vector_of_ints_1.len());
+        _plain_text_rot_3.SetLength(_vector_of_ints_1.len());
+        _plain_text_rot_4.SetLength(_vector_of_ints_1.len());
+
+        println!("Plaintext #1: {}", _plain_text_1.GetString());
+        println!("Plaintext #2: {}", _plain_text_2.GetString());
+        println!("Plaintext #3: {}", _plain_text_3.GetString());
+
+        println!("\nResults of homomorphic computations");
+        println!("#1 + #2 + #3: {}", _plain_text_add_result.GetString());
+        println!("#1 * #2 * #3: {}", _plain_text_mult_result.GetString());
+        println!("Left rotation of #1 by 1: {}", _plain_text_rot_1.GetString());
+        println!("Left rotation of #1 by 2: {}", _plain_text_rot_2.GetString());
+        println!("Right rotation of #1 by -1: {}", _plain_text_rot_3.GetString());
+        println!("Right rotation of #1 by -2: {}", _plain_text_rot_4.GetString());
+    }
 }