Просмотр исходного кода

Merge pull request #223 from openfheorg/dev

Update to v1.3.0.0
yspolyakov 9 месяцев назад
Родитель
Сommit
e69343d49f

+ 4 - 4
.github/workflows/manual.yml

@@ -14,7 +14,7 @@ on:
         description: 'Compiler type'
         type: string
         required: true
-        default: 'GLANG-14'
+        default: 'GLANG-18'
       native_backend:
         description: 'Size of NativeInteger'
         type: string
@@ -34,10 +34,10 @@ on:
         description: 'Compiler type'
         type: choice
         options:
-        - 'GCC-12'
-        - 'CLANG-14'
+        - 'GCC-14'
+        - 'CLANG-18'
         required: true
-        default: 'GLANG-14'
+        default: 'GLANG-18'
       native_backend:
         description: 'Size of NativeInteger'
         type: choice

+ 6 - 5
CMakeLists.txt

@@ -2,10 +2,11 @@ cmake_minimum_required (VERSION 3.5.1)
 
 project (OpenFHE-Python)
 
-set(OPENFHE_PYTHON_VERSION_MAJOR 0)
-set(OPENFHE_PYTHON_VERSION_MINOR 8)
-set(OPENFHE_PYTHON_VERSION_PATCH 10)
-set(OPENFHE_PYTHON_VERSION ${OPENFHE_PYTHON_VERSION_MAJOR}.${OPENFHE_PYTHON_VERSION_MINOR}.${OPENFHE_PYTHON_VERSION_PATCH})
+set(OPENFHE_PYTHON_VERSION_MAJOR 1)
+set(OPENFHE_PYTHON_VERSION_MINOR 3)
+set(OPENFHE_PYTHON_VERSION_PATCH 0)
+set(OPENFHE_PYTHON_VERSION_TWEAK 0)
+set(OPENFHE_PYTHON_VERSION ${OPENFHE_PYTHON_VERSION_MAJOR}.${OPENFHE_PYTHON_VERSION_MINOR}.${OPENFHE_PYTHON_VERSION_PATCH}.${OPENFHE_PYTHON_VERSION_TWEAK})
 
 set(CMAKE_CXX_STANDARD 17)
 option( BUILD_STATIC "Set to ON to include static versions of the library" OFF)
@@ -14,7 +15,7 @@ if(APPLE)
     set(CMAKE_CXX_VISIBILITY_PRESET default)
 endif()
 
-find_package(OpenFHE 1.2.2 REQUIRED)
+find_package(OpenFHE 1.3.0 REQUIRED)
 find_package(pybind11 REQUIRED)
 
 # "CMAKE_INTERPROCEDURAL_OPTIMIZATION ON" (ON is the default value) causes link failure. see

+ 1 - 1
README.md

@@ -35,7 +35,7 @@ Please see [Instructions for the Docker setup](docker/README.md)
 
 Before building, make sure you have the following dependencies installed:
 
-- [OpenFHE 1.1.3+](https://github.com/openfheorg/openfhe-development) by following the instructions in [OpenFHE Documentation](https://openfhe-development.readthedocs.io/en/latest/sphinx_rsts/intro/installation/installation.html)
+- [OpenFHE 1.3.0+](https://github.com/openfheorg/openfhe-development) by following the instructions in [OpenFHE Documentation](https://openfhe-development.readthedocs.io/en/latest/sphinx_rsts/intro/installation/installation.html)
 - [Python 3.6+](https://www.python.org/)
 - [pybind11](https://pybind11.readthedocs.io/en/stable/installing.html)
 

+ 1 - 1
examples/pke/advanced-real-numbers-128.py

@@ -383,7 +383,7 @@ def main():
         fast_rotation_demo1()
         fast_rotation_demo2()
     else:
-        print("This demo only runs for 128-bit CKKS.\nIf you want to test it please reinstall the OpenFHE C++ with the flag -DNATIVE_INT=128, then reinstall OpenFHE-Python.")
+        print("This demo only runs for 128-bit CKKS.\nIf you want to test it please reinstall the OpenFHE C++ with the flag -DNATIVE_SIZE=128, then reinstall OpenFHE-Python.")
 
 if __name__ == "__main__":
     main()

+ 15 - 11
src/include/bindings.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef OPENFHE_BINDINGS_H
-#define OPENFHE_BINDINGS_H
+//==================================================================================
+#ifndef __BINDINGS_H__
+#define __BINDINGS_H__
 
 #include <pybind11/pybind11.h>
 
@@ -39,4 +42,5 @@ void bind_ciphertext(pybind11::module &m);
 void bind_serialization(pybind11::module &m);
 void bind_schemes(pybind11::module &m);
 void bind_sch_swch_params(pybind11::module &m);
-#endif // OPENFHE_BINDINGS_H
+
+#endif // __BINDINGS_H__

+ 15 - 11
src/include/binfhe/binfhecontext_wrapper.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef BINFHE_CRYPTOCONTEXT_BINDINGS_H
-#define BINFHE_CRYPTOCONTEXT_BINDINGS_H
+//==================================================================================
+#ifndef __BINFHECONTEXT_WRAPPER_H__
+#define __BINFHECONTEXT_WRAPPER_H__
 
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
@@ -66,4 +69,5 @@ NativeInteger StaticFunction(NativeInteger m, NativeInteger p);
 // extern py::function static_f;
 
 LWECiphertext EvalFuncWrapper(BinFHEContext &self, ConstLWECiphertext &ct, const std::vector<uint64_t> &LUT);
-#endif // BINFHE_CRYPTOCONTEXT_BINDINGS_H
+
+#endif // __BINFHECONTEXT_WRAPPER_H__

+ 14 - 11
src/include/binfhe_bindings.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef BINFHE_BINDINGS_H
-#define BINFHE_BINDINGS_H
+//==================================================================================
+#ifndef __BINFHE_BINDINGS_H__
+#define __BINFHE_BINDINGS_H__
 
 #include <pybind11/pybind11.h>
 
@@ -34,4 +37,4 @@ void bind_binfhe_enums(pybind11::module &m);
 void bind_binfhe_context(pybind11::module &m);
 void bind_binfhe_keys(pybind11::module &m);
 void bind_binfhe_ciphertext(pybind11::module &m);
-#endif // BINFHE_BINDINGS_H
+#endif // __BINFHE_BINDINGS_H__

+ 14 - 11
src/include/docstrings/binfhecontext_docs.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef BINFHECONTEXT_DOCSTRINGS_H
-#define BINFHECONTEXT_DOCSTRINGS_H
+//==================================================================================
+#ifndef __BINFHECONTEXT_DOCS_H
+#define __BINFHECONTEXT_DOCS_H
 
 // GenerateBinFHEContext
 const char* binfhe_GenerateBinFHEContext_parset_docs = R"pbdoc(
@@ -199,4 +202,4 @@ const char* binfhe_SerializedObjectName_docs = R"pbdoc(
    :return: object name
    :rtype: std::string
 )pbdoc";
-#endif // BINFHECONTEXT_DOCSTRINGS_H
+#endif // __BINFHECONTEXT_DOCS_H

+ 14 - 11
src/include/docstrings/ciphertext_docs.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef CIPHERTEXT_DOCSTRINGS_H
-#define CIPHERTEXT_DOCSTRINGS_H
+//==================================================================================
+#ifndef __CIPHERTEXT_DOCS_H__
+#define __CIPHERTEXT_DOCS_H__
 
 // GetLevel
 const char* ctx_GetLevel_docs = R"pbdoc(
@@ -58,4 +61,4 @@ const char* cc_RemoveElement_docs = R"pbdoc(
     :param index: The index of the element to remove.
     :type index: int
 )pbdoc";
-#endif // CIPHERTEXT_DOCSTRINGS_H
+#endif // __CIPHERTEXT_DOCS_H__

+ 372 - 67
src/include/docstrings/cryptocontext_docs.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef CRYPTOCONTEXT_DOCSTRINGS_H
-#define CRYPTOCONTEXT_DOCSTRINGS_H
+//==================================================================================
+#ifndef __CRYPTOCONTEXT_DOCS_H__
+#define __CRYPTOCONTEXT_DOCS_H__
 
 #include "pybind11/pybind11.h"
 #include "pybind11/attr.h"
@@ -53,7 +56,7 @@ const char* cc_GetKeyGenLevel_docs = R"pbdoc(
 )pbdoc";
 
 const char* cc_GetRingDimension_docs = R"pbdoc(
-    Get the ring dimension used for this context
+    Getter for ring dimension
 
     :return: The ring dimension
     :rtype: int
@@ -67,16 +70,16 @@ const char* cc_GetPlaintextModulus_docs = R"pbdoc(
 )pbdoc";
 
 const char* cc_GetCyclotomicOrder_docs = R"pbdoc(
-    Get the cyclotomic order used for this context
+    Getter for cyclotomic order
 
-    :return: The cyclotomic order
+    :return: cyclotomic order
     :rtype: int
 )pbdoc";
 
 const char* cc_GetModulus_docs = R"pbdoc(
-    Get the cyclotomic order used for this context
+    Getter for ciphertext modulus
 
-    :return: The modulus
+    :return: modulus
     :rtype: int
 )pbdoc";
 
@@ -89,7 +92,7 @@ const char* cc_Enable_docs = R"pbdoc(
 )pbdoc";
 
 const char* cc_KeyGen_docs = R"pbdoc(
-    Generate a public and private key pair
+    Generates a standard public/secret key pair.
 
     :return: a public/secret key pair
     :rtype: KeyPair
@@ -329,13 +332,13 @@ Decrypt a single ciphertext into the appropriate plaintext
 )pbdoc";
 
 const char* cc_KeySwitchGen_docs = R"pbdoc(
-    KeySwitchGen creates a key that can be used with the OpenFHE KeySwitch operation
+    Generates a key switching key from one secret key to another.
 
-    :param oldPrivateKey: input secrey key
+    :param oldPrivateKey: Original secret key.
     :type oldPrivateKey: PrivateKey
-    :param newPrivateKey: output secret key
+    :param newPrivateKey: Target secret key.
     :type newPrivateKey: PrivateKey
-    :return: new evaluation key
+    :return: New evaluation key for key switching.
     :rtype: EvalKey
 )pbdoc";
 
@@ -787,56 +790,56 @@ const char* cc_EvalSumKeyGen_docs = R"pbdoc(
 )pbdoc";
 
 const char* cc_EvalSumRowsKeyGen_docs = R"pbdoc(
-    Generate the automorphism keys for EvalSumRows; works only for packed encoding
+    Generates automorphism keys for EvalSumRows (only for packed encoding).
 
-    :param privateKey: private key
+    :param privateKey: Private key used for key generation.
     :type privateKey: PrivateKey
-    :param publicKey: public key
+    :param publicKey: Public key (used in NTRU schemes; unused now).
     :type publicKey: PublicKey
-    :param rowSize: size of rows in the matrix
+    :param rowSize: Number of slots per row in the packed matrix.
     :type rowSize: int
-    :param subringDim: subring dimension (set to cyclotomic order if set to 0)
+    :param subringDim: Subring dimension (use cyclotomic order if 0).
     :type subringDim: int
-    :return: returns the evaluation keys
+    :return: Map of generated evaluation keys.
     :rtype: EvalKeyMap
 )pbdoc";
 
 const char* cc_EvalSumColsKeyGen_docs = R"pbdoc(
-    Generates the automorphism keys for EvalSumCols; works only for packed encoding
+    Generates automorphism keys for EvalSumCols (only for packed encoding).
 
-    :param privateKey: private key
+    :param privateKey: Private key used for key generation.
     :type privateKey: PrivateKey
-    :param publicKey: public key
+    :param publicKey: Public key (used in NTRU schemes; unused now).
     :type publicKey: PublicKey
-    :return: returns the evaluation keys
+    :return: Map of generated evaluation keys.
     :rtype: EvalKeyMap
 )pbdoc";
 
 const char* cc_EvalSumRows_docs = R"pbdoc(
-    Sums all elements over row-vectors in a matrix - works only with packed encoding
+    Sums all elements across each row in a packed-encoded matrix ciphertext.
 
-    :param ciphertext: the input ciphertext
+    :param ciphertext: Input ciphertext.
     :type ciphertext: Ciphertext
-    :param rowSize: size of rows in the matrix
-    :type rowSize: int
-    :param evalSumKeyMap: reference to the map of evaluation keys generated by
+    :param numRows: Number of rows in the matrix.
+    :type numRows: int
+    :param evalSumKeyMap: Map of evaluation keys generated for row summation.
     :type evalSumKeyMap: EvalKeyMap
-    :param subringDim: the current cyclotomic order/subring dimension. If set to 0, we use the full cyclotomic order.
+    :param subringDim: Subring dimension (use full cyclotomic order if 0).
     :type subringDim: int
-    :return: Ciphertext: resulting ciphertext
+    :return: Ciphertext: Ciphertext containing row-wise sums.
     :rtype: Ciphertext
 )pbdoc";
 
 const char* cc_EvalSumCols_docs = R"pbdoc(
-    Sums all elements over column-vectors in a matrix - works only with packed encoding
+    Sums all elements across each column in a packed-encoded matrix ciphertext.
 
-    :param ciphertext: the input ciphertext
+    :param ciphertext: Input ciphertext.
     :type ciphertext: Ciphertext
-    :param rowSize: size of rows in the matrix
-    :type rowSize: int
-    :param evalSumKeyMap: reference to the map of evaluation keys generated by
+    :param numCols: Number of columns in the matrix.
+    :type numCols: int
+    :param evalSumKeyMap: Map of evaluation keys generated for column summation.
     :type evalSumKeyMap: EvalKeyMap
