in pir_client.cpp [80:135]
Plaintext PIRClient::decode_reply(PirReply reply) {
uint32_t exp_ratio = pir_params_.expansion_ratio;
uint32_t recursion_level = pir_params_.d;
vector<Ciphertext> temp = reply;
uint64_t t = params_.plain_modulus().value();
for (uint32_t i = 0; i < recursion_level; i++) {
cout << "Client: " << i + 1 << "/ " << recursion_level << "-th decryption layer started." << endl;
vector<Ciphertext> newtemp;
vector<Plaintext> tempplain;
for (uint32_t j = 0; j < temp.size(); j++) {
Plaintext ptxt;
decryptor_->decrypt(temp[j], ptxt);
#ifdef DEBUG
cout << "Client: reply noise budget = " << decryptor_->invariant_noise_budget(temp[j]) << endl;
#endif
// multiply by inverse_scale for every coefficient of ptxt
for(int h = 0; h < ptxt.coeff_count(); h++){
ptxt[h] *= inverse_scales_[recursion_level - 1 - i];
ptxt[h] %= t;
}
//cout << "decoded (and scaled) plaintext = " << ptxt.to_string() << endl;
tempplain.push_back(ptxt);
#ifdef DEBUG
cout << "recursion level : " << i << " noise budget : ";
cout << decryptor_->invariant_noise_budget(temp[j]) << endl;
#endif
if ((j + 1) % exp_ratio == 0 && j > 0) {
// Combine into one ciphertext.
Ciphertext combined = compose_to_ciphertext(tempplain);
newtemp.push_back(combined);
tempplain.clear();
// cout << "Client: const term of ciphertext = " << combined[0] << endl;
}
}
cout << "Client: done." << endl;
cout << endl;
if (i == recursion_level - 1) {
assert(temp.size() == 1);
return tempplain[0];
} else {
tempplain.clear();
temp = newtemp;
}
}
// This should never be called
assert(0);
Plaintext fail;
return fail;
}