Hi all,
I’m trying to test the EvalSign()
function after performing scheme switching from CKKS to FHEW.
However, I get the following error message:
terminate called after throwing an instance of 'lbcrypto::openfhe_error'
what(): /home/clemens/Documents/openfhe-development/src/binfhe/lib/binfhe-base-scheme.cpp:373 ERROR: No key [262144] found in the map
Aborted (core dumped)
I noticed that ccLWE.GetBTKeyMap()->size()
is 0, so it appears to me that there are actually no bootstrapping keys after the scheme switching. Is this to be expected?
Could you please help me troubleshoot this further?
Also, is there a working example for executing EvalSign
after scheme switching? I can only find either scheme switching examples where different functions are evaluated, or EvalSign
examples that do not use scheme switching.
Thank you very much!
I used the code below. The code was originally taken from the ArgminViaSchemeSwitching()
function that is part of the scheme-switching.cpp
example and then adjusted.
#include "openfhe.h"
#include "binfhecontext.h"
using namespace lbcrypto;
int main() {
std::cout << "\n-----Sign Evaluation through Scheme Switching Test-----\n" << std::endl;
// Step 1: Setup CryptoContext for CKKS
uint32_t scaleModSize = 50;
uint32_t firstModSize = 60;
uint32_t ringDim = 8192;
SecurityLevel sl = HEStd_NotSet;
BINFHE_PARAMSET slBin = TOY;
uint32_t logQ_ccLWE = 25;
bool arbFunc = false;
bool oneHot = true; // Change to false if the output should not be one-hot encoded
uint32_t slots = 16; // sparsely-packed
uint32_t batchSize = slots;
uint32_t numValues = 16;
ScalingTechnique scTech = FIXEDMANUAL;
uint32_t multDepth =
9 + 3 + 1 + static_cast < int > (std::log2(numValues)); // 13 for FHEW to CKKS, log2(numValues) for argmin
if (scTech == FLEXIBLEAUTOEXT)
multDepth += 1;
CCParams < CryptoContextCKKSRNS > parameters;
parameters.SetMultiplicativeDepth(multDepth);
parameters.SetScalingModSize(scaleModSize);
parameters.SetFirstModSize(firstModSize);
parameters.SetScalingTechnique(scTech);
parameters.SetSecurityLevel(sl);
parameters.SetRingDim(ringDim);
parameters.SetBatchSize(batchSize);
CryptoContext < DCRTPoly > cc = GenCryptoContext(parameters);
// Enable the features that you wish to use
cc -> Enable(PKE);
cc -> Enable(KEYSWITCH);
cc -> Enable(LEVELEDSHE);
cc -> Enable(ADVANCEDSHE);
cc -> Enable(SCHEMESWITCH);
std::cout << "CKKS scheme is using ring dimension " << cc -> GetRingDimension();
std::cout << ", and number of slots " << slots << ", and supports a depth of " << multDepth << std::endl <<
std::endl;
// Generate encryption keys
auto keys = cc -> KeyGen();
// Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
auto FHEWparams = cc -> EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, false, slots);
auto ccLWE = FHEWparams.first;
auto privateKeyFHEW = FHEWparams.second;
const auto cryptoParams = std::dynamic_pointer_cast < CryptoParametersCKKSRNS > (cc -> GetCryptoParameters());
cc -> EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, numValues, oneHot);
std::cout << "FHEW scheme is using lattice parameter " << ccLWE.GetParams() -> GetLWEParams() -> Getn();
std::cout << ", logQ " << logQ_ccLWE;
std::cout << ", and modulus q " << ccLWE.GetParams() -> GetLWEParams() -> Getq() << std::endl << std::endl;
// Scale the inputs to ensure their difference is correctly represented after switching to FHEW
double scaleSign = 512.0;
auto modulus_LWE = 1 << logQ_ccLWE;
auto beta = ccLWE.GetBeta().ConvertToInt();
auto pLWE = modulus_LWE / (2 * beta); // Large precision
uint32_t init_level = 0;
//const auto cryptoParams = std::dynamic_pointer_cast<CryptoParametersCKKSRNS>(cc->GetCryptoParameters());
if (cryptoParams -> GetScalingTechnique() == FLEXIBLEAUTOEXT)
init_level = 1;
// This formulation is for clarity
cc -> EvalCompareSwitchPrecompute(pLWE, init_level, scaleSign);
// Step 3: Encoding and encryption of inputs
// Inputs
std::vector<double> x1 = {-1.125, -1.12, 5.0, 6.0, -1.0, 2.0, 8.0, -1.0,
9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.25, 15.30};
// Encoding as plaintexts
Plaintext ptxt1 = cc -> MakeCKKSPackedPlaintext(x1);
// Encrypt the encoded vectors
auto c1 = cc -> Encrypt(keys.publicKey, ptxt1);
// Transform the ciphertext from CKKS to FHEW
auto cTemp = cc -> EvalCKKStoFHEW(c1, numValues);
std::cout << "BT Keymap Size: " << ccLWE.GetBTKeyMap()->size();
std::vector < LWECiphertext > LWESign(numValues);
for (uint32_t j = 0; j < numValues; j++) {
LWESign[j] = ccLWE.EvalSign(cTemp[j], true);
std::cout << "--> " << LWESign[j] << std::endl;
}
return 0;
}