-    :return: Ciphertext: resulting ciphertext
+    :return: Ciphertext: Ciphertext containing column-wise sums.
     :rtype: Ciphertext
 )pbdoc";
 
@@ -932,7 +935,24 @@ const char* cc_MultiKeySwitchGen_docs = R"pbdoc(
     :rtype: EvalKey
 )pbdoc";
 
-// TODO (Oliveira, R.) - Complete the following documentation
+const char* cc_GetEvalMultKeyVector_docs = R"pbdoc(
+    Get relinearization keys for a specific secret key tag
+
+    :param keyId: key identifier used for private key
+    :type keyId: str
+    :return: EvalKeyVector: vector with all relinearization keys.
+    :rtype: EvalKeyVector
+)pbdoc";
+
+const char* cc_GetEvalAutomorphismKeyMap_docs = R"pbdoc(
+    Get automorphism keys for a specific secret key tag
+
+    :param keyId: key identifier used for private key
+    :type keyId: str
+    :return: EvalKeyMap: map with all automorphism keys.
+    :rtype: EvalKeyMap
+)pbdoc";
+
 const char* cc_GetEvalSumKeyMap_docs = R"pbdoc(
     Get a map of summation keys (each is composed of several automorphism keys) for a specific secret key tag
     :return: EvalKeyMap: key map
@@ -944,6 +964,22 @@ const char* cc_InsertEvalSumKey_docs = R"pbdoc(
     :param evalKeyMap: key map
     :type evalKeyMap: EvalKeyMap
 )pbdoc";
+
+const char* cc_MultiEvalAtIndexKeyGen_docs = R"pbdoc(
+    Threshold FHE: Generates joined rotation keys from the current secret key and prior joined rotation keys
+
+    :param privateKey: secret key share
+    :type privateKey: PrivateKey
+    :param evalKeyMap: a map with prior joined rotation keys
+    :type evalKeyMap: EvalKeyMap
+    :param indexList: a vector of rotation indices
+    :type indexList: List[int32]
+    :param keyId: new key identifier used for resulting evaluation key
+    :type keyId: str
+    :return: EvalKeyMap: a map with new joined rotation keys
+    :rtype: EvalKeyMap
+)pbdoc";
+
 const char* cc_MultiEvalSumKeyGen_docs = R"pbdoc(
     Threshold FHE: Generates joined summation evaluation keys from the current secret share and prior joined summation keys
 
@@ -957,6 +993,32 @@ const char* cc_MultiEvalSumKeyGen_docs = R"pbdoc(
     :rtype: EvalKeyMap
 )pbdoc";
 
+const char* cc_MultiAddEvalAutomorphismKeys_docs = R"pbdoc(
+    Threshold FHE: Adds two prior evaluation key sets for automorphisms
+
+    :param evalKeyMap1: first automorphism key set
+    :type evalKeyMap1: EvalKeyMap
+    :param evalKeyMap2: second automorphism key set
+    :type evalKeyMap2: EvalKeyMap
+    :param keyId: new key identifier used for resulting evaluation key
+    :type keyId: str
+    :return: the new joined key set for summation
+    :rtype: evalKeyMap
+)pbdoc";
+
+const char* cc_MultiAddPubKeys_docs = R"pbdoc(
+    Threshold FHE: Adds two prior public keys
+
+    :param publicKey1: first public key
+    :type publicKey1: PublicKey
+    :param publicKey2: second public key
+    :type publicKey2: PublicKey
+    :param keyId: new key identifier used for the resulting key
+    :type keyId: str
+    :return: the new combined key
+    :rtype: PublicKey
+)pbdoc";
+
 const char* cc_MultiAddEvalKeys_docs = R"pbdoc(
     Threshold FHE: Adds two prior evaluation keys
 
@@ -1009,6 +1071,47 @@ const char* cc_MultiAddEvalMultKeys_docs = R"pbdoc(
     :rtype: EvalKey
 )pbdoc";
 
+const char* cc_IntBootDecrypt_docs = R"pbdoc(
+    Performs masked decryption for interactive bootstrapping (2-party protocol).
+
+    :param privateKey: Secret key share
+    :type privateKey: PrivateKey
+    :param ciphertext: Input Ciphertext
+    :type ciphertext: Ciphertext
+    :return: Resulting ciphertext
+    :rtype: Ciphertext
+)pbdoc";
+
+const char* cc_IntBootEncrypt_docs = R"pbdoc(
+    Encrypts Client's masked decryption for interactive bootstrapping. Increases ciphertext modulus to allow further computation. Done by Client.
+
+    :param publicKey: Joined public key (Threshold FHE)
+    :type publicKey: PublicKey
+    :param ciphertext: Input Ciphertext
+    :type ciphertext: Ciphertext
+    :return: Resulting ciphertext
+    :rtype: Ciphertext
+)pbdoc";
+
+const char* cc_IntBootAdd_docs = R"pbdoc(
+    Combines encrypted and unencrypted masked decryptions in 2-party interactive bootstrapping. It is the last step in the boostrapping.
+
+    :param ciphertext1: Encrypted masked decryption
+    :type ciphertext1: Ciphertext
+    :param ciphertext2: Unencrypted masked decryption
+    :type ciphertext2: Ciphertext
+    :return: Refreshed ciphertext
+    :rtype: Ciphertext
+)pbdoc";
+
+const char* cc_IntBootAdjustScale_docs = R"pbdoc(
+    Prepares a ciphertext for interactive bootstrapping.
+
+    :param ciphertext: Input ciphertext
+    :type ciphertext: Ciphertext
+    :return: Adjusted ciphertext
+    :rtype: Ciphertext
+)pbdoc";
 
 const char* cc_IntMPBootAdjustScale_docs = R"pbdoc(
     Threshold FHE: Prepare a ciphertext for Multi-Party Interactive Bootstrapping.
@@ -1066,12 +1169,21 @@ const char* cc_IntMPBootEncrypt_docs = R"pbdoc(
 )pbdoc";
 
 const char* cc_InsertEvalMultKey_docs = R"pbdoc(
-    InsertEvalMultKey - add the given vector of keys to the map, replacing the existing vector if there
+    Adds the given vector of keys to the map, replacing the existing vector if there
 
     :param evalKeyVec: vector of keys
     :type evalKeyVec: List[EvalKey]
 )pbdoc";
 
+const char* cc_InsertEvalAutomorphismKey_docs = R"pbdoc(
+    Add the given map of keys to the map, replacing the existing map if there is one
+
+    :param evalKeyMap: map of keys to be inserted
+    :type EvalKeyMap
+    :param keyTag: key identifier for the given key map
+    :type keyTag: str
+)pbdoc";
+
 const char* cc_EvalSum_docs = R"pbdoc(
     Function for evaluating a sum of all components in a vector.
 
@@ -1118,13 +1230,13 @@ const char* cc_ReEncrypt_docs = R"pbdoc(
 )pbdoc";
 
 const char* cc_EvalPoly_docs = R"pbdoc(
-    Method for polynomial evaluation for polynomials represented as power series.
+    Evaluates a polynomial (given as a power series) on a ciphertext (CKKS only). Use EvalPolyLinear() for low polynomial degrees (degree < 5), or EvalPolyPS() for higher degrees.
 
-    :param ciphertext: input ciphertext
+    :param ciphertext: Input ciphertext.
     :type ciphertext: Ciphertext
-    :param coefficients: vector of coefficients in the polynomial; the size of the vector is the degree of the polynomial + 1
+    :param coefficients: Polynomial coefficients (vector's size = (degree + 1)).
     :type coefficients: list
-    :return: Ciphertext: the result of polynomial evaluation.
+    :return: Ciphertext: Resulting ciphertext.
     :rtype: Ciphertext
 )pbdoc";
 
@@ -1225,22 +1337,215 @@ const char* cc_EvalBootstrap_docs = R"pbdoc(
     :rtype: Ciphertext
 )pbdoc";
 
-// TODO (Oliveira, R.) - Complete the following documentation
-const char* cc_EvalCKKStoFHEWSetup_docs = "";
-const char* cc_EvalCKKStoFHEWKeyGen_docs = "";
-const char* cc_EvalCKKStoFHEWPrecompute_docs = "";
-const char* cc_EvalCKKStoFHEW_docs = "";
-const char* cc_EvalFHEWtoCKKSSetup_docs = "";
-const char* cc_EvalFHEWtoCKKSKeyGen_docs = "";
-const char* cc_EvalFHEWtoCKKS_docs = "";
-const char* cc_EvalSchemeSwitchingSetup_docs = "";
-const char* cc_EvalSchemeSwitchingKeyGen_docs = "";
-const char* cc_EvalCompareSwitchPrecompute_docs = "";
-const char* cc_EvalCompareSchemeSwitching_docs = "";
-const char* cc_EvalMinSchemeSwitching_docs = "";
-const char* cc_EvalMinSchemeSwitchingAlt_docs = "";
-const char* cc_EvalMaxSchemeSwitching_docs = "";
-const char* cc_EvalMaxSchemeSwitchingAlt_docs = "";
+const char* cc_EvalCKKStoFHEWSetup_docs = R"pbdoc(
+    Sets all parameters for switching from CKKS to FHEW.
+
+    :param schswchparams: Parameters for CKKS-to-FHEW scheme switching.
+    :type schswchparams: SchSwchParams
+    :return: FHEW secret key.
+    :rtype: LWEPrivateKey
+)pbdoc";
+
+const char* cc_EvalCKKStoFHEWKeyGen_docs = R"pbdoc(
+    Sets all parameters for switching from CKKS to FHEW.
+
+    :param keyPair: CKKS key pair.
+    :type keyPair: KeyPair
+    :param lwesk: FHEW secret key.
+    :type lwesk: LWEPrivateKey
+)pbdoc";
+
+const char* cc_EvalCKKStoFHEWPrecompute_docs = R"pbdoc(
+    Performs precomputations for CKKS homomorphic decoding. Allows setting a custom scale factor. Given as a separate method than EvalCKKStoFHEWSetup to allow the user to specify a scale that depends on the CKKS and FHEW cryptocontexts
+
+    :param scale: Scaling factor for the linear transform matrix.
+    :type scale: float
+)pbdoc";
+
+const char* cc_EvalCKKStoFHEW_docs = R"pbdoc(
+    Switches a CKKS ciphertext to a vector of FHEW ciphertexts.
+
+    :param ciphertext: Input CKKS ciphertext.
+    :type ciphertext: Ciphertext
+    :param numCtxts: Number of coefficients to extract (defaults to number of slots if 0).
+    :type numCtxts: int
+)pbdoc";
+
+const char* cc_EvalFHEWtoCKKSSetup_docs = R"pbdoc(
+    Sets parameters for switching from FHEW to CKKS. Requires existing CKKS context.
+
+    :param ccLWE: Source FHEW crypto context.
+    :type ccLWE: BinFHEContext
+    :param numSlotsCKKS  Number of slots in resulting CKKS ciphertext.
+    :type numSlotsCKKS: int
+    :param logQ:  Ciphertext modulus size in FHEW (for high precision).
+    :type logQ: int
+)pbdoc";
+
+const char* cc_EvalFHEWtoCKKSKeyGen_docs = R"pbdoc(
+    Generates keys for switching from FHEW to CKKS.
+
+    :param keyPair:   CKKS key pair.
+    :type keyPair:    KeyPair
+    :param lwesk:     FHEW secret key.
+    :type lwesk:      LWEPrivateKey
+    :param numSlots:  Number of slots for CKKS encryption.
+    :type numSlots:   int
+    :param numCtxts:  Number of LWE ciphertext values to encrypt.
+    :type numCtxts:   int
+    :param dim1:      Baby-step parameter for linear transform.
+    :type dim1:       int
+    :param L:         Target level for homomorphic decoding matrix.
+    :type L:          int
+)pbdoc";
+
+const char* cc_EvalFHEWtoCKKS_docs = R"pbdoc(
+    Switches a vector of FHEW ciphertexts to a single CKKS ciphertext.
+
+    :param LWECiphertexts:  Input vector of FHEW ciphertexts.
+    :type  LWECiphertexts:  list of LWECiphertext.
+    :param numCtxts:        Number of values to encode.
+    :type  numCtxts:        int
+    :param numSlots:        Number of CKKS slots to use.
+    :type  numSlots:        int
+    :param p:               Plaintext modulus (default = 4).
+    :type  p:               int.
+    :param pmin:            Minimum expected plaintext value (default = 0.0).
+    :type  pmin:            float.
+    :param pmax:            Maximum expected plaintext value (default = 2.0).
+    :type  pmax:            float.
+    :param dim1:            Baby-step parameter (used in argmin).
+    :type  dim1:            int.
+    :return:                CKKS ciphertext encoding the input LWE messages.
+    :rtype:                 Ciphertext
+)pbdoc";
+
+const char* cc_EvalSchemeSwitchingSetup_docs = R"pbdoc(
+    Sets parameters for switching between CKKS and FHEW.
+
+    :param schswchparams:  Scheme switching parameter object.
+    :type  schswchparams:  SchSwchParams.
+    :return:               FHEW secret key.
+    :rtype:                LWEPrivateKey.
+)pbdoc";
+
+const char* cc_EvalSchemeSwitchingKeyGen_docs = R"pbdoc(
+    Generates keys for switching between CKKS and FHEW.
+
+    :param keyPair:  CKKS key pair.
+    :type  keyPair:  KeyPair.
+    :param lwesk:    FHEW secret key.
+    :type  lwesk:    LWEPrivateKey.
+)pbdoc";
+
+const char* cc_EvalCompareSwitchPrecompute_docs = R"pbdoc(
+    Performs precomputations for scheme switching in CKKS-to-FHEW comparison. Given as a separate method than EvalSchemeSwitchingSetup to allow the user to specify a scale.
+
+    :param pLWE:       Target plaintext modulus for FHEW ciphertexts.
+    :type  pLWE:       int.
+    :param scaleSign:  Scaling factor for CKKS ciphertexts before switching.
+    :type  scaleSign:  float.
+    :param unit:       Indicates if input messages are normalized to unit circle.
+    :type  unit:       bool.
+)pbdoc";
+
+const char* cc_EvalCompareSchemeSwitching_docs = R"pbdoc(
+    Compares two CKKS ciphertexts using FHEW-based scheme switching and returns CKKS result.
+
+    :param ciphertext1:  First input CKKS ciphertext.
+    :type  ciphertext1:  Ciphertext.
+    :param ciphertext2:  Second input CKKS ciphertext.
+    :type  ciphertext2:  Ciphertext.
+    :param numCtxts:     Number of coefficients to extract.
+    :type  numCtxts:     int.
+    :param numSlots:     Number of slots to encode in the result.
+    :type  numSlots:     int.
+    :param pLWE:         Target plaintext modulus for FHEW ciphertexts.
+    :type  pLWE:         int.
+    :param scaleSign:    Scaling factor for CKKS ciphertexts before switching.
+    :type  scaleSign:    float.
+    :param unit:         Indicates if input messages are normalized to unit circle.
+    :type  unit:         bool.
+    :return:             CKKS ciphertext encoding sign comparison result.
+    :rtype:              Ciphertext
+)pbdoc";
+
+const char* cc_EvalMinSchemeSwitching_docs = R"pbdoc(
+    Computes minimum and index of the first packed values using scheme switching.
+
+    :param ciphertext:  Input CKKS ciphertext.
+    :type  ciphertext:  Ciphertext.
+    :param publicKey:   CKKS public key.
+    :type  publicKey:   PublicKey.
+    :param numValues:   Number of values to compare (we assume that numValues is a power of two).
+    :type  numValues:   int.
+    :param numSlots:    Number of output slots.
+    :type  numSlots:    int.
+    :param pLWE:        Target plaintext modulus for FHEW.
+    :type  pLWE:        int.
+    :param scaleSign:   Scaling factor before switching to FHEW. The resulting FHEW ciphertexts will encrypt values modulo pLWE, so scaleSign should account for this pLWE and is given here only if the homomorphic decoding matrix is not scaled with the desired values
+    :type  scaleSign:   float.
+    :return: A vector of two CKKS ciphertexts: [min, argmin]. The ciphertexts have junk after the first slot in the first ciphertext
+         and after numValues in the second ciphertext if oneHot=true and after the first slot if oneHot=false.
+    :rtype:             list of Ciphertext.
+)pbdoc";
+
+const char* cc_EvalMinSchemeSwitchingAlt_docs = R"pbdoc(
+    Computes minimum and index using more FHEW operations than CKKS with higher precision, but slower than EvalMinSchemeSwitching.
+
+    :param ciphertext:  Input CKKS ciphertext.
+    :type  ciphertext:  Ciphertext.
+    :param publicKey:   CKKS public key.
+    :type  publicKey:   PublicKey.
+    :param numValues:   Number of packed values to compare.
+    :type  numValues:   int.
+    :param numSlots:    Number of slots in the output ciphertexts.
+    :type  numSlots:    int.
+    :param pLWE:        Target plaintext modulus for FHEW ciphertexts.
+    :type  pLWE:        int.
+    :param scaleSign:   Scaling factor before switching to FHEW.
+    :type  scaleSign:   float.
+    :return:            A vector with two CKKS ciphertexts: [min, argmin].
+    :rtype:             list of Ciphertext.
+)pbdoc";
+
+const char* cc_EvalMaxSchemeSwitching_docs = R"pbdoc(
+    Computes maximum and index from the first packed values using scheme switching.
+
+    :param ciphertext:  Input CKKS ciphertext.
+    :type  ciphertext:  Ciphertext.
+    :param publicKey:   CKKS public key.
+    :type  publicKey:   PublicKey.
+    :param numValues:   Number of values to compare (we assume that numValues is a power of two).
+    :type  numValues:   int.
+    :param numSlots:    Number of output slots.
+    :type  numSlots:    int.
+    :param pLWE:        Target plaintext modulus for FHEW.
+    :type  pLWE:        int.
+    :param scaleSign:   Scaling factor before switching to FHEW.
+    :type  scaleSign:   float.
+    :return:            A vector of two CKKS ciphertexts: [max, argmax]. The ciphertexts have junk after the first slot in the first ciphertext and after numValues in the second ciphertext if oneHot=true and after the first slot if oneHot=false.
+    :rtype:             list of Ciphertext.
+)pbdoc";
+
+const char* cc_EvalMaxSchemeSwitchingAlt_docs = R"pbdoc(
+    Computes max and index via scheme switching, with more FHEW operations for better precision than EvalMaxSchemeSwitching.
+
+    :param ciphertext:  Input CKKS ciphertext.
+    :type  ciphertext:  Ciphertext.
+    :param publicKey:   CKKS public key.
+    :type  publicKey:   PublicKey.
+    :param numValues:   Number of values to compare.
+    :type  numValues:   int.
+    :param numSlots:    Number of output slots.
+    :type  numSlots:    int.
+    :param pLWE:        Target plaintext modulus for FHEW.
+    :type  pLWE:        int.
+    :param scaleSign:   Scaling factor before switching to FHEW.
+    :type  scaleSign:   float.
+    :return:            A vector of two CKKS ciphertexts: [max, argmax].
+    :rtype:             list of Ciphertext.
+)pbdoc";
 
 const char* cc_EvalAutomorphismKeyGen_docs = R"pbdoc(
     Generate automophism keys for a given private key; Uses the private key for encryption
