Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ project (OpenFHE C CXX)

set(OPENFHE_VERSION_MAJOR 1)
set(OPENFHE_VERSION_MINOR 6)
set(OPENFHE_VERSION_PATCH 0)
set(OPENFHE_VERSION_PATCH 1)
set(OPENFHE_VERSION ${OPENFHE_VERSION_MAJOR}.${OPENFHE_VERSION_MINOR}.${OPENFHE_VERSION_PATCH})

set(CMAKE_CXX_STANDARD 17)
Expand Down
6 changes: 6 additions & 0 deletions docs/static_docs/Release_Notes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
10/09/2026: OpenFHE 1.6.1 (stable) is released

* Fixes decryption failures after CKKS bootstrapping with uniform ternary secrets for affected scenarios (#1364)

The detailed list of changes is available at https://github.com/openfheorg/openfhe-development/issues?q=is%3Aissue+milestone%3A%22Release+1.6.1%22

09/28/2026: OpenFHE 1.6.0 (development) is released

* Adds the CKKS-based Fourier-extension functional bootstrapping method proposed in https://ia.cr/2026/367 and presented at EUROCRYPT '26 (#1207)
Expand Down
41 changes: 41 additions & 0 deletions src/pke/include/scheme/ckksrns/ckksrns-fhe.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
*/
namespace lbcrypto {

class CryptoParametersCKKSRNS;

/**
* @brief Precomputations of CKKS bootstrapping for one number of slots.
*
Expand Down Expand Up @@ -111,6 +113,13 @@ class CKKSBootstrapPrecom {
/// flag indicating whether we perform StC before ModRaise
bool BTSlotsEncoding;

// which setup populated this precomputation. Each bootstrapping variant folds its own uniform-secret overflow bound
// K (K_UNIFORM, K_UNIFORM_FBT or K_UNIFORM_FEFBT) into the CoeffsToSlots matrix, so a precomputation generated by
// one variant cannot be consumed by another. Not serialized: only the parameters are serialized, and the setup call
// that rebuilds the matrices after deserialization restores the variant together with them.
enum BootstrapVariant : uint32_t { BOOTSTRAP = 0, FBT = 1, FEFBT = 2 };
BootstrapVariant m_variant = BOOTSTRAP;

template <class Archive>
void save(Archive& ar) const {
ar(cereal::make_nvp("dim1_Enc", m_paramsEnc.g));
Expand Down Expand Up @@ -998,6 +1007,21 @@ class FHECKKSRNS : public FHERNS {
OPENFHE_THROW("Precomputations for " + std::to_string(slots) + " slots not found.");
}

// The bootstrapping variants fold different uniform-secret overflow bounds K into the
// CoeffsToSlots matrix (K_UNIFORM, K_UNIFORM_FBT, K_UNIFORM_FEFBT), so a precomputation can
// only be consumed by the variant whose setup generated it.
CKKSBootstrapPrecom& GetBootPrecom(uint32_t slots, CKKSBootstrapPrecom::BootstrapVariant variant) const {
auto& precom = GetBootPrecom(slots);
if (precom.m_variant != variant) {
constexpr const char* setupName[] = {"EvalBootstrapSetup", "EvalFBTSetup", "EvalFEFuncBootstrapSetup"};
OPENFHE_THROW("The bootstrapping precomputation for " + std::to_string(slots) + " slots was generated by " +
setupName[precom.m_variant] + ", but this operation requires " + setupName[variant] +
": regular, functional and FE functional bootstrapping fold different overflow bounds K "
"into the CoeffsToSlots matrix and cannot share precomputations.");
}
return precom;
}

//------------------------------------------------------------------------------
// Find Rotation Indices
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -1127,6 +1151,23 @@ class FHECKKSRNS : public FHERNS {
static constexpr uint32_t K_UNIFORM = 648;
static constexpr uint32_t K_UNIFORM_FBT = 672;
static constexpr uint32_t K_UNIFORM_FEFBT = 696;

/**
* Returns the mod-raise overflow bound K for the secret key distribution of cryptoParams. Every setup
* folds K into the CoeffsToSlots matrix (the scaleEnc factor): the matrix coefficients carry 1/K at
* full precision, whereas the runtime scalar 2^-deg/(K*N) would be truncated to
* log2(scalingFactor) - log2(K*N) - deg bits when encoded at the scaling factor (about 19 bits for a
* 50-bit scaling factor and a 60-bit first modulus at N = 2^12, and 4 bits fewer at N = 2^16), an
* error that the overflow I (up to K) and the correction factor then amplify. Folding also keeps the
* CtS rotations acting on the full-magnitude message, so their key-switching noise is not amplified.
*
* @param cryptoParams the CKKS crypto parameters
* @param uniformK the bound for UNIFORM_TERNARY, specific to the bootstrapping variant: K_UNIFORM for
* regular, K_UNIFORM_FBT for functional and K_UNIFORM_FEFBT for FE functional bootstrapping
* @return the overflow bound K
*/
static double GetModRaiseOverflowBound(const std::shared_ptr<CryptoParametersCKKSRNS>& cryptoParams,
double uniformK);
// number of double-angle iterations in CKKS bootstrapping. Must be static because it is used in a static function.
static constexpr uint32_t R_UNIFORM = 6;
// number of double-angle iterations in CKKS bootstrapping. Must be static because it is used in a static function.
Expand Down
Loading