I have working code for my project. Now I’m trying to change the architecture to multiparty scenario where I define on high level the number of parties.
Therefore, I took the code from src/pke/examples/tckks-interactive-mp-bootstrapping-Chebyshev.cpp and changed it in a way that the number of parties is flexible.
For some calculations it does work as expected, but especially for more complex calculations I’m getting an “approximation error too high”
Woud you please double-check my code?
std::cout << "Key generation for " << numparties << " parties started." << std::endl;
numParties = numparties;
for (int i = 0; i < numparties; i++) {
Party party;
party.id = i;
if (0 == i)
party.kpShard = cryptoContext->KeyGen();
else
party.kpShard = cryptoContext->MultipartyKeyGen(parties[i-1].kpShard.publicKey);
parties.push_back(party);
}
std::cout << "Joint public key for (s_0 + s_1 + ... + s_n) is generated..." << std::endl;
// Assert everything is good
for (int i = 0; i < numparties; i++) {
if (!parties[i].kpShard.good()) {
std::cout << "Key generation failed for party " << i << "!" << std::endl;
exit(1);
}
}
////////////////////////////////////////////////////////////
// Perform Key Generation Operation
////////////////////////////////////////////////////////////
// Generate evalmult key part
std::cout << "EvalMultKey generation started." << std::endl;
std::vector<EvalKey<DCRTPoly>> EvalMultKeyTemp;
EvalKey<DCRTPoly> evalMultKeyFinal;
for(int i = 0; i<numparties; i++)
{
if(i==0){
EvalMultKeyTemp.push_back(cryptoContext->KeySwitchGen(parties[i].kpShard.secretKey, parties[i].kpShard.secretKey));
}
else{
auto EvalMultKeyi = cryptoContext->MultiKeySwitchGen(parties[i].kpShard.secretKey, parties[i].kpShard.secretKey, EvalMultKeyTemp[0]);
EvalMultKeyTemp.push_back(cryptoContext->MultiAddEvalKeys(EvalMultKeyTemp[i-1], EvalMultKeyi, parties[i].kpShard.publicKey->GetKeyTag()));
std::vector<EvalKey<DCRTPoly>> EvalMultKeyAdd;
for(int j=0; j< numparties; j++){
EvalMultKeyAdd.push_back(cryptoContext->MultiMultEvalKey(parties[j].kpShard.secretKey, EvalMultKeyTemp[i], parties[i].kpShard.publicKey->GetKeyTag()));
}
evalMultKeyFinal = cryptoContext->MultiAddEvalMultKeys(EvalMultKeyAdd[0], EvalMultKeyAdd[1], EvalMultKeyAdd[0]->GetKeyTag());
for(int j=2; j<numparties; j++){
evalMultKeyFinal = cryptoContext->MultiAddEvalMultKeys(evalMultKeyFinal, EvalMultKeyAdd[j], EvalMultKeyAdd[j]->GetKeyTag());
}
}
}
cryptoContext->InsertEvalMultKey({evalMultKeyFinal});
std::cout << "EvalSumKey generation started." << std::endl;
// Generate evalsum key part for first party
cryptoContext->EvalSumKeyGen(parties[0].kpShard.secretKey);
auto evalSumKeys =
std::make_shared<std::map<usint, EvalKey<DCRTPoly>>>(cryptoContext->GetEvalSumKeyMap(parties[0].kpShard.secretKey->GetKeyTag()));
std::shared_ptr<std::map<usint, lbcrypto::EvalKey<lbcrypto::DCRTPoly>>> evalSumkKeysJoin;
for (int i = 1; i < numparties; i++) {
auto evalSumkKeysPartyi = cryptoContext->MultiEvalSumKeyGen(parties[i].kpShard.secretKey, evalSumKeys, parties[i].kpShard.publicKey->GetKeyTag());
if(i==1){
evalSumkKeysJoin = cryptoContext->MultiAddEvalSumKeys(evalSumKeys, evalSumkKeysPartyi, parties[i].kpShard.publicKey->GetKeyTag());
}
else{
evalSumkKeysJoin = cryptoContext->MultiAddEvalSumKeys(evalSumkKeysJoin, evalSumkKeysPartyi, parties[i].kpShard.publicKey->GetKeyTag());
}
cryptoContext->InsertEvalSumKey(evalSumkKeysJoin);
}