@@ -1279,7 +1584,7 @@ const char* cc_ClearEvalMultKeys_docs = R"pbdoc(
 )pbdoc";
 
 const char* cc_ClearEvalAutomorphismKeys_docs = R"pbdoc(
-    ClearEvalAutomorphismKeys - flush EvalAutomorphismKey cache
+    Flush EvalAutomorphismKey cache
 )pbdoc";
 
 const char* cc_SerializeEvalAutomorphismKey_docs = R"pbdoc(
@@ -1327,4 +1632,4 @@ const char* cc_DeserializeEvalMultKey_docs = R"pbdoc(
 )pbdoc";
 
 
-#endif //CRYPTOCONTEXT_DOCSTRINGS_H
+#endif // __CRYPTOCONTEXT_DOCS_H__

+ 17 - 11
src/include/docstrings/cryptoparameters_docs.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef CRYPTOPARAMS_DOCSTRINGS_H
-#define CRYPTOPARAMS_DOCSTRINGS_H
+//==================================================================================
+#ifndef __CRYPTOPARAMETERS_DOCS_H__
+#define __CRYPTOPARAMETERS_DOCS_H__
 
 const char* ccparams_doc = R"doc(
     Crypto parameters for the BFV, BGV and CKKS scheme.
@@ -60,6 +63,9 @@ const char* ccparams_doc = R"doc(
     :ivar int multiHopModSize: size of moduli used for PRE in the provable HRA setting
     :ivar EncryptionTechnique encryptionTechnique: STANDARD or EXTENDED mode for BFV encryption
     :ivar MultiplicationTechnique multiplicationTechnique: multiplication method in BFV: BEHZ, HPS, etc.
+    :ivar CKKSDataType ckksDataType: CKKS data type: real or complex. Noise flooding is only enabled for real values.
+    :ivar uint32_t compositeDegree: parameter to support high-precision CKKS RNS with small word sizes
+    :ivar uint32_t registerWordSize: parameter to support high-precision CKKS RNS with small word sizes
 )doc";
 
 const char* cc_GetScalingFactorReal_docs = R"pbdoc(
@@ -72,4 +78,4 @@ const char* cc_GetScalingFactorReal_docs = R"pbdoc(
 )pbdoc";
 
 
-#endif // CRYPTOPARAMS_DOCSTRINGS_H
+#endif // __CRYPTOPARAMETERS_DOCS_H__

+ 14 - 11
src/include/docstrings/plaintext_docs.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,9 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef PLAINTEXT_DOCSTRINGS_H
-#define PLAINTEXT_DOCSTRINGS_H
+//==================================================================================
+#ifndef __PLAINTEXT_DOCS_H__
+#define __PLAINTEXT_DOCS_H__
 
 // GetScalingFactor
 const char* ptx_GetScalingFactor_docs = R"doc(
@@ -133,4 +136,4 @@ const char* ptx_GetRealPackedValue_docs = R"pbdoc(
 )pbdoc";
 
 
-#endif // PLAINTEXT_DOCSTRINGS_H
+#endif // __PLAINTEXT_DOCS_H__

+ 26 - 33
src/include/pke/cryptocontext_wrapper.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,33 +27,24 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//==================================================================================
+#ifndef __CRYPTOCONTEXT_WRAPPER_H__
+#define __CRYPTOCONTEXT_WRAPPER_H__
 
-#ifndef OPENFHE_CRYPTOCONTEXT_BINDINGS_H
-#define OPENFHE_CRYPTOCONTEXT_BINDINGS_H
-
-#include "bindings.h"
 #include "openfhe.h"
 
-#include <pybind11/pybind11.h>
-#include <pybind11/stl.h>
-#include <vector>
-#include <algorithm>
-#include <complex>
-
-
-namespace py = pybind11;
 using namespace lbcrypto;
-using ParmType = typename DCRTPoly::Params;
+
 
 Ciphertext<DCRTPoly> EvalFastRotationPrecomputeWrapper(CryptoContext<DCRTPoly> &self,
                                                        ConstCiphertext<DCRTPoly> ciphertext);
 
 Ciphertext<DCRTPoly> EvalFastRotationWrapper(CryptoContext<DCRTPoly> &self,
                                              ConstCiphertext<DCRTPoly> ciphertext,
-                                             const usint index,
-                                             const usint m,
+                                             uint32_t index,
+                                             uint32_t m,
                                              ConstCiphertext<DCRTPoly> digits);
-Ciphertext<DCRTPoly> EvalFastRotationExtWrapper(CryptoContext<DCRTPoly> &self, ConstCiphertext<DCRTPoly> ciphertext, const usint index, ConstCiphertext<DCRTPoly> digits, bool addFirst);
+Ciphertext<DCRTPoly> EvalFastRotationExtWrapper(CryptoContext<DCRTPoly> &self, ConstCiphertext<DCRTPoly> ciphertext, uint32_t index, ConstCiphertext<DCRTPoly> digits, bool addFirst);
 
 Plaintext DecryptWrapper(CryptoContext<DCRTPoly> &self,
                          ConstCiphertext<DCRTPoly> ciphertext, const PrivateKey<DCRTPoly> privateKey);
@@ -58,16 +52,15 @@ Plaintext DecryptWrapper(CryptoContext<DCRTPoly> &self,
                          const PrivateKey<DCRTPoly> privateKey, ConstCiphertext<DCRTPoly> ciphertext);
 Plaintext MultipartyDecryptFusionWrapper(CryptoContext<DCRTPoly>& self,const std::vector<Ciphertext<DCRTPoly>>& partialCiphertextVec);
 
-const std::map<usint, EvalKey<DCRTPoly>> EvalAutomorphismKeyGenWrapper(CryptoContext<DCRTPoly>& self,const PrivateKey<DCRTPoly> privateKey,const std::vector<usint> &indexList);
-const std::shared_ptr<std::map<usint, EvalKey<DCRTPoly>>> GetEvalSumKeyMapWrapper(CryptoContext<DCRTPoly>& self, const std::string &id);
-const PlaintextModulus GetPlaintextModulusWrapper(CryptoContext<DCRTPoly>& self);
-const double GetModulusWrapper(CryptoContext<DCRTPoly>& self);
-void RemoveElementWrapper(Ciphertext<DCRTPoly>& self, usint index);
-const double GetScalingFactorRealWrapper(CryptoContext<DCRTPoly>& self, uint32_t l);
-const uint64_t GetModulusCKKSWrapper(CryptoContext<DCRTPoly>& self);
-const ScalingTechnique GetScalingTechniqueWrapper(CryptoContext<DCRTPoly>& self);
-const usint GetDigitSizeWrapper(CryptoContext<DCRTPoly>& self);
+const std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>> GetEvalSumKeyMapWrapper(CryptoContext<DCRTPoly>& self, const std::string &id);
+PlaintextModulus GetPlaintextModulusWrapper(CryptoContext<DCRTPoly>& self);
+double GetModulusWrapper(CryptoContext<DCRTPoly>& self);
+void RemoveElementWrapper(Ciphertext<DCRTPoly>& self, uint32_t index);
+double GetScalingFactorRealWrapper(CryptoContext<DCRTPoly>& self, uint32_t l);
+uint64_t GetModulusCKKSWrapper(CryptoContext<DCRTPoly>& self);
+ScalingTechnique GetScalingTechniqueWrapper(CryptoContext<DCRTPoly>& self);
+uint32_t GetDigitSizeWrapper(CryptoContext<DCRTPoly>& self);
 
 void ClearEvalMultKeysWrapper();
 
-#endif // OPENFHE_CRYPTOCONTEXT_BINDINGS_H
+#endif // __CRYPTOCONTEXT_WRAPPER_H__

+ 18 - 19
src/include/pke/serialization.h

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,16 +27,12 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef OPENFHE_SERIALIZATION_BINDINGS_H
-#define OPENFHE_SERIALIZATION_BINDINGS_H
+//==================================================================================
+#ifndef __SERIALIZATION_H__
+#define __SERIALIZATION_H__
 
 #include <pybind11/pybind11.h>
-#include "openfhe.h"
-#include "bindings.h"
 
