Percy++
A C++ implementation of Private Information Retrieval (PIR) protocols
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
itclient_impl.h
1 // Percy++ Copyright 2007,2012,2013,2014
2 // Ian Goldberg <iang@cs.uwaterloo.ca>,
3 // Casey Devet <cjdevet@uwaterloo.ca>,
4 // Ann Yang <y242yang@uwaterloo.ca>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of version 2 of the GNU General Public License as
8 // published by the Free Software Foundation.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // There is a copy of the GNU General Public License in the COPYING file
16 // packaged with this plugin; if you cannot find it, write to the Free
17 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 
20 #ifndef __ITCLIENT_IMPL_H__
21 #define __ITCLIENT_IMPL_H__
22 
23 #include <iostream>
24 #include <algorithm>
25 #include <utility>
26 #include "gf2e.h"
27 #include "itparams.h"
28 #include "percyresult.h"
29 #include "rsdecoder.h"
30 
31 template <typename GF2E_Element>
32 inline void setCoeffs(GF2X &GF2X_P);
33 
34 template <>
35 inline void setCoeffs<GF28_Element>(GF2X &GF2X_P) {
36  SetCoeff(GF2X_P, 8, 1);
37  SetCoeff(GF2X_P, 4, 1);
38  SetCoeff(GF2X_P, 3, 1);
39  SetCoeff(GF2X_P, 1, 1);
40  SetCoeff(GF2X_P, 0, 1);
41 }
42 
43 template <>
44 inline void setCoeffs<GF216_Element>(GF2X &GF2X_P) {
45  SetCoeff(GF2X_P, 16, 1);
46  SetCoeff(GF2X_P, 14, 1);
47  SetCoeff(GF2X_P, 12, 1);
48  SetCoeff(GF2X_P, 7, 1);
49  SetCoeff(GF2X_P, 6, 1);
50  SetCoeff(GF2X_P, 4, 1);
51  SetCoeff(GF2X_P, 2, 1);
52  SetCoeff(GF2X_P, 1, 1);
53  SetCoeff(GF2X_P, 0, 1);
54 }
55 
56 // Constructor and destructor
57 template <typename GF2E_Element>
59  nservers_t num_servers, nservers_t t, sid_t * sids, PercyStats * stats) :
60  PercyClient(params, num_servers, t, stats),
61  params(static_cast<const GF2EParams*>(params->percy_params())),
62  indices(),
63  interp_indices(),
64  vec_interp_indices(),
65  vecs_interp_indices(),
66  randmults(),
67  answers(),
68  unfinished_results(),
69  decoded()
70 {
71  // Initialize the GF2E modulus
72  GF2X MODULUS_P;
73  setCoeffs<GF2E_Element>(MODULUS_P);
74 
75  GF2E::init(MODULUS_P);
76  GF2X::HexOutput = 1;
77 
78  choose_indices(sids);
79  nqueries_t max_qbs = num_servers - 1 - this->params->tau();
80  choose_interp_indices(max_qbs);
81 }
82 
83 template <typename GF2E_Element>
85 {
86  if (indices != NULL) {
87  delete[] indices;
88  }
89  if (interp_indices != NULL) {
90  delete[] interp_indices;
91  }
92  while (answers.size() > 0) {
93  if (answers.back() != NULL) {
94  delete[] answers.back();
95  }
96  answers.pop_back();
97  }
98  typename map<nqueries_t, GF2E_Element *>::iterator siter;
99  for (siter = stored_shares.begin(); siter != stored_shares.end(); ++siter) {
100  delete[] siter->second;
101  }
102  stored_shares.clear();
103 }
104 
105 
106 // Generate t-private (t+1)-of-l shares of a given secret value.
107 template <typename GF2E_Element>
108 static void genshares_GF2E(nservers_t t, nservers_t l,
109  const GF2E_Element *indices, GF2E_Element *values, GF2E_Element secret)
110 {
111  // Pick a random polynomial of degree t with the right constant term
112  GF2E_Element * coeffs = new GF2E_Element[t+1];
113  coeffs[0] = secret;
114  for (nservers_t i=1;i<=t;++i) {
115  coeffs[i] = RandomBits_ulong(8*sizeof(GF2E_Element));
116  }
117 
118  // Evaluate the polynomial at each of the indices
119  for (nservers_t i=0; i<l; ++i) {
120  values[i] = evalpoly_GF2E<GF2E_Element>(coeffs, t, indices[i]);
121  }
122  delete[] coeffs;
123 }
124 
125 #ifdef VERBOSE_ITCLIENT
126 template <typename GF2E_Element>
127 static void showpoly(const char *label, const GF2E_Element *poly,
128  nqueries_t numcoeffs)
129 {
130  if (label) {
131  fprintf(stderr, "%s", label);
132  }
133  fprintf(stderr, "[ ");
134  for (nqueries_t i = 0; i < numcoeffs; ++i) {
135  fprintf(stderr, "%02x ", poly[i]);
136  }
137  fprintf(stderr, "]\n");
138 }
139 #endif
140 
141 // Generate t-private (t+1)-of-l shares of a given secret value.
142 template <typename GF2E_Element>
143 static void gensharesmulti_GF2E(nservers_t t, nservers_t l,
144  const GF2E_Element *indices, GF2E_Element *values,
145  const GF2E_Element* secret, const GF2E_Element *interp_indices,
146  nqueries_t qbs)
147 {
148  // Special case for t=0 so we don't have to worry about polynomials
149  // with degree < 0
150  if (t==0) {
151  for (nservers_t i=0; i<l; ++i) {
152  values[i] = interpolate_GF2E(interp_indices, secret, qbs,
153  indices[i]);
154  }
155  return;
156  }
157 
158  // Pick a random polynomial of degree t-1
159  GF2E_Element * randpoly = new GF2E_Element[t];
160  for (nservers_t i=0; i<t; ++i) {
161  randpoly[i] = RandomBits_ulong(8*sizeof(GF2E_Element));
162  }
163 
164  GF2E_Element * buildroots = new GF2E_Element[qbs+1];
165  polyfromroots_GF2E(buildroots, interp_indices, qbs);
166  GF2E_Element * final = new GF2E_Element[t+qbs];
167  multpoly_GF2E(final, randpoly, t-1, buildroots, qbs);
168 
169  // Evaluate the polynomial at each of the indices
170  for (nservers_t i=0; i<l; ++i) {
171  values[i] = evalpoly_GF2E<GF2E_Element>(final, t+qbs-1, indices[i]) ^
172  interpolate_GF2E(interp_indices, secret, qbs,
173  indices[i]);
174  }
175  delete[] randpoly;
176  delete[] buildroots;
177  delete[] final;
178 }
179 
180 template <typename GF2E_Element>
182  indices = new GF2E_Element[num_servers];
183  for (nservers_t j=0; j<num_servers; ++j) {
184  if (params->tau()) {
185  // Use the indices provided
186  indices[j] = (GF2E_Element)sids[j];
187  } else {
188  // Use random indices
189  GF2E_Element r;
190  bool ok = false;
191  do {
192  r = RandomLen_long(8*sizeof(GF2E_Element));
193  if (r != 0) {
194  ok = true;
195  for (nservers_t k=0;k<j;++k) {
196  if (indices[k] == r) {
197  ok = false;
198  }
199  }
200  }
201  } while (!ok);
202  indices[j] = r;
203  }
204  }
205 
206  // Create NTL version
207  indices_ntl.SetLength(num_servers);
208  for (nservers_t ix=0; ix<num_servers; ++ix) {
209  conv(indices_ntl[ix],
210  GF2XFromBytes((unsigned char *)(indices + ix),
211  sizeof(GF2E_Element)));
212  }
213 }
214 
215 
216 template <typename GF2E_Element>
218  vec_interp_indices.SetLength(qbs);
219  interp_indices = new GF2E_Element[qbs];
220  GF2E_Element candidate = 0x00;
221  nqueries_t i = 0;
222  while (i < qbs){
223  bool in_server_indices = false;
224  for (nservers_t s=0; s<num_servers; s++){
225  if (indices[s] == candidate){
226  in_server_indices = true;
227  }
228  }
229  if (!in_server_indices) {
230  interp_indices[i] = candidate;
231  conv(vec_interp_indices[i],
232  GF2XFromBytes((unsigned char *)(interp_indices + i),
233  sizeof(GF2E_Element)));
234  ++i;
235  }
236  --candidate;
237  }
238 }
239 
240 // Send a request for the given block number (0-based) to the
241 // servers connected with the ostreams in the given vector.
242 template <typename GF2E_Element>
244  nqueries_t request_identifier)
245 {
246  const vector<dbsize_t>& block_numbers = get_block_numbers(request_identifier);
247  nqueries_t qbs = get_qbs(request_identifier);
248  nqueries_t num_block_requests = block_numbers.size();
249  nqueries_t num_queries = (num_block_requests+qbs-1)/qbs;
250  // Generate random multiples (!= 0)
251  if (randomize) {
252  randmults[request_identifier] = vector<GF2E_Element>();
253  vector<GF2E_Element>& request_randmults = randmults[request_identifier];
254  for (nqueries_t i = 0; i < num_queries * num_servers; ++i) {
255  GF2E_Element r = 0;
256  while (r == 0) {
257  r = RandomLen_long(8*sizeof(GF2E_Element));
258  }
259  request_randmults.push_back(r);
260  }
261  }
262 
263  // Construct the shares of the e_{index} vector
264  dbsize_t num_virtual_blocks = params->num_virtual_blocks();
265  dbsize_t virtual_block_size = params->virtual_block_size();
266  GF2E_Element * shares = new GF2E_Element[num_queries * num_virtual_blocks * num_servers];
267  nqueries_t current_query = 0;
268  GF2E_Element* secrets = new GF2E_Element[qbs];
269  for (nqueries_t q=0; q<num_block_requests; q += qbs) {
270  nqueries_t tmpblock = (num_block_requests - q) > qbs ?
271  qbs : (num_block_requests - q);
272  vec_GF2E interps = vec_interp_indices;
273  interps.SetLength(tmpblock);
274  vecs_interp_indices.push_back(interps);
275  for (dbsize_t i = 0; i < num_virtual_blocks; ++i) {
276  if (tmpblock == 1) {
277  dbsize_t virtual_block_number = block_numbers[q] / virtual_block_size;
278  genshares_GF2E<GF2E_Element>(t, num_servers, indices,
279  shares + (current_query * num_virtual_blocks + i) * num_servers,
280  i == virtual_block_number);
281  } else {
282  // create GF2E_Element
283  for (nqueries_t k = 0; k < tmpblock; k++) {
284  dbsize_t virtual_block_number = block_numbers[q+k] / virtual_block_size;
285  if (virtual_block_number == i) {
286  secrets[k] = (GF2E_Element)(1);
287  } else {
288  secrets[k] = (GF2E_Element)(0);
289  }
290  }
291  gensharesmulti_GF2E<GF2E_Element>(t, num_servers, indices,
292  shares + (current_query * num_virtual_blocks + i) * num_servers,
293  secrets, interp_indices, tmpblock);
294  }
295  }
296  current_query += 1;
297  }
298  delete[] secrets;
299 
300  // Multiply shares by random multiples
301  if (randomize) {
302  vector<GF2E_Element>& request_randmults = randmults[request_identifier];
303  for (nservers_t p = 0; p < num_servers; ++p) {
304  for (nqueries_t i = 0; i < num_queries; ++i) {
305  for (dbsize_t j = 0; j < num_virtual_blocks; ++j) {
306  dbsize_t index = (i * num_virtual_blocks + j) * num_servers
307  + p;
308  shares[index] =
309  multiply_GF2E<GF2E_Element>(shares[index],
310  request_randmults[p*num_queries + i]);
311  }
312  }
313  }
314  }
315 
316  // Stored shares
317  stored_shares[request_identifier] = shares;
318 }
319 
320 template <typename GF2E_Element>
322  nqueries_t request_identifier, vector<ostream*> &osvec,
323  bool send_num_queries)
324 {
325  // Get some parameters and stored values
326  GF2E_Element * shares = stored_shares[request_identifier];
327  nqueries_t qbs = get_qbs(request_identifier);
328  nqueries_t num_block_requests = get_block_numbers(request_identifier).size();
329  nqueries_t num_queries = (num_block_requests+qbs-1)/qbs;
330  dbsize_t num_virtual_blocks = params->num_virtual_blocks();
331 
332  // Check number of streams
333  if (num_servers != osvec.size()) {
334  std::cerr << "Incorrect iostream vector size passed to "
335  "send_request_GF2E.\n";
336  std::cerr << "Was " << osvec.size() << ", should be " << num_servers
337  << ".\n";
338  return 0;
339  }
340 
341  // Send the params and query to each server
342  for (nservers_t j = 0; j < num_servers; ++j) {
343  if (send_num_queries) {
344  percy_write_le_uint16(*osvec[j], num_queries);
345  }
346  for (nqueries_t q=0; q<num_queries; ++q) {
347  for (dbsize_t i = 0; i < num_virtual_blocks; ++i) {
348  dbsize_t index = (q * num_virtual_blocks + i) * num_servers + j;
349  char *shareptr = (char *)&(shares[index]);
350  osvec[j]->write(shareptr, sizeof(GF2E_Element));
351  }
352  }
353  osvec[j]->flush();
354  }
355 
356  // Clean up
357  delete[] shares;
358  stored_shares.erase(request_identifier);
359 
360  return num_servers * ((send_num_queries ? 2 : 0) + num_queries *
361  num_virtual_blocks * sizeof(GF2E_Element));
362 }
363 
364 // Receive the server's replies, and return a number of servers that
365 // gave complete (but not necessarily correct) replies.
366 template <typename GF2E_Element>
368  nqueries_t request_identifier, vector<istream*> &isvec)
369 {
370  dbsize_t words_per_block = params->words_per_block();
371  nqueries_t qbs = get_qbs(request_identifier);
372  nqueries_t num_block_requests = get_block_numbers(request_identifier).size();
373  nqueries_t num_queries = (num_block_requests+qbs-1)/qbs;
374  nqueries_t q;
375 
376  // The vector of servers that have responded properly
377  goodservers.clear();
378 
379  // The responses from the servers
380  nqueries_t prev = answers.size();
381  for (nqueries_t q = 0; q < num_queries; ++q) {
382  answers.push_back(new GF2E_Element[words_per_block * num_servers]);
383  }
384 
385  // Read the replies
386  for (nservers_t j = 0; j < num_servers; ++j) {
387  bool isgood = true;
388  for (nqueries_t q = prev; q < prev + num_queries; ++q) {
389  for (dbsize_t i = 0; isgood && i < words_per_block; ++i) {
390  isvec[j]->read((char *)(answers[q] + i * num_servers + j),
391  sizeof(GF2E_Element));
392  if (isvec[j]->eof()) {
393  std::cerr << "Server " << j+1 << " did not send complete reply.\n";
394  std::cerr << "Marking server " << j+1 << " as bad.\n";
395  isgood = false;
396  break;
397  }
398  if ((dbsize_t)(isvec[j]->gcount()) < 1) {
399  // Mark this server as bad
400  std::cerr << "Marking server " << j+1 << " as bad.\n";
401  isgood = false;
402  break;
403  }
404  }
405  }
406  if (isgood) {
407  goodservers.push_back(j);
408  }
409  }
410 
411  // Remove random multiple
412  if (randomize) {
413  vector<GF2E_Element>& request_randmults = randmults[request_identifier];
414  for (nservers_t j = 0; j < num_servers; ++j) {
415  for (nqueries_t q = 0; q < num_queries; ++q) {
416  GF2E_Element randmult_inv =
417  inverse_GF2E<GF2E_Element>(request_randmults[j*num_queries + q]);
418  for (dbsize_t i = 0; i < words_per_block; ++i) {
419  answers[q+prev][i*num_servers + j] = multiply_GF2E<GF2E_Element>(
420  answers[q+prev][i*num_servers + j], randmult_inv);
421  }
422  }
423  }
424  randmults.erase(request_identifier);
425  }
426 
427  // Add to unfinished_results and decoded
428  for (q=0; q<num_queries; ++q) {
429  unfinished_results.push_back(
430  vector<DecoderResult<GF2E> >(1, DecoderResult<GF2E>(goodservers, vector<map<dbsize_t, GF2E> >())));
431  decoded.push_back(std::set<dbsize_t>());
432  }
433 
434  return num_servers * num_queries * words_per_block * sizeof(GF2E_Element);
435 }
436 
437 // Construct the numpoints Lagrange coefficents to interpolate at the
438 // point alpha from the source points
439 // indices[goodservers[firstpoint .. firstpoint+numpoints-1]]
440 template <typename GF2E_Element>
442  GF2E_Element alpha, nservers_t firstpoint, nservers_t numpoints)
443 {
444  for (nservers_t i=0; i < numpoints; ++i) {
445  GF2E_Element numer = 1, denom = 1;
446  for (nservers_t j=0; j < numpoints; ++j) {
447  if (j==i) continue;
448  GF2E_Element numerdiff = indices[goodservers[firstpoint+j]] ^
449  alpha;
450  GF2E_Element denomdiff = indices[goodservers[firstpoint+j]] ^
451  indices[goodservers[firstpoint+i]];
452  numer = multiply_GF2E<GF2E_Element>(numer, numerdiff);
453  denom = multiply_GF2E<GF2E_Element>(denom, denomdiff);
454  }
455  coeffs[i] = multiply_GF2E<GF2E_Element>(numer,
456  inverse_GF2E<GF2E_Element>(denom));
457  }
458 }
459 
460 // Do Lagrange interpolation of source values
461 // answers[goodservers[firstpoint..firstpoint+numpoints-1]] with the
462 // coefficients coeffs[0..t]
463 template <typename GF2E_Element>
465  const GF2E_Element *word_answers, const GF2E_Element *coeffs,
466  nservers_t firstpoint, nservers_t numpoints)
467 {
468  GF2E_Element res = 0;
469 
470  for (nservers_t i = 0; i < numpoints; ++i) {
471  res ^= multiply_GF2E<GF2E_Element>(coeffs[i],
472  word_answers[goodservers[firstpoint+i]]);
473  }
474 
475  return res;
476 }
477 
478 template <typename GF2E_Element>
480  vector<vector<PercyResult> > &results)
481 {
482  dbsize_t words_per_block = params->words_per_block();
483  nqueries_t num_queries = vecs_interp_indices.size();
484  nservers_t k = goodservers.size();
485 
486  if (k <= t) return false;
487 
488  results.clear();
489  for (nqueries_t q = 0; q < num_queries; ++q) {
490 
491  // blocks per query; the polynomial is of degree t+bpq-1
492  nqueries_t bpq = vecs_interp_indices[q].length();
493 
494  // bpq == 0 is the old case of just retrieving one block,
495  // interpolated at 0
496  const bool justzero = (bpq == 0);
497  if (justzero) {
498  bpq = 1;
499  }
500  GF2E_Element *resblock = new GF2E_Element[words_per_block * bpq];
501 
502  // Construct the Lagrange coefficients for the interp indices as
503  // well as the target indices[goodservers[0..(k-t-bpq-1)]] from
504  // the source indices[goodservers[k-t-bpq .. k-1]]
505 
506  // result_coeffs[a] is the array of t+bpq coeffs to interpolate
507  // interp_indices[a]
508  GF2E_Element *result_coeffs = new GF2E_Element[bpq*(t+bpq)];
509  for (nservers_t a = 0; a < bpq; ++a) {
510  construct_lagrange_coeffs(result_coeffs + a*(t+bpq),
511  justzero ? 0 : interp_indices[a],
512  k-t-bpq, t+bpq);
513  }
514 
515  // check_coeffs[a] is the array of t+bpq coeffs to interpolate
516  // indices[goodservers[a]]
517  GF2E_Element *check_coeffs = new GF2E_Element[(k-t-bpq)*(t+bpq)];
518  for (nservers_t a = 0; a < k-t-bpq; ++a) {
519  construct_lagrange_coeffs(check_coeffs + a*(t+bpq),
520  indices[goodservers[a]],
521  k-t-bpq, t+bpq);
522  }
523 
524  for (dbsize_t word = 0; word < words_per_block; ++word) {
525  // Check if all the servers agree
526  bool match = true;
527  for (nservers_t a = 0; a < k-t-bpq; ++a) {
528  GF2E_Element expectedans =
529  answers[q][word*num_servers + goodservers[a]];
530  GF2E_Element actualans = interpolate(
531  answers[q] + word*num_servers,
532  check_coeffs + a*(t+bpq), k-t-bpq, t+bpq);
533 
534  if (expectedans != actualans) {
535  match = false;
536  break;
537  }
538  }
539  if (!match) {
540  delete[] check_coeffs;
541  delete[] result_coeffs;
542  delete[] resblock;
543  results.clear();
544  return false;
545  }
546  for (nservers_t a = 0; a < bpq; ++a) {
547  resblock[a*words_per_block+word] = interpolate(
548  answers[q] + word*num_servers,
549  result_coeffs + a*(t+bpq), k-t-bpq, t+bpq);
550  }
551  }
552  for (nservers_t a = 0; a < bpq; ++a) {
553  PercyResult thisresult(goodservers,
554  string((char *)(resblock + a*words_per_block),
555  words_per_block*sizeof(GF2E_Element)));
556  results.push_back(vector<PercyResult>(1, thisresult));
557  }
558 
559  delete[] result_coeffs;
560  delete[] check_coeffs;
561  delete[] resblock;
562  }
563 
564  return true;
565 }
566 
567 //Process the received replies and return the decoded results as a
568 //PercyResults object.
569 template <typename GF2E_Element>
571  vector<vector<PercyResult> >& results)
572 {
573  dbsize_t words_per_block = params->words_per_block();
574  nservers_t tau = params->tau();
575 
576  // Check that results is empty
577  if (!(results.empty())) {
578  std::cerr << "The results vector must be empty\n";
579  return false;
580  }
581 
582  if (try_fast_recover(h, results)) {
583  // Clean up
584  while (answers.size() > 0) {
585  if (answers.back() != NULL) {
586  delete[] answers.back();
587  }
588  answers.pop_back();
589  }
590  answers_ntl.clear();
591  unfinished_results.clear();
592  decoded.clear();
593  vecs_interp_indices.clear();
594  return 0;
595  }
596 
597  // Create NTL answers not yet created
598  for (nqueries_t q = answers_ntl.size(); q < answers.size(); ++q) {
599  answers_ntl.push_back(vector<vec_GF2E>(words_per_block));
600  for (dbsize_t c = 0; c < words_per_block; ++c) {
601  answers_ntl[q][c].SetLength(num_servers);
602  for (nservers_t j = 0; j < num_servers; ++j) {
603  conv(answers_ntl[q][c][j],
604  GF2XFromBytes((unsigned char *)(answers[q] +
605  c * num_servers + j), sizeof(GF2E_Element)));
606  }
607  }
608  }
609 
610  RSDecoder_GF2E decoder;
611 
612  // Call the decoder's Recover method
613  bool res = decoder.Recover(sizeof(GF2E_Element), t+tau, h, goodservers,
614  answers_ntl, indices_ntl, unfinished_results, decoded,
615  vecs_interp_indices);
616 
617  // Convert the results to PercyBlockResults
618  // Remove queries that are completely decoded
619  GF2E_Element *sigma = new GF2E_Element[words_per_block];
620  for (nqueries_t q = 0; q < answers.size(); ++q) {
621  for (dbsize_t i = 0; i < unfinished_results[q].size(); ++i) {
622  ssize_t indices_len = vecs_interp_indices[q].length();
623  const int num_subqueries = indices_len > 0 ? indices_len : 1;
624  for (int sub_query = 0; sub_query < num_subqueries; sub_query++) {
625  results.push_back(vector<PercyResult>());
626  vector<PercyResult> &block_results = results.back();
627  if (decoded[q].size() == words_per_block) {
628  for (dbsize_t j = 0; j < words_per_block; ++j) {
629  BytesFromGF2X((unsigned char *)(sigma + j),
630  rep(unfinished_results[q][i].recovered[sub_query][j]),
631  sizeof(GF2E_Element));
632  }
633  block_results.push_back(PercyResult(unfinished_results[q][i].G,
634  string((char *)sigma, words_per_block * sizeof(GF2E_Element))));
635  }
636  }
637  }
638 
639  if (decoded[q].size() == words_per_block) {
640  // Remove query
641  if (answers[q] != NULL) {
642  delete[] answers[q];
643  }
644  answers.erase(answers.begin() + q);
645  answers_ntl.erase(answers_ntl.begin() + q);
646  unfinished_results.erase(unfinished_results.begin() + q);
647  decoded.erase(decoded.begin() + q);
648  vecs_interp_indices.erase(vecs_interp_indices.begin() + q);
649  --q;
650  }
651  }
652  delete[] sigma;
653 
654  (void)res;
655  return answers.size();
656 }
657 
658 #endif
Client parameters.
Definition: percyparams.h:189
Definition: percyresult.h:30
Definition: percystats.h:66
Reed-Solomon Decoder.
Definition: rsdecoder.h:161
Contains the results (so far) of decoding words.
Definition: rsdecoder.h:87
A PIR client for the IT-PIR protocol by Goldberg (2007) over GF(2^E).
Definition: itclient.h:147
bool Recover(dbsize_t bytes_per_word, nservers_t t, nservers_t h, const vector< nservers_t > &goodservers, const vector< vector< vec_F > > &values, const vec_F &server_indices, vector< vector< DecoderResult< F > > > &results, vector< std::set< dbsize_t > > &decoded, const vector< vec_F > &vec_interp_indices, const nqueries_t multi_only=0)
The main method to do the Reed-Solomon Decoding.
Definition: rsdecoder_impl.h:2823
virtual ~PercyClient_GF2E()
Destructor.
Definition: itclient_impl.h:84
An abstract base class for a PIR client.
Definition: percyclient.h:35
PercyClient_GF2E(const PercyClientParams *params, nservers_t num_servers, nservers_t t, sid_t *sids, PercyStats *stats=NULL)
Constructor.
Definition: itclient_impl.h:58
Definition: itparams.h:144