It is unclear to me how the hypercube expansion works exactly. For example, with
uint64_t number_of_items = 1 << 16;
uint64_t size_per_item = 12*4096/8; // in bytes
uint32_t N = 4096;
// Recommended values: (logt, d) = (12, 2) or (8, 1).
uint32_t logt = 12;
uint32_t d = 2;
The loop to expand the query into a hypercube in the generate_reply function:
for (uint32_t i = 0; i < nvec.size(); i++) {
vector<Ciphertext> expanded_query;
auto time_server_s = high_resolution_clock::now();
uint64_t n_i = nvec[i];
for (uint32_t j = 0; j < query[i].size(); j++){
uint64_t total = N;
if (j == query[i].size() - 1){
total = n_i % N;
}
vector<Ciphertext> expanded_query_part = expand_query(query[i][j], total, client_id);
expanded_query.insert( expanded_query.end(),
std::make_move_iterator(expanded_query_part.begin()),
std::make_move_iterator(expanded_query_part.end()));
expanded_query_part.clear();
}
This loop produces 256 polynomials with 256 non-zero cipherthext coefficients each; granted all but one encrypt the plain text value of 0. The loop that does the Homomorphic selection is the following:
for (uint64_t k = 0; k < product; k++) {
evaluator_->multiply_plain(expanded_query[0], (*cur)[k], intermediateCtxts[k]);
for (uint64_t j = 1; j < n_i; j++) {
evaluator_->multiply_plain(expanded_query[j], (*cur)[k + j * product], temp);
evaluator_->add_inplace(intermediateCtxts[k], temp); // Adds to first component.
}
}
Here is my confusion: it is my understanding that each coefficient of every polynomial should, by themselves, be multiplied by the (k+j product)-th element of the database, and then accumulated using addition into a single value. This is not what happens, instead all 256 polynomials get multiplied 256 times each, where polynomial k multiplies with entry 256n+k for all n up to 0< n < 256. How is this selecting one entry in the database? Where each entry takes up the entire ciphertext space for one polynomial with 4096 coefficients and 12-bits available in each one(total of 6144 bytes).
Also, on the second round of the loop, since "nvec.size = 2" we have n_i = 256 but product = 10? I do not understand this at all. Any comments on the matter would be greatly appreciated.
It is unclear to me how the hypercube expansion works exactly. For example, with
The loop to expand the query into a hypercube in the generate_reply function:
This loop produces 256 polynomials with 256 non-zero cipherthext coefficients each; granted all but one encrypt the plain text value of 0. The loop that does the Homomorphic selection is the following:
Here is my confusion: it is my understanding that each coefficient of every polynomial should, by themselves, be multiplied by the (k+j product)-th element of the database, and then accumulated using addition into a single value. This is not what happens, instead all 256 polynomials get multiplied 256 times each, where polynomial k multiplies with entry 256n+k for all n up to 0< n < 256. How is this selecting one entry in the database? Where each entry takes up the entire ciphertext space for one polynomial with 4096 coefficients and 12-bits available in each one(total of 6144 bytes).
Also, on the second round of the loop, since "nvec.size = 2" we have n_i = 256 but product = 10? I do not understand this at all. Any comments on the matter would be greatly appreciated.