-using namespace lbcrypto;
-namespace py = pybind11;
 
 template <typename ST>
 bool SerializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype, std::string id);
@@ -48,25 +47,25 @@ template <typename T, typename ST>
 std::string SerializeToStringWrapper(const T& obj, const ST& sertype);
 
 template <typename T, typename ST>
-py::bytes SerializeToBytesWrapper(const T& obj, const ST& sertype);
+pybind11::bytes SerializeToBytesWrapper(const T& obj, const ST& sertype);
 
 template <typename T, typename ST>
 T DeserializeFromStringWrapper(const std::string& str, const ST& sertype);
 
 template <typename T, typename ST>
-T DeserializeFromBytesWrapper(const py::bytes& bytes, const ST& sertype);
+T DeserializeFromBytesWrapper(const pybind11::bytes& bytes, const ST& sertype);
 
 template <typename ST>
 std::string SerializeEvalMultKeyToStringWrapper(const ST& sertype, const std::string& id);
 
 template <typename ST>
-py::bytes SerializeEvalMultKeyToBytesWrapper(const ST& sertype, const std::string& id);
+pybind11::bytes SerializeEvalMultKeyToBytesWrapper(const ST& sertype, const std::string& id);
 
 template <typename ST>
 std::string SerializeEvalAutomorphismKeyToStringWrapper(const ST& sertype, const std::string& id);
 
 template <typename ST>
-py::bytes SerializeEvalAutomorphismKeyToBytesWrapper(const ST& sertype, const std::string& id);
+pybind11::bytes SerializeEvalAutomorphismKeyToBytesWrapper(const ST& sertype, const std::string& id);
 
 template <typename ST>
 void DeserializeEvalMultKeyFromStringWrapper(const std::string& data, const ST& sertype);
@@ -80,4 +79,4 @@ void DeserializeEvalAutomorphismKeyFromStringWrapper(const std::string& data, co
 template <typename ST>
 void DeserializeEvalAutomorphismKeyFromBytesWrapper(const std::string& data, const ST& sertype);
 
-#endif // OPENFHE_SERIALIZATION_BINDINGS_H
+#endif // __SERIALIZATION_H__

+ 338 - 121
src/lib/bindings.cpp

@@ -1,26 +1,65 @@
-#include <pybind11/pybind11.h>
+//==================================================================================
+// BSD 2-Clause License
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
+// All rights reserved.
+//
+// Author TPOC: contact@openfhe.org
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//==================================================================================
+#include "bindings.h"
+
 #include <pybind11/stl.h>
 #include <pybind11/stl_bind.h>
 #include <pybind11/complex.h>
 #include <pybind11/functional.h>
 #include <pybind11/operators.h>
 #include <pybind11/iostream.h>
-#include <iostream>
-#include <map>
+
 #include "openfhe.h"
+
 #include "key/key-ser.h"
-#include "bindings.h"
-#include "cryptocontext_wrapper.h"
 #include "binfhe_bindings.h"
+
+#include "cryptocontext_wrapper.h"
 #include "cryptocontext_docs.h"
 #include "cryptoparameters_docs.h"
 #include "plaintext_docs.h"
 #include "ciphertext_docs.h"
-#include "serialization.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;
-PYBIND11_MAKE_OPAQUE(std::map<usint, EvalKey<DCRTPoly>>);
+
+// disable the PYBIND11 template-based conversion for this type
+PYBIND11_MAKE_OPAQUE(std::map<uint32_t, EvalKey<DCRTPoly>>);
+
+inline std::shared_ptr<CryptoParametersRNS> GetParamsRNSChecked(const CryptoContext<DCRTPoly>& self, const std::string& func) {
+    auto ptr = std::dynamic_pointer_cast<CryptoParametersRNS>(self->GetCryptoParameters());
+    if (!ptr)
+        OPENFHE_THROW("Failed to cast to CryptoParametersRNS in " + func + "()");
+    return ptr;
+}
 
 template <typename T>
 void bind_parameters(py::module &m,const std::string name)
@@ -58,6 +97,9 @@ void bind_parameters(py::module &m,const std::string name)
         .def("GetMultiplicationTechnique", &CCParams<T>::GetMultiplicationTechnique)
         .def("GetPRENumHops", &CCParams<T>::GetPRENumHops)
         .def("GetInteractiveBootCompressionLevel", &CCParams<T>::GetInteractiveBootCompressionLevel)
+        .def("GetCompositeDegree", &CCParams<T>::GetCompositeDegree)
+        .def("GetRegisterWordSize", &CCParams<T>::GetRegisterWordSize)
+        .def("GetCKKSDataType", &CCParams<T>::GetCKKSDataType)
         // setters
         .def("SetPlaintextModulus", &CCParams<T>::SetPlaintextModulus)
         .def("SetDigitSize", &CCParams<T>::SetDigitSize)
@@ -88,6 +130,9 @@ void bind_parameters(py::module &m,const std::string name)
         .def("SetMultiplicationTechnique", &CCParams<T>::SetMultiplicationTechnique)
         .def("SetPRENumHops", &CCParams<T>::SetPRENumHops)
         .def("SetInteractiveBootCompressionLevel", &CCParams<T>::SetInteractiveBootCompressionLevel)
+        .def("SetCompositeDegree", &CCParams<T>::SetCompositeDegree)
+        .def("SetRegisterWordSize", &CCParams<T>::SetRegisterWordSize)
+        .def("SetCKKSDataType", &CCParams<T>::SetCKKSDataType)
         .def("__str__",[](const CCParams<T> &params) {
             std::stringstream stream;
             stream << params;
@@ -100,6 +145,12 @@ void bind_parameters(py::module &m,const std::string name)
 
 void bind_crypto_context(py::module &m)
 {
+    //Parameters Type
+    /*TODO (Oliveira): If we expose Poly's and ParmType, this block will go somewhere else */
+    using ParmType = typename DCRTPoly::Params;
+    using ParmTypePtr = std::shared_ptr<ParmType>;
+    py::class_<ParmType, ParmTypePtr>(m, "ParmType");
+
     py::class_<CryptoContextImpl<DCRTPoly>, std::shared_ptr<CryptoContextImpl<DCRTPoly>>>(m, "CryptoContext")
         .def(py::init<>())
         .def("GetKeyGenLevel", &CryptoContextImpl<DCRTPoly>::GetKeyGenLevel, cc_GetKeyGenLevel_docs)
@@ -117,6 +168,43 @@ void bind_crypto_context(py::module &m)
         .def("GetScalingTechnique",&GetScalingTechniqueWrapper)
         .def("GetDigitSize", &GetDigitSizeWrapper)
         .def("GetCyclotomicOrder", &CryptoContextImpl<DCRTPoly>::GetCyclotomicOrder, cc_GetCyclotomicOrder_docs)
+        .def("GetCKKSDataType", &CryptoContextImpl<DCRTPoly>::GetCKKSDataType)
+        .def("GetNoiseEstimate", [](CryptoContext<DCRTPoly>& self) {
+            return GetParamsRNSChecked(self, "GetNoiseEstimate")->GetNoiseEstimate();
+        })
+        .def("SetNoiseEstimate", [](CryptoContext<DCRTPoly>& self, double noiseEstimate) {
+            GetParamsRNSChecked(self, "SetNoiseEstimate")->SetNoiseEstimate(noiseEstimate);
+        }, py::arg("noiseEstimate"))
+        .def("GetMultiplicativeDepth", [](CryptoContext<DCRTPoly>& self) {
+            return GetParamsRNSChecked(self, "GetMultiplicativeDepth")->GetMultiplicativeDepth();
+        })
+        .def("SetMultiplicativeDepth", [](CryptoContext<DCRTPoly>& self, uint32_t multiplicativeDepth) {
+            GetParamsRNSChecked(self, "SetMultiplicativeDepth")->SetMultiplicativeDepth(multiplicativeDepth);
+        }, py::arg("multiplicativeDepth"))
+        .def("GetEvalAddCount", [](CryptoContext<DCRTPoly>& self) {
+            return GetParamsRNSChecked(self, "GetEvalAddCount")->GetEvalAddCount();
+        })
+        .def("SetEvalAddCount", [](CryptoContext<DCRTPoly>& self, uint32_t evalAddCount) {
+            GetParamsRNSChecked(self, "SetEvalAddCount")->SetEvalAddCount(evalAddCount);
+        }, py::arg("evalAddCount"))
+        .def("GetKeySwitchCount", [](CryptoContext<DCRTPoly>& self) {
+            return GetParamsRNSChecked(self, "GetKeySwitchCount")->GetKeySwitchCount();
+        })
+        .def("SetKeySwitchCount", [](CryptoContext<DCRTPoly>& self, uint32_t keySwitchCount) {
+            GetParamsRNSChecked(self, "SetKeySwitchCount")->SetKeySwitchCount(keySwitchCount);
+        }, py::arg("keySwitchCount"))
+        .def("GetPRENumHops", [](CryptoContext<DCRTPoly>& self) {
+            return GetParamsRNSChecked(self, "GetPRENumHops")->GetPRENumHops();
+        })
+        .def("SetPRENumHops", [](CryptoContext<DCRTPoly>& self, uint32_t PRENumHops) {
+            GetParamsRNSChecked(self, "SetPRENumHops")->SetPRENumHops(PRENumHops);
+        }, py::arg("PRENumHops"))
+        .def("GetRegisterWordSize", [](CryptoContext<DCRTPoly>& self) {
+            return GetParamsRNSChecked(self, "GetRegisterWordSize")->GetRegisterWordSize();
+        })
+        .def("GetCompositeDegree", [](CryptoContext<DCRTPoly>& self) {
+            return GetParamsRNSChecked(self, "GetCompositeDegree")->GetCompositeDegree();
+        })
         .def("Enable", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(PKESchemeFeature)>(&CryptoContextImpl<DCRTPoly>::Enable), cc_Enable_docs,
              py::arg("feature"))
         .def("KeyGen", &CryptoContextImpl<DCRTPoly>::KeyGen, cc_KeyGen_docs)
@@ -145,13 +233,13 @@ void bind_crypto_context(py::module &m)
             py::arg("noiseScaleDeg ") = 1,
             py::arg("level") = 0)
         // TODO (Oliveira): allow user to specify different params values
-        .def("MakeCKKSPackedPlaintext", static_cast<Plaintext (CryptoContextImpl<DCRTPoly>::*)(const std::vector<std::complex<double>> &, size_t, uint32_t, const std::shared_ptr<ParmType>, usint) const>(&CryptoContextImpl<DCRTPoly>::MakeCKKSPackedPlaintext), cc_MakeCKKSPackedPlaintextComplex_docs,
+        .def("MakeCKKSPackedPlaintext", static_cast<Plaintext (CryptoContextImpl<DCRTPoly>::*)(const std::vector<std::complex<double>> &, size_t, uint32_t, const std::shared_ptr<ParmType>, uint32_t) const>(&CryptoContextImpl<DCRTPoly>::MakeCKKSPackedPlaintext), cc_MakeCKKSPackedPlaintextComplex_docs,
              py::arg("value"),
              py::arg("scaleDeg") = static_cast<size_t>(1),
              py::arg("level") = static_cast<uint32_t>(0),
              py::arg("params") = py::none(),
              py::arg("slots") = 0)
-        .def("MakeCKKSPackedPlaintext", static_cast<Plaintext (CryptoContextImpl<DCRTPoly>::*)(const std::vector<double> &, size_t, uint32_t, const std::shared_ptr<ParmType>, usint) const>(&CryptoContextImpl<DCRTPoly>::MakeCKKSPackedPlaintext), cc_MakeCKKSPlaintextReal_docs,
+        .def("MakeCKKSPackedPlaintext", static_cast<Plaintext (CryptoContextImpl<DCRTPoly>::*)(const std::vector<double> &, size_t, uint32_t, const std::shared_ptr<ParmType>, uint32_t) const>(&CryptoContextImpl<DCRTPoly>::MakeCKKSPackedPlaintext), cc_MakeCKKSPlaintextReal_docs,
              py::arg("value"),
              py::arg("scaleDeg") = static_cast<size_t>(1),
              py::arg("level") = static_cast<uint32_t>(0),
@@ -202,28 +290,27 @@ void bind_crypto_context(py::module &m)
             cc_KeySwitchGen_docs,
             py::arg("oldPrivateKey"),
             py::arg("newPrivateKey"))
-        .def("EvalAdd", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalAdd", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalAdd), 
             cc_EvalAdd_docs,
             py::arg("ciphertext1"),
             py::arg("ciphertext2"))
-        .def("EvalAdd", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, double) const>
+        .def("EvalAdd", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, double) const>
             (&CryptoContextImpl<DCRTPoly>::EvalAdd), 
             cc_EvalAddfloat_docs,
             py::arg("ciphertext"),
-            py::arg("constant"))
-        //inline Ciphertext<Element> EvalAdd(ConstCiphertext<Element> ciphertext, ConstPlaintext plaintext) const
-        .def("EvalAdd", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstPlaintext) const>
+            py::arg("scalar"))
+        .def("EvalAdd", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, ConstPlaintext) const>
             (&CryptoContextImpl<DCRTPoly>::EvalAdd),
             cc_EvalAddPlaintext_docs,
             py::arg("ciphertext"),
             py::arg("plaintext"))
-        .def("EvalAddInPlace", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly> &, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalAddInPlace", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly>&, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalAddInPlace),
             cc_EvalAddInPlace_docs,
             py::arg("ciphertext1"),
             py::arg("ciphertext2"))
-        .def("EvalAddInPlace", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly> &, ConstPlaintext) const>
+        .def("EvalAddInPlace", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly>&, ConstPlaintext) const>
             (&CryptoContextImpl<DCRTPoly>::EvalAddInPlace),
             cc_EvalAddInPlacePlaintext_docs,
             py::arg("ciphertext"),
@@ -252,32 +339,32 @@ void bind_crypto_context(py::module &m)
             cc_EvalAddMutableInPlace_docs,
             py::arg("ciphertext1"),
             py::arg("ciphertext2"))
-        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSub),
             cc_EvalSub_docs,
             py::arg("ciphertext1"),
             py::arg("ciphertext2"))
-        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, double) const>
+        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, double) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSub),
             cc_EvalSubfloat_docs,
             py::arg("ciphertext"),
-            py::arg("constant"))
-        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(double, ConstCiphertext<DCRTPoly>) const>
+            py::arg("scalar"))
+        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(double, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSub),
             "",
-            py::arg("constant"),
+            py::arg("scalar"),
             py::arg("ciphertext"))
-        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstPlaintext) const>
+        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, ConstPlaintext) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSub),
             cc_EvalSubPlaintext_docs,
             py::arg("ciphertext"),
             py::arg("plaintext"))
-        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstPlaintext, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalSub", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstPlaintext, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSub),
             "",
             py::arg("plaintext"),
             py::arg("ciphertext"))
-        .def("EvalSubInPlace", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly> &, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalSubInPlace", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly> &, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSubInPlace),
             cc_EvalSubInPlace_docs,
             py::arg("ciphertext1"),
@@ -286,11 +373,11 @@ void bind_crypto_context(py::module &m)
             (&CryptoContextImpl<DCRTPoly>::EvalSubInPlace),
             cc_EvalSubInPlacefloat_docs,
             py::arg("ciphertext"),
-            py::arg("constant"))
+            py::arg("scalar"))
         .def("EvalSubInPlace", static_cast<void (CryptoContextImpl<DCRTPoly>::*)(double, Ciphertext<DCRTPoly> &) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSubInPlace),
             "",
-            py::arg("constant"),
+            py::arg("scalar"),
             py::arg("ciphertext"))
         .def("EvalSubMutable", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly> &, Ciphertext<DCRTPoly> &) const>
             (&CryptoContextImpl<DCRTPoly>::EvalSubMutable),
@@ -311,30 +398,30 @@ void bind_crypto_context(py::module &m)
             cc_EvalSubMutableInPlace_docs,
             py::arg("ciphertext1"),
             py::arg("ciphertext2"))
-        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalMult),
             cc_EvalMult_docs,
             py::arg("ciphertext1"),
             py::arg("ciphertext2"))
-        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, double) const>
+        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, double) const>
             (&CryptoContextImpl<DCRTPoly>::EvalMult),
             cc_EvalMultfloat_docs,
             py::arg("ciphertext"),
-            py::arg("constant"))
-        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstPlaintext) const>
+            py::arg("scalar"))
+        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, ConstPlaintext) const>
             (&CryptoContextImpl<DCRTPoly>::EvalMult),
             cc_EvalMultPlaintext_docs,
             py::arg("ciphertext"),
             py::arg("plaintext"))
-        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstPlaintext, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstPlaintext, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalMult),
             "",
             py::arg("plaintext"),
             py::arg("ciphertext"))
-        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(double, ConstCiphertext<DCRTPoly>) const>
+        .def("EvalMult", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(double, const ConstCiphertext<DCRTPoly>&) const>
             (&CryptoContextImpl<DCRTPoly>::EvalMult),
             "",
-            py::arg("constant"),
+            py::arg("scalar"),
             py::arg("ciphertext"))
         .def("EvalMultMutable", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(Ciphertext<DCRTPoly> &, Ciphertext<DCRTPoly> &) const>
             (&CryptoContextImpl<DCRTPoly>::EvalMultMutable),
@@ -455,20 +542,20 @@ void bind_crypto_context(py::module &m)
         .def("EvalSumRows", &CryptoContextImpl<DCRTPoly>::EvalSumRows,
              cc_EvalSumRows_docs,
              py::arg("ciphertext"),
-             py::arg("rowSize"),
+             py::arg("numRows"),
              py::arg("evalSumKeyMap"),
              py::arg("subringDim") = 0)
         .def("EvalSumCols", &CryptoContextImpl<DCRTPoly>::EvalSumCols,
              cc_EvalSumCols_docs,
              py::arg("ciphertext"),
-             py::arg("rowSize"),
+             py::arg("numCols"),
              py::arg("evalSumKeyMap"))
-        .def("EvalInnerProduct", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstCiphertext<DCRTPoly>, usint) const>(&CryptoContextImpl<DCRTPoly>::EvalInnerProduct),
+        .def("EvalInnerProduct", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, const ConstCiphertext<DCRTPoly>&, uint32_t) const>(&CryptoContextImpl<DCRTPoly>::EvalInnerProduct),
              cc_EvalInnerProduct_docs,
              py::arg("ciphertext1"),
              py::arg("ciphertext2"),
              py::arg("batchSize"))
-        .def("EvalInnerProduct", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(ConstCiphertext<DCRTPoly>, ConstPlaintext, usint) const>(&CryptoContextImpl<DCRTPoly>::EvalInnerProduct),
+        .def("EvalInnerProduct", static_cast<Ciphertext<DCRTPoly> (CryptoContextImpl<DCRTPoly>::*)(const ConstCiphertext<DCRTPoly>&, ConstPlaintext, uint32_t) const>(&CryptoContextImpl<DCRTPoly>::EvalInnerProduct),
              cc_EvalInnerProductPlaintext_docs,
              py::arg("ciphertext"),
              py::arg("plaintext"),
@@ -497,21 +584,59 @@ void bind_crypto_context(py::module &m)
              py::arg("originalPrivateKey"),
              py::arg("newPrivateKey"),
              py::arg("evalKey"))
+        .def("MultiEvalAtIndexKeyGen",
+            [](CryptoContextImpl<DCRTPoly>* self,
+                const PrivateKey<DCRTPoly>& privateKey,
+                std::shared_ptr<std::map<unsigned int, EvalKey<DCRTPoly>>> evalKeyMap,
+                const std::vector<int32_t>& indexList,
+                const std::string& keyTag = "") {
+              return self->MultiEvalAtIndexKeyGen(privateKey, evalKeyMap, indexList, keyTag);
+             },
+             cc_MultiEvalAtIndexKeyGen_docs,
+             py::arg("privateKey"),
+             py::arg("evalKeyMap"),
+             py::arg("indexList"),
+             py::arg("keyTag") = "")
         .def("MultiEvalSumKeyGen", &CryptoContextImpl<DCRTPoly>::MultiEvalSumKeyGen,
              cc_MultiEvalSumKeyGen_docs,
              py::arg("privateKey"),
              py::arg("evalKeyMap"),
-             py::arg("keyId") = "")
+             py::arg("keyTag") = "")
+        .def("MultiAddEvalAutomorphismKeys", &CryptoContextImpl<DCRTPoly>::MultiAddEvalAutomorphismKeys,
+            cc_MultiAddEvalAutomorphismKeys_docs,
+            py::arg("evalKeyMap1"),
+            py::arg("evalKeyMap1"),
+            py::arg("keyTag") = "")
+        .def("MultiAddPubKeys", &CryptoContextImpl<DCRTPoly>::MultiAddPubKeys,
+            cc_MultiAddPubKeys_docs,
+            py::arg("publicKey1"),
+            py::arg("publicKey2"),
+            py::arg("keyTag") = "")
         .def("MultiAddEvalKeys", &CryptoContextImpl<DCRTPoly>::MultiAddEvalKeys,
              cc_MultiAddEvalKeys_docs,
              py::arg("evalKey1"),
              py::arg("evalKey2"),
-             py::arg("keyId") = "")
+             py::arg("keyTag") = "")
         .def("MultiAddEvalMultKeys", &CryptoContextImpl<DCRTPoly>::MultiAddEvalMultKeys,
              cc_MultiAddEvalMultKeys_docs,
              py::arg("evalKey1"),
              py::arg("evalKey2"),
-             py::arg("keyId") = "")
+             py::arg("keyTag") = "")
+        .def("IntBootDecrypt",&CryptoContextImpl<DCRTPoly>::IntBootDecrypt,
+            cc_IntBootDecrypt_docs,
+            py::arg("privateKey"),
+            py::arg("ciphertext"))
+        .def("IntBootEncrypt",&CryptoContextImpl<DCRTPoly>::IntBootEncrypt,
+            cc_IntBootEncrypt_docs,
+            py::arg("publicKey"),
+            py::arg("ciphertext"))
+        .def("IntBootAdd",&CryptoContextImpl<DCRTPoly>::IntBootAdd,
+            cc_IntBootAdd_docs,
+            py::arg("ciphertext1"),
+            py::arg("ciphertext2"))
+        .def("IntBootAdjustScale",&CryptoContextImpl<DCRTPoly>::IntBootAdjustScale,
+            cc_IntBootAdjustScale_docs,
+            py::arg("ciphertext"))
         .def("IntMPBootAdjustScale",&CryptoContextImpl<DCRTPoly>::IntMPBootAdjustScale,
              cc_IntMPBootAdjustScale_docs,
              py::arg("ciphertext"))
@@ -536,12 +661,12 @@ void bind_crypto_context(py::module &m)
              cc_MultiMultEvalKey_docs,
              py::arg("privateKey"),
              py::arg("evalKey"),
-             py::arg("keyId") = "")
+             py::arg("keyTag") = "")
         .def("MultiAddEvalSumKeys", &CryptoContextImpl<DCRTPoly>::MultiAddEvalSumKeys,
              cc_MultiAddEvalSumKeys_docs,
              py::arg("evalKeyMap1"),
              py::arg("evalKeyMap2"),
-             py::arg("keyId") = "")
+             py::arg("keyTag") = "")
         .def("EvalMerge", &CryptoContextImpl<DCRTPoly>::EvalMerge,
              cc_EvalMerge_docs,
              py::arg("ciphertextVec"))
@@ -686,11 +811,12 @@ void bind_crypto_context(py::module &m)
              py::arg("pLWE") = 0,
              py::arg("scaleSign") = 1.0)
         //TODO (Oliveira, R.): Solve pointer handling bug when returning EvalKeyMap objects for the next functions
-        .def("EvalAutomorphismKeyGen", &EvalAutomorphismKeyGenWrapper, 
+        .def("EvalAutomorphismKeyGen",
+            static_cast<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>> (CryptoContextImpl<DCRTPoly>::*)(const PrivateKey<DCRTPoly>, const std::vector<uint32_t>&) const>
+            (&CryptoContextImpl<DCRTPoly>::EvalAutomorphismKeyGen), 
             cc_EvalAutomorphismKeyGen_docs,
             py::arg("privateKey"),
-            py::arg("indexList"),
-            py::return_value_policy::reference_internal)
+            py::arg("indexList"))
         .def("EvalLinearWSumMutable",
             static_cast<lbcrypto::Ciphertext<DCRTPoly> (lbcrypto::CryptoContextImpl<DCRTPoly>::*)(
                 const std::vector<double>&,
@@ -705,8 +831,13 @@ void bind_crypto_context(py::module &m)
             &CryptoContextImpl<DCRTPoly>::EvalLinearWSum),
              py::arg("ciphertext"),
              py::arg("coefficients"))
+       .def("Compress", &CryptoContextImpl<DCRTPoly>::Compress,
+            py::arg("ciphertext"),
+            py::arg("towersLeft"))
         .def("EvalMultMany", &CryptoContextImpl<DCRTPoly>::EvalMultMany,
             py::arg("ciphertextVec"))
+        .def("EvalAddMany", &CryptoContextImpl<DCRTPoly>::EvalAddMany,
+            py::arg("ciphertextVec"))
         .def("EvalAddManyInPlace", &CryptoContextImpl<DCRTPoly>::EvalAddManyInPlace,
             py::arg("ciphertextVec"))
         .def("FindAutomorphismIndex", &CryptoContextImpl<DCRTPoly>::FindAutomorphismIndex,
@@ -715,6 +846,9 @@ void bind_crypto_context(py::module &m)
         .def("FindAutomorphismIndices", &CryptoContextImpl<DCRTPoly>::FindAutomorphismIndices,
             cc_FindAutomorphismIndices_docs,
             py::arg("idxList"))
+        .def("GetEvalSumKeyMap", &GetEvalSumKeyMapWrapper,
+            cc_GetEvalSumKeyMap_docs)
+        .def("GetBinCCForSchemeSwitch", &CryptoContextImpl<DCRTPoly>::GetBinCCForSchemeSwitch)
         .def_static(
             "InsertEvalSumKey", &CryptoContextImpl<DCRTPoly>::InsertEvalSumKey,
             cc_InsertEvalSumKey_docs,
@@ -725,103 +859,104 @@ void bind_crypto_context(py::module &m)
             cc_InsertEvalMultKey_docs,
             py::arg("evalKeyVec"),
             py::arg("keyTag") = "")
+        .def_static(
+            "InsertEvalAutomorphismKey", &CryptoContextImpl<DCRTPoly>::InsertEvalAutomorphismKey,
+            cc_InsertEvalAutomorphismKey_docs,
+            py::arg("evalKeyMap"),
+            py::arg("keyTag") = "")
         .def_static(
             "ClearEvalAutomorphismKeys", []()
             { CryptoContextImpl<DCRTPoly>::ClearEvalAutomorphismKeys(); },
             cc_ClearEvalAutomorphismKeys_docs)
-        .def("GetEvalSumKeyMap", &GetEvalSumKeyMapWrapper,
-            cc_GetEvalSumKeyMap_docs,
-            py::return_value_policy::reference)
-        .def("GetBinCCForSchemeSwitch", &CryptoContextImpl<DCRTPoly>::GetBinCCForSchemeSwitch,
-        		py::return_value_policy::reference_internal)
+        // it is safer to return by value instead of by reference (GetEvalMultKeyVector returns a const reference to std::vector)
+        .def_static("GetEvalMultKeyVector",
+            [](const std::string& keyTag) {
+              return CryptoContextImpl<DCRTPoly>::GetEvalMultKeyVector(keyTag);
+            },
+            cc_GetEvalMultKeyVector_docs,
+            py::arg("keyTag") = "")
+        .def_static("GetEvalAutomorphismKeyMap", &CryptoContextImpl<DCRTPoly>::GetEvalAutomorphismKeyMapPtr,
+            cc_GetEvalAutomorphismKeyMap_docs,
+            py::arg("keyTag") = "")
         .def_static(
-            "SerializeEvalMultKey", [](const std::string &filename, const SerType::SERBINARY &sertype, std::string id = "")
+            "SerializeEvalMultKey", [](const std::string &filename, const SerType::SERBINARY &sertype, std::string keyTag = "")
             {
-                std::ofstream outfile(filename,std::ios::out | std::ios::binary);
-                bool res;
-                res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey<SerType::SERBINARY>(outfile, sertype, id);
-                outfile.close();
-                return res; },
+              std::ofstream outfile(filename, std::ios::out | std::ios::binary);
+              bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey<SerType::SERBINARY>(outfile, sertype, keyTag);
+              outfile.close();
+              return res; },
             cc_SerializeEvalMultKey_docs,
-            py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
+            py::arg("filename"), py::arg("sertype"), py::arg("keyTag") = "")
         .def_static( // SerializeEvalMultKey - JSON
-            "SerializeEvalMultKey", [](const std::string &filename, const SerType::SERJSON &sertype, std::string id = "")
+            "SerializeEvalMultKey", [](const std::string &filename, const SerType::SERJSON &sertype, std::string keyTag = "")
             {
-                std::ofstream outfile(filename,std::ios::out | std::ios::binary);
-                bool res;
-                res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey<SerType::SERJSON>(outfile, sertype, id);
-                outfile.close();
-                return res; },
+              std::ofstream outfile(filename, std::ios::out | std::ios::binary);
+              bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey<SerType::SERJSON>(outfile, sertype, keyTag);
+              outfile.close();
+              return res; },
             cc_SerializeEvalMultKey_docs,
-            py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
+            py::arg("filename"), py::arg("sertype"), py::arg("keyTag") = "")
         .def_static( // SerializeEvalAutomorphismKey - Binary
-            "SerializeEvalAutomorphismKey", [](const std::string &filename, const SerType::SERBINARY &sertype, std::string id = "")
+            "SerializeEvalAutomorphismKey", [](const std::string &filename, const SerType::SERBINARY &sertype, std::string keyTag = "")
             {
-                std::ofstream outfile(filename,std::ios::out | std::ios::binary);
-                bool res;
-                res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<SerType::SERBINARY>(outfile, sertype, id);
-                outfile.close();
-                return res; },
+              std::ofstream outfile(filename, std::ios::out | std::ios::binary);
+              bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<SerType::SERBINARY>(outfile, sertype, keyTag);
+              outfile.close();
+              return res; },
             cc_SerializeEvalAutomorphismKey_docs,
-            py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
+            py::arg("filename"), py::arg("sertype"), py::arg("keyTag") = "")
         .def_static( // SerializeEvalAutomorphismKey - JSON
-            "SerializeEvalAutomorphismKey", [](const std::string &filename, const SerType::SERJSON &sertype, std::string id = "")
+            "SerializeEvalAutomorphismKey", [](const std::string &filename, const SerType::SERJSON &sertype, std::string keyTag = "")
             {
-                std::ofstream outfile(filename,std::ios::out | std::ios::binary);
-                bool res;
-                res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<SerType::SERJSON>(outfile, sertype, id);
-                outfile.close();
-                return res; },
+              std::ofstream outfile(filename, std::ios::out | std::ios::binary);
+              bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<SerType::SERJSON>(outfile, sertype, keyTag);
+              outfile.close();
+              return res; },
             cc_SerializeEvalAutomorphismKey_docs,
-            py::arg("filename"), py::arg("sertype"), py::arg("id") = "")
+            py::arg("filename"), py::arg("sertype"), py::arg("keyTag") = "")
         .def_static("DeserializeEvalMultKey", // DeserializeEvalMultKey - Binary
         [](const std::string &filename, const SerType::SERBINARY &sertype)
                     {
-                        std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
-                         if (!emkeys.is_open()) {
-                            std::cerr << "I cannot read serialization from " << filename << std::endl;
-                         }
-                        bool res;
-                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<SerType::SERBINARY>(emkeys, sertype);
-                        return res; 
-                        
+              std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
+              if (!emkeys.is_open()) {
+                std::cerr << "I cannot read serialization from " << filename << std::endl;
+              }
+              bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<SerType::SERBINARY>(emkeys, sertype);
+              return res; 
                         },
                         cc_DeserializeEvalMultKey_docs,
                         py::arg("filename"), py::arg("sertype"))
         .def_static("DeserializeEvalMultKey", // DeserializeEvalMultKey - JSON
         [](const std::string &filename, const SerType::SERJSON &sertype)
                     {
-                        std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
-                         if (!emkeys.is_open()) {
-                            std::cerr << "I cannot read serialization from " << filename << std::endl;
-                         }
-                        bool res;
-                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<SerType::SERJSON>(emkeys, sertype);
-                        return res; },
+              std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
+              if (!emkeys.is_open()) {
+                std::cerr << "I cannot read serialization from " << filename << std::endl;
+              }
+              bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<SerType::SERJSON>(emkeys, sertype);
+              return res; },
                         cc_DeserializeEvalMultKey_docs,
                         py::arg("filename"), py::arg("sertype"))
         .def_static("DeserializeEvalAutomorphismKey", // DeserializeEvalAutomorphismKey - Binary
         [](const std::string &filename, const SerType::SERBINARY &sertype)
                     {
-                        std::ifstream erkeys(filename, std::ios::in | std::ios::binary);
-                         if (!erkeys.is_open()) {
-                            std::cerr << "I cannot read serialization from " << filename << std::endl;
-                         }
-                        bool res;
-                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<SerType::SERBINARY>(erkeys, sertype);
-                        return res; },
+              std::ifstream erkeys(filename, std::ios::in | std::ios::binary);
+              if (!erkeys.is_open()) {
+                std::cerr << "I cannot read serialization from " << filename << std::endl;
+              }
+              bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<SerType::SERBINARY>(erkeys, sertype);
+              return res; },
                         cc_DeserializeEvalAutomorphismKey_docs,
                         py::arg("filename"), py::arg("sertype"))
         .def_static("DeserializeEvalAutomorphismKey", // DeserializeEvalAutomorphismKey - JSON
         [](const std::string &filename, const SerType::SERJSON &sertype)
                     {
-                        std::ifstream erkeys(filename, std::ios::in | std::ios::binary);
-                         if (!erkeys.is_open()) {
-                            std::cerr << "I cannot read serialization from " << filename << std::endl;
-                         }
-                        bool res;
-                        res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<SerType::SERJSON>(erkeys, sertype);
-                        return res; },
+              std::ifstream erkeys(filename, std::ios::in | std::ios::binary);
+              if (!erkeys.is_open()) {
+                std::cerr << "I cannot read serialization from " << filename << std::endl;
+              }
+              bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<SerType::SERJSON>(erkeys, sertype);
+              return res; },
                         cc_DeserializeEvalAutomorphismKey_docs,
                         py::arg("filename"), py::arg("sertype"));
 
@@ -901,12 +1036,16 @@ void bind_enums_and_constants(py::module &m)
        .value("FLEXIBLEAUTO", ScalingTechnique::FLEXIBLEAUTO)
        .value("FLEXIBLEAUTOEXT", ScalingTechnique::FLEXIBLEAUTOEXT)
        .value("NORESCALE", ScalingTechnique::NORESCALE)
+       .value("COMPOSITESCALINGAUTO", ScalingTechnique::COMPOSITESCALINGAUTO)
+       .value("COMPOSITESCALINGMANUAL", ScalingTechnique::COMPOSITESCALINGMANUAL)
        .value("INVALID_RS_TECHNIQUE", ScalingTechnique::INVALID_RS_TECHNIQUE);
     m.attr("FIXEDMANUAL") = py::cast(ScalingTechnique::FIXEDMANUAL);
     m.attr("FIXEDAUTO") = py::cast(ScalingTechnique::FIXEDAUTO);
     m.attr("FLEXIBLEAUTO") = py::cast(ScalingTechnique::FLEXIBLEAUTO);
     m.attr("FLEXIBLEAUTOEXT") = py::cast(ScalingTechnique::FLEXIBLEAUTOEXT);
     m.attr("NORESCALE") = py::cast(ScalingTechnique::NORESCALE);
+    m.attr("COMPOSITESCALINGAUTO") = py::cast(ScalingTechnique::COMPOSITESCALINGAUTO);
+    m.attr("COMPOSITESCALINGMANUAL") = py::cast(ScalingTechnique::COMPOSITESCALINGMANUAL);
     m.attr("INVALID_RS_TECHNIQUE") = py::cast(ScalingTechnique::INVALID_RS_TECHNIQUE);
 
     // Key Switching Techniques
@@ -985,7 +1124,13 @@ void bind_enums_and_constants(py::module &m)
         .value("SLACK", COMPRESSION_LEVEL::SLACK);
     m.attr("COMPACT") = py::cast(COMPRESSION_LEVEL::COMPACT);
     m.attr("SLACK") = py::cast(COMPRESSION_LEVEL::SLACK);
-        
+
+    py::enum_<CKKSDataType>(m,"CKKSDataType")
+        .value("REAL", CKKSDataType::REAL)
+        .value("COMPLEX", CKKSDataType::COMPLEX);
+    m.attr("REAL") = py::cast(CKKSDataType::REAL);
+    m.attr("COMPLEX") = py::cast(CKKSDataType::COMPLEX);
+
     /* ---- CORE enums ---- */ 
     // Security Level
     py::enum_<SecurityLevel>(m,"SecurityLevel")
@@ -998,15 +1143,8 @@ void bind_enums_and_constants(py::module &m)
     m.attr("HEStd_256_classic") = py::cast(SecurityLevel::HEStd_256_classic);
     m.attr("HEStd_NotSet") = py::cast(SecurityLevel::HEStd_NotSet);
     
-    //Parameters Type
-    /*TODO (Oliveira): If we expose Poly's and ParmType, this block will go somewhere else */
-    using ParmType = typename DCRTPoly::Params;
-    py::class_<ParmType, std::shared_ptr<ParmType>>(m, "ParmType");
-
     //NATIVEINT function
     m.def("get_native_int", &get_native_int);
-  
-    
 }
 
 void bind_keys(py::module &m)
@@ -1024,16 +1162,95 @@ void bind_keys(py::module &m)
         .def_readwrite("secretKey", &KeyPair<DCRTPoly>::secretKey)
         .def("good", &KeyPair<DCRTPoly>::good,kp_good_docs);
     py::class_<EvalKeyImpl<DCRTPoly>, std::shared_ptr<EvalKeyImpl<DCRTPoly>>>(m, "EvalKey")
-    .def(py::init<>())
+        .def(py::init<>())
         .def("GetKeyTag", &EvalKeyImpl<DCRTPoly>::GetKeyTag)
         .def("SetKeyTag", &EvalKeyImpl<DCRTPoly>::SetKeyTag);
-    py::class_<std::map<usint, EvalKey<DCRTPoly>>, std::shared_ptr<std::map<usint, EvalKey<DCRTPoly>>>>(m, "EvalKeyMap")
+    py::class_<std::map<uint32_t, EvalKey<DCRTPoly>>, std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>>(m, "EvalKeyMap")
         .def(py::init<>());
 }
 
+// PlaintextImpl is an abstract class, so we should use a helper (trampoline) class
+class PlaintextImpl_helper : public PlaintextImpl
+{
+public:
+    using PlaintextImpl::PlaintextImpl; // inherited constructors
+
+    // the PlaintextImpl virtual functions' overrides
+    bool Encode() override {
+        PYBIND11_OVERRIDE_PURE(
+            bool,          // return type
+            PlaintextImpl, // parent class
+            Encode         // function name
+                           // no arguments
+        );
+    }
+    bool Decode() override {
+        PYBIND11_OVERRIDE_PURE(
+            bool,          // return type
+            PlaintextImpl, // parent class
+            Decode         // function name
+                           // no arguments
+        );
+    }
+    bool Decode(size_t depth, double scalingFactor, ScalingTechnique scalTech, ExecutionMode executionMode) override {
+        PYBIND11_OVERRIDE(
+            bool,          // return type
+            PlaintextImpl, // parent class
+            Decode,        // function name
+            depth, scalingFactor, scalTech, executionMode // arguments
+        );
+    }
+    size_t GetLength() const override {
+        PYBIND11_OVERRIDE_PURE(
+            size_t,        // return type
+            PlaintextImpl, // parent class
+            GetLength      // function name
+                           // no arguments
+        );
+    }
+    void SetLength(size_t newSize) override {
+        PYBIND11_OVERRIDE(
+            void,          // return type
+            PlaintextImpl, // parent class
+            SetLength,     // function name
+            newSize        // arguments
+        );
+    }
+    double GetLogError() const override {
+        PYBIND11_OVERRIDE(double, PlaintextImpl, GetLogError);
+    }
+    double GetLogPrecision() const override {
+        PYBIND11_OVERRIDE(double, PlaintextImpl, GetLogPrecision);
+    }
+    const std::string& GetStringValue() const override {
+        PYBIND11_OVERRIDE(const std::string&, PlaintextImpl, GetStringValue);
+    }
+    const std::vector<int64_t>& GetCoefPackedValue() const override {
+        PYBIND11_OVERRIDE(const std::vector<int64_t>&, PlaintextImpl, GetCoefPackedValue);
+    }
+    const std::vector<int64_t>& GetPackedValue() const override {
+        PYBIND11_OVERRIDE(const std::vector<int64_t>&, PlaintextImpl, GetPackedValue);
+    }
+    const std::vector<std::complex<double>>& GetCKKSPackedValue() const override {
+        PYBIND11_OVERRIDE(const std::vector<std::complex<double>>&, PlaintextImpl, GetCKKSPackedValue);
+    }
+    std::vector<double> GetRealPackedValue() const override {
+        PYBIND11_OVERRIDE(std::vector<double>, PlaintextImpl, GetRealPackedValue);
+    }
+    void SetStringValue(const std::string& str) override {
+        PYBIND11_OVERRIDE(void, PlaintextImpl, SetStringValue, str);
+    }
+    void SetIntVectorValue(const std::vector<int64_t>& vec) override {
+        PYBIND11_OVERRIDE(void, PlaintextImpl, SetIntVectorValue, vec);
+    }
+    std::string GetFormattedValues(int64_t precision) const override {
+        PYBIND11_OVERRIDE(std::string, PlaintextImpl, GetFormattedValues, precision);
+    }
+};
+
 void bind_encodings(py::module &m)
 {
-    py::class_<PlaintextImpl, std::shared_ptr<PlaintextImpl>>(m, "Plaintext")
+    py::class_<PlaintextImpl, std::shared_ptr<PlaintextImpl>, PlaintextImpl_helper>(m, "Plaintext")
         .def("GetScalingFactor", &PlaintextImpl::GetScalingFactor,
             ptx_GetScalingFactor_docs)
         .def("SetScalingFactor", &PlaintextImpl::SetScalingFactor,
@@ -1043,8 +1260,6 @@ void bind_encodings(py::module &m)
             ptx_GetSchemeID_docs)
         .def("GetLength", &PlaintextImpl::GetLength,
             ptx_GetLength_docs)
-        .def("GetSchemeID", &PlaintextImpl::GetSchemeID,
-            ptx_GetSchemeID_docs)
         .def("SetLength", &PlaintextImpl::SetLength,
             ptx_SetLength_docs,
             py::arg("newSize"))
@@ -1054,7 +1269,9 @@ void bind_encodings(py::module &m)
             ptx_GetLogPrecision_docs)
         .def("Encode", &PlaintextImpl::Encode,
             ptx_Encode_docs)
-        .def("Decode", &PlaintextImpl::Decode,
+        .def("Decode", py::overload_cast<>(&PlaintextImpl::Decode),
+            ptx_Decode_docs)
+        .def("Decode", py::overload_cast<size_t, double, ScalingTechnique, ExecutionMode>(&PlaintextImpl::Decode),
             ptx_Decode_docs)
         .def("LowBound", &PlaintextImpl::LowBound,
             ptx_LowBound_docs)

+ 11 - 8
src/lib/binfhe/binfhecontext_wrapper.cpp

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,7 +27,7 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+//==================================================================================
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
 #include <openfhe.h>

+ 27 - 25
src/lib/binfhe_bindings.cpp

@@ -1,43 +1,45 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
-// 1. Redistributions of source code must retain the above copyright notice,
-// this
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//==================================================================================
 #include "binfhe_bindings.h"
+
+#include <pybind11/operators.h>
+
+#include "openfhe.h"
 #include "binfhecontext.h"
 #include "binfhecontext_docs.h"
 #include "binfhecontext_wrapper.h"
-#include "openfhe.h"
+
 #include "cereal/archives/binary.hpp"
-#include "cereal/archives/portable_binary.hpp"
-#include "core/utils/serial.h"
-#include <iostream>
-#include <pybind11/operators.h>
-#include <pybind11/pybind11.h>
+// #include "cereal/archives/portable_binary.hpp"
+// #include "core/utils/serial.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;

+ 22 - 35
src/lib/pke/cryptocontext_wrapper.cpp

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,19 +27,9 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+//==================================================================================
 #include "cryptocontext_wrapper.h"
-#include <openfhe.h>
-
-#include <pybind11/pybind11.h>
-#include <pybind11/stl.h>
-#include <vector>
-#include <algorithm>
-#include <complex>
-#include <iomanip>
 
-using namespace lbcrypto;
-namespace py = pybind11;
 
 Ciphertext<DCRTPoly> EvalFastRotationPrecomputeWrapper(CryptoContext<DCRTPoly> &self,ConstCiphertext<DCRTPoly> ciphertext) {
     std::shared_ptr<std::vector<DCRTPoly>> precomp = self->EvalFastRotationPrecompute(ciphertext);
@@ -46,14 +39,14 @@ Ciphertext<DCRTPoly> EvalFastRotationPrecomputeWrapper(CryptoContext<DCRTPoly> &
     cipherdigitsPtr->SetElements(elements);
     return cipherdigitsPtr;
 }
-Ciphertext<DCRTPoly> EvalFastRotationWrapper(CryptoContext<DCRTPoly>& self,ConstCiphertext<DCRTPoly> ciphertext, const usint index, const usint m,ConstCiphertext<DCRTPoly> digits) {
+Ciphertext<DCRTPoly> EvalFastRotationWrapper(CryptoContext<DCRTPoly>& self,ConstCiphertext<DCRTPoly> ciphertext, uint32_t index, uint32_t m,ConstCiphertext<DCRTPoly> digits) {
     
         std::vector<DCRTPoly> digitsElements = digits->GetElements();
         std::shared_ptr<std::vector<DCRTPoly>> digitsElementsPtr = std::make_shared<std::vector<DCRTPoly>>(digitsElements);
         return self->EvalFastRotation(ciphertext, index, m, digitsElementsPtr);
     }
 
-Ciphertext<DCRTPoly> EvalFastRotationExtWrapper(CryptoContext<DCRTPoly>& self,ConstCiphertext<DCRTPoly> ciphertext, const usint index, ConstCiphertext<DCRTPoly> digits, bool addFirst) {
+Ciphertext<DCRTPoly> EvalFastRotationExtWrapper(CryptoContext<DCRTPoly>& self,ConstCiphertext<DCRTPoly> ciphertext, uint32_t index, ConstCiphertext<DCRTPoly> digits, bool addFirst) {
     std::vector<DCRTPoly> digitsElements = digits->GetElements();
     std::shared_ptr<std::vector<DCRTPoly>> digitsElementsPtr = std::make_shared<std::vector<DCRTPoly>>(digitsElements);
     return self->EvalFastRotationExt(ciphertext, index, digitsElementsPtr, addFirst);
@@ -77,32 +70,26 @@ Plaintext MultipartyDecryptFusionWrapper(CryptoContext<DCRTPoly>& self,const std
     return plaintextDecResult;
 }
 
-const std::map<usint, EvalKey<DCRTPoly>> EvalAutomorphismKeyGenWrapper(CryptoContext<DCRTPoly>& self,const PrivateKey<DCRTPoly> privateKey,const std::vector<usint> &indexList){
-    return *(self->EvalAutomorphismKeyGen(privateKey, indexList));
-}
-
-const std::shared_ptr<std::map<usint, EvalKey<DCRTPoly>>> GetEvalSumKeyMapWrapper(CryptoContext<DCRTPoly>& self,const std::string &id){
-    auto evalSumKeyMap = 
-        std::make_shared<std::map<usint, EvalKey<DCRTPoly>>>(self->GetEvalSumKeyMap(id));
-    return evalSumKeyMap;
+const std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>> GetEvalSumKeyMapWrapper(CryptoContext<DCRTPoly>& self,const std::string &keyTag){
+    return std::make_shared<std::map<uint32_t, EvalKey<DCRTPoly>>>(CryptoContextImpl<DCRTPoly>::GetEvalSumKeyMap(keyTag));;
 }
 
-const PlaintextModulus GetPlaintextModulusWrapper(CryptoContext<DCRTPoly>& self){
+PlaintextModulus GetPlaintextModulusWrapper(CryptoContext<DCRTPoly>& self){
     return self->GetCryptoParameters()->GetPlaintextModulus();
 }
 
-const double GetModulusWrapper(CryptoContext<DCRTPoly>& self){
+double GetModulusWrapper(CryptoContext<DCRTPoly>& self){
     return self->GetCryptoParameters()->GetElementParams()->GetModulus().ConvertToDouble();
 }
 
-void RemoveElementWrapper(Ciphertext<DCRTPoly> &self, usint index){
+void RemoveElementWrapper(Ciphertext<DCRTPoly> &self, uint32_t index){
     self->GetElements().erase(self->GetElements().begin()+index);
 }
-const usint GetDigitSizeWrapper(CryptoContext<DCRTPoly>& self){
+uint32_t GetDigitSizeWrapper(CryptoContext<DCRTPoly>& self){
     return self->GetCryptoParameters()->GetDigitSize();
 }
 
-const double GetScalingFactorRealWrapper(CryptoContext<DCRTPoly>& self, uint32_t l){
+double GetScalingFactorRealWrapper(CryptoContext<DCRTPoly>& self, uint32_t l){
     if(self->getSchemeId()==SCHEME::CKKSRNS_SCHEME){
         const auto cryptoParams = std::dynamic_pointer_cast<CryptoParametersCKKSRNS>(self->GetCryptoParameters());
         double scFactor = cryptoParams->GetScalingFactorReal(l);
@@ -124,7 +111,7 @@ const double GetScalingFactorRealWrapper(CryptoContext<DCRTPoly>& self, uint32_t
     }
 }
 
-const uint64_t GetModulusCKKSWrapper(CryptoContext<DCRTPoly> &self)
+uint64_t GetModulusCKKSWrapper(CryptoContext<DCRTPoly> &self)
 {
 
     const auto cryptoParams = std::dynamic_pointer_cast<CryptoParametersCKKSRNS>(self->GetCryptoParameters());
@@ -134,7 +121,7 @@ const uint64_t GetModulusCKKSWrapper(CryptoContext<DCRTPoly> &self)
     return modulus_CKKS_from;
 }
 
-const ScalingTechnique GetScalingTechniqueWrapper(CryptoContext<DCRTPoly> & self){
+ScalingTechnique GetScalingTechniqueWrapper(CryptoContext<DCRTPoly> & self){
     if(self->getSchemeId()==SCHEME::CKKSRNS_SCHEME){
         const auto cryptoParams = std::dynamic_pointer_cast<CryptoParametersCKKSRNS>(self->GetCryptoParameters());
         return cryptoParams->GetScalingTechnique();

+ 108 - 71
src/lib/pke/serialization.cpp

@@ -1,19 +1,22 @@
+//==================================================================================
 // BSD 2-Clause License
-
-// Copyright (c) 2023, OpenFHE
-
+//
+// Copyright (c) 2023-2025, Duality Technologies Inc. and other contributors
+//
 // All rights reserved.
-
+//
+// Author TPOC: contact@openfhe.org
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
-
+//
 // 1. Redistributions of source code must retain the above copyright notice, this
 //    list of conditions and the following disclaimer.
-
+//
 // 2. Redistributions in binary form must reproduce the above copyright notice,
 //    this list of conditions and the following disclaimer in the documentation
 //    and/or other materials provided with the distribution.
-
+//
 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,53 +27,50 @@
 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//==================================================================================
+#include "serialization.h"
 
-#include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
+// #include <pybind11/stl_bind.h> - not needed for now
+
 #include "openfhe.h"
-#include "bindings.h"
-#include "utils/exception.h"
 // header files needed for serialization
-#include "serialization.h"
-#include "metadata-ser.h"
 #include "ciphertext-ser.h"
 #include "cryptocontext-ser.h"
 #include "key/key-ser.h"
-#include "scheme/bfvrns/bfvrns-ser.h"
-#include "scheme/bgvrns/bgvrns-ser.h"
-#include "scheme/ckksrns/ckksrns-ser.h"
 
 using namespace lbcrypto;
 namespace py = pybind11;
 
+// disable the PYBIND11 template-based conversion for this type
+PYBIND11_MAKE_OPAQUE(std::map<uint32_t, EvalKey<DCRTPoly>>);
+
+
 template <typename ST>
-bool SerializeEvalMultKeyWrapper(const std::string &filename, const ST &sertype, std::string id)
-{
+bool SerializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype, std::string keyTag) {
     std::ofstream outfile(filename, std::ios::out | std::ios::binary);
-    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey<ST>(outfile, sertype, id);
+    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey<ST>(outfile, sertype, keyTag);
     outfile.close();
     return res;
 }
 
 template <typename ST>
-bool SerializeEvalAutomorphismKeyWrapper(const std::string& filename, const ST& sertype, std::string id)
-{
+bool SerializeEvalAutomorphismKeyWrapper(const std::string& filename, const ST& sertype, std::string keyTag) {
     std::ofstream outfile(filename, std::ios::out | std::ios::binary);
-    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<ST>(outfile, sertype, id);
+    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey<ST>(outfile, sertype, keyTag);
     outfile.close();
     return res;
 }
 
 template <typename ST>
-bool DeserializeEvalMultKeyWrapper(const std::string &filename, const ST &sertype)
-{
+bool DeserializeEvalMultKeyWrapper(const std::string& filename, const ST& sertype) {
     std::ifstream emkeys(filename, std::ios::in | std::ios::binary);
-    if (!emkeys.is_open())
-    {
+    if (!emkeys.is_open()) {
         std::cerr << "I cannot read serialization from " << filename << std::endl;
     }
     bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<ST>(emkeys, sertype);
-    return res; }
+    return res;
+}
 
 template <typename T, typename ST>
 std::tuple<T, bool> DeserializeFromFileWrapper(const std::string& filename, const ST& sertype) {
@@ -94,10 +94,14 @@ std::string SerializeToStringWrapper(const T& obj, const ST& sertype) {
 
 template <typename T, typename ST>
 py::bytes SerializeToBytesWrapper(const T& obj, const ST& sertype) {
-    std::ostringstream oss(std::ios::binary);
+    // let strbuf be dynamically allocated as we may be dealing with large keys
+    auto strbuf = std::make_unique<std::stringbuf>(std::ios::out | std::ios::binary);
+    std::ostream oss(strbuf.get());
+
     Serial::Serialize<T>(obj, oss, sertype);
-    std::string str = oss.str();
-    return py::bytes(str);
+
+    const std::string& str = strbuf->str();
+    return py::bytes(str.data(), str.size());
 }
 
 template <typename T, typename ST>
@@ -118,26 +122,28 @@ CryptoContext<DCRTPoly> DeserializeCCFromStringWrapper(const std::string& str, c
 
 template <typename T, typename ST>
 T DeserializeFromBytesWrapper(const py::bytes& bytes, const ST& sertype) {
-    T obj;
-    std::string str(bytes);
+    std::string str{static_cast<std::string>(bytes)};
     std::istringstream iss(str, std::ios::binary);
+
+    T obj;
     Serial::Deserialize<T>(obj, iss, sertype);
     return obj;
 }
 
 template <typename ST>
 CryptoContext<DCRTPoly> DeserializeCCFromBytesWrapper(const py::bytes& bytes, const ST& sertype) {
-    CryptoContext<DCRTPoly> obj;
-    std::string str(bytes);
+    std::string str{static_cast<std::string>(bytes)};
     std::istringstream iss(str, std::ios::binary);
+
+    CryptoContext<DCRTPoly> obj;
     Serial::Deserialize<DCRTPoly>(obj, iss, sertype);
     return obj;
 }
 
 template <typename ST>
-std::string SerializeEvalMultKeyToStringWrapper(const ST& sertype, const std::string& id) {
+std::string SerializeEvalMultKeyToStringWrapper(const ST& sertype, const std::string& keyTag) {
     std::ostringstream oss;
-    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey(oss, sertype, id);
+    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey(oss, sertype, keyTag);
     if (!res) {
         throw std::runtime_error("Failed to serialize EvalMultKey");
     }
@@ -145,36 +151,41 @@ std::string SerializeEvalMultKeyToStringWrapper(const ST& sertype, const std::st
 }
 
 template <typename ST>
-py::bytes SerializeEvalMultKeyToBytesWrapper(const ST& sertype, const std::string& id) {
-    std::ostringstream oss(std::ios::binary);
-    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey(oss, sertype, id);
-    if (!res) {
+py::bytes SerializeEvalMultKeyToBytesWrapper(const ST& sertype, const std::string& keyTag) {
+    // let strbuf be dynamically allocated as we may be dealing with large keys
+    auto strbuf = std::make_unique<std::stringbuf>(std::ios::out | std::ios::binary);
+    std::ostream oss(strbuf.get());
+
+    if (!CryptoContextImpl<DCRTPoly>::SerializeEvalMultKey(oss, sertype, keyTag)) {
         throw std::runtime_error("Failed to serialize EvalMultKey");
     }
-    std::string str = oss.str();
-    return py::bytes(str);
-}
 
+    const std::string& str = strbuf->str();
+    return py::bytes(str.data(), str.size());
+}
 
 template <typename ST>
-std::string SerializeEvalAutomorphismKeyToStringWrapper(const ST& sertype, const std::string& id) {
+std::string SerializeEvalAutomorphismKeyToStringWrapper(const ST& sertype, const std::string& keyTag) {
     std::ostringstream oss;
-    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey(oss, sertype, id);
+    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey(oss, sertype, keyTag);
     if (!res) {
         throw std::runtime_error("Failed to serialize EvalAutomorphismKey");
     }
     return oss.str();
 }
 
-
 template <typename ST>
-py::bytes SerializeEvalAutomorphismKeyToBytesWrapper(const ST& sertype, const std::string& id) {
-    std::ostringstream oss(std::ios::binary);
-    bool res = CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey(oss, sertype, id);
-    if (!res) {
+py::bytes SerializeEvalAutomorphismKeyToBytesWrapper(const ST& sertype, const std::string& keyTag) {
+    // let strbuf be dynamically allocated as we may be dealing with large keys
+    auto strbuf = std::make_unique<std::stringbuf>(std::ios::out | std::ios::binary);
+    std::ostream oss(strbuf.get());
+
+    if (!CryptoContextImpl<DCRTPoly>::SerializeEvalAutomorphismKey(oss, sertype, keyTag)) {
         throw std::runtime_error("Failed to serialize EvalAutomorphismKey");
     }
-    return oss.str();
+
+    const std::string& str = strbuf->str();
+    return py::bytes(str.data(), str.size());
 }
 
 template <typename ST>
@@ -187,11 +198,11 @@ void DeserializeEvalMultKeyFromStringWrapper(const std::string& data, const ST&
 }
 
 template <typename ST>
-void DeserializeEvalMultKeyFromBytesWrapper(const std::string& data, const ST& sertype) {
-    std::string str(data);
+void DeserializeEvalMultKeyFromBytesWrapper(const py::bytes& bytes, const ST& sertype) {
+    std::string str{static_cast<std::string>(bytes)};
     std::istringstream iss(str, std::ios::binary);
-    bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<ST>(iss, sertype);
-    if (!res) {
+
+    if (!CryptoContextImpl<DCRTPoly>::DeserializeEvalMultKey<ST>(iss, sertype)) {
         throw std::runtime_error("Failed to deserialize EvalMultKey");
     }
 }
@@ -199,7 +210,7 @@ void DeserializeEvalMultKeyFromBytesWrapper(const std::string& data, const ST& s
 template <typename ST>
 void DeserializeEvalAutomorphismKeyFromStringWrapper(const std::string& data, const ST& sertype) {
     std::istringstream iss(data);
-    std::map<std::string, std::shared_ptr<std::map<usint, EvalKey<DCRTPoly>>>> keyMap;
+    std::map<std::string, std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>> keyMap;
     bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<ST>(iss, sertype);
     if (!res) {
         throw std::runtime_error("Failed to deserialize EvalAutomorphismKey");
@@ -207,11 +218,11 @@ void DeserializeEvalAutomorphismKeyFromStringWrapper(const std::string& data, co
 }
 
 template <typename ST>
-void DeserializeEvalAutomorphismKeyFromBytesWrapper(const std::string& data, const ST& sertype) {
-    std::string str(data);
+void DeserializeEvalAutomorphismKeyFromBytesWrapper(const py::bytes& bytes, const ST& sertype) {
+    std::string str{static_cast<std::string>(bytes)};
     std::istringstream iss(str, std::ios::binary);
-    bool res = CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<ST>(iss, sertype);
-    if (!res) {
+
+    if (!CryptoContextImpl<DCRTPoly>::DeserializeEvalAutomorphismKey<ST>(iss, sertype)) {
         throw std::runtime_error("Failed to deserialize EvalAutomorphismKey");
     }
 }
@@ -238,6 +249,10 @@ void bind_serialization(pybind11::module &m) {
           py::arg("filename"), py::arg("obj"), py::arg("sertype"));
     m.def("DeserializeEvalKey", static_cast<std::tuple<EvalKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<EvalKey<DCRTPoly>, SerType::SERJSON>),
           py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>&, const SerType::SERJSON&)>(&Serial::SerializeToFile<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeEvalKeyMap", static_cast<std::tuple<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, bool> (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeFromFileWrapper<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, SerType::SERJSON>),
+          py::arg("filename"), py::arg("sertype"));
 
     // JSON Serialization to string
     m.def("Serialize", &SerializeToStringWrapper<CryptoContext<DCRTPoly>, SerType::SERJSON>,
@@ -260,14 +275,21 @@ void bind_serialization(pybind11::module &m) {
           py::arg("obj"), py::arg("sertype"));
     m.def("DeserializeEvalKeyString", &DeserializeFromStringWrapper<EvalKey<DCRTPoly>, SerType::SERJSON>,
           py::arg("str"), py::arg("sertype"));
+    m.def("Serialize", &SerializeToBytesWrapper<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, SerType::SERJSON>,
+          py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeEvalKeyMapString", &DeserializeFromBytesWrapper<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, SerType::SERJSON>,
+          py::arg("str"), py::arg("sertype"));
+
     m.def("SerializeEvalMultKeyString", &SerializeEvalMultKeyToStringWrapper<SerType::SERJSON>,
-          py::arg("sertype"), py::arg("id") = "");
-    m.def("DeserializeEvalMultKeyString", &DeserializeEvalMultKeyFromStringWrapper<SerType::SERJSON>,
-          py::arg("sertype"), py::arg("id") = "");
+          py::arg("sertype"), py::arg("keyTag") = "");
+    m.def("DeserializeEvalMultKeyString",
+          static_cast<void (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeEvalMultKeyFromStringWrapper<SerType::SERJSON>),
+          py::arg("data"), py::arg("sertype"));
     m.def("SerializeEvalAutomorphismKeyString", &SerializeEvalAutomorphismKeyToStringWrapper<SerType::SERJSON>,
-          py::arg("sertype"), py::arg("id") = "");
-    m.def("DeserializeEvalAutomorphismKeyString", &DeserializeEvalAutomorphismKeyFromStringWrapper<SerType::SERJSON>,
-          py::arg("sertype"), py::arg("id") = "");
+          py::arg("sertype"), py::arg("keyTag") = "");
+    m.def("DeserializeEvalAutomorphismKeyString",
+          static_cast<void (*)(const std::string&, const SerType::SERJSON&)>(&DeserializeEvalAutomorphismKeyFromStringWrapper<SerType::SERJSON>),
+          py::arg("data"), py::arg("sertype"));
 
     // Binary Serialization
     m.def("SerializeToFile", static_cast<bool (*)(const std::string&,const CryptoContext<DCRTPoly>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<DCRTPoly>),
@@ -290,6 +312,10 @@ void bind_serialization(pybind11::module &m) {
           py::arg("filename"), py::arg("obj"), py::arg("sertype"));
     m.def("DeserializeEvalKey", static_cast<std::tuple<EvalKey<DCRTPoly>,bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<EvalKey<DCRTPoly>, SerType::SERBINARY>),
           py::arg("filename"), py::arg("sertype"));
+    m.def("SerializeToFile", static_cast<bool (*)(const std::string&, const std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>&, const SerType::SERBINARY&)>(&Serial::SerializeToFile<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>>),
+          py::arg("filename"), py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeEvalKeyMap", static_cast<std::tuple<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, bool> (*)(const std::string&, const SerType::SERBINARY&)>(&DeserializeFromFileWrapper<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, SerType::SERBINARY>),
+          py::arg("filename"), py::arg("sertype"));
 
     // Binary Serialization to bytes
     m.def("Serialize", &SerializeToBytesWrapper<CryptoContext<DCRTPoly>, SerType::SERBINARY>,
@@ -312,12 +338,23 @@ void bind_serialization(pybind11::module &m) {
           py::arg("obj"), py::arg("sertype"));
     m.def("DeserializeEvalKeyString", &DeserializeFromBytesWrapper<EvalKey<DCRTPoly>, SerType::SERBINARY>,
           py::arg("str"), py::arg("sertype"));
+    m.def("Serialize", &SerializeToBytesWrapper<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, SerType::SERBINARY>,
+          py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeEvalKeyMapString", &DeserializeFromBytesWrapper<std::shared_ptr<std::map<uint32_t, EvalKey<DCRTPoly>>>, SerType::SERBINARY>,
+          py::arg("str"), py::arg("sertype"));
+    m.def("Serialize", &SerializeToBytesWrapper<std::vector<EvalKey<DCRTPoly>>, SerType::SERBINARY>,
+          py::arg("obj"), py::arg("sertype"));
+    m.def("DeserializeEvalKeyMapVectorString", &DeserializeFromBytesWrapper<std::vector<EvalKey<DCRTPoly>>, SerType::SERBINARY>,
+          py::arg("str"), py::arg("sertype"));
+
     m.def("SerializeEvalMultKeyString", &SerializeEvalMultKeyToBytesWrapper<SerType::SERBINARY>,
-          py::arg("sertype"), py::arg("id") = "");
-    m.def("DeserializeEvalMultKeyString", &DeserializeEvalMultKeyFromBytesWrapper<SerType::SERBINARY>,
-          py::arg("sertype"), py::arg("id") = "");
+          py::arg("sertype"), py::arg("keyTag") = "");
+    m.def("DeserializeEvalMultKeyString",
+          static_cast<void (*)(const py::bytes&, const SerType::SERBINARY&)>(&DeserializeEvalMultKeyFromBytesWrapper<SerType::SERBINARY>),
+          py::arg("bytes"), py::arg("sertype"));
     m.def("SerializeEvalAutomorphismKeyString", &SerializeEvalAutomorphismKeyToBytesWrapper<SerType::SERBINARY>,
-          py::arg("sertype"), py::arg("id") = "");
-    m.def("DeserializeEvalAutomorphismKeyString", &DeserializeEvalAutomorphismKeyFromBytesWrapper<SerType::SERBINARY>,
-          py::arg("sertype"), py::arg("id") = "");
+          py::arg("sertype"), py::arg("keyTag") = "");
+    m.def("DeserializeEvalAutomorphismKeyString",
+          static_cast<void (*)(const py::bytes&, const SerType::SERBINARY&)>(&DeserializeEvalAutomorphismKeyFromBytesWrapper<SerType::SERBINARY>),
+          py::arg("bytes"), py::arg("sertype"));
 }