serverEntity.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. #include <iostream>
  2. #include "serverEntity.hpp"
  3. /********************
  4. * PUBLIC FUNCTIONS *
  5. ********************/
  6. /*
  7. * CONSTRUCTORS
  8. */
  9. PrsonaServerEntity::PrsonaServerEntity(
  10. size_t numServers)
  11. {
  12. if (numServers < 1)
  13. std::cerr << "You have to have at least 1 server. I'm making it anyways." << std::endl;
  14. // Make the first server, which makes the BGN parameters
  15. servers.push_back(PrsonaServer(numServers));
  16. // Make the rest of the servers, which take the BGN parameters
  17. const BGN& sharedBGN = servers[0].get_bgn_details();
  18. for (size_t i = 1; i < numServers; i++)
  19. servers.push_back(PrsonaServer(numServers, sharedBGN));
  20. // After all servers have made their seeds,
  21. // make sure they have the initial fresh generator
  22. std::vector<Proof> pi;
  23. Twistpoint firstGenerator = get_fresh_generator(pi);
  24. for (size_t i = 0; i < numServers; i++)
  25. servers[i].initialize_fresh_generator(pi, firstGenerator);
  26. pi.clear();
  27. // It's important that no server knows the DLOG between g and h for ElGamal,
  28. // so have each server collaborate to make h.
  29. Twistpoint blindGenerator = PrsonaServer::EL_GAMAL_GENERATOR;
  30. for (size_t i = 0; i < numServers; i++)
  31. blindGenerator = servers[i].add_rand_seed_to_generator(pi, blindGenerator);
  32. for (size_t i = 0; i < numServers; i++)
  33. servers[i].set_EG_blind_generator(pi, blindGenerator);
  34. }
  35. /*
  36. * BASIC PUBLIC SYSTEM INFO GETTERS
  37. */
  38. BGNPublicKey PrsonaServerEntity::get_bgn_public_key() const
  39. {
  40. return get_bgn_public_key(0);
  41. }
  42. BGNPublicKey PrsonaServerEntity::get_bgn_public_key(
  43. size_t which) const
  44. {
  45. return servers[which].get_bgn_public_key();
  46. }
  47. Twistpoint PrsonaServerEntity::get_blinding_generator() const
  48. {
  49. return get_blinding_generator(0);
  50. }
  51. Twistpoint PrsonaServerEntity::get_blinding_generator(
  52. size_t which) const
  53. {
  54. std::vector<Proof> pi;
  55. Twistpoint retval = get_blinding_generator(pi, which);
  56. if (!servers[which].verify_generator_proof(pi, retval, servers[which].get_num_servers()))
  57. {
  58. std::cerr << "Error making the generator, aborting." << std::endl;
  59. return Twistpoint();
  60. }
  61. return retval;
  62. }
  63. Twistpoint PrsonaServerEntity::get_blinding_generator(
  64. std::vector<Proof>& pi) const
  65. {
  66. return get_blinding_generator(pi, 0);
  67. }
  68. Twistpoint PrsonaServerEntity::get_blinding_generator(
  69. std::vector<Proof>& pi,
  70. size_t which) const
  71. {
  72. return servers[which].get_blinding_generator(pi);
  73. }
  74. Twistpoint PrsonaServerEntity::get_fresh_generator() const
  75. {
  76. return get_fresh_generator(0);
  77. }
  78. Twistpoint PrsonaServerEntity::get_fresh_generator(
  79. size_t which) const
  80. {
  81. std::vector<Proof> pi;
  82. Twistpoint retval = get_fresh_generator(pi, which);
  83. if (!servers[which].verify_generator_proof(pi, retval, servers[which].get_num_servers()))
  84. {
  85. std::cerr << "Error making the generator, aborting." << std::endl;
  86. return Twistpoint();
  87. }
  88. return retval;
  89. }
  90. Twistpoint PrsonaServerEntity::get_fresh_generator(
  91. std::vector<Proof>& pi) const
  92. {
  93. return get_fresh_generator(pi, 0);
  94. }
  95. Twistpoint PrsonaServerEntity::get_fresh_generator(
  96. std::vector<Proof>& pi,
  97. size_t which) const
  98. {
  99. Twistpoint retval = PrsonaServer::EL_GAMAL_GENERATOR;
  100. pi.clear();
  101. for (size_t j = 0; j < servers[which].get_num_servers(); j++)
  102. {
  103. size_t index = (which + j) % servers[which].get_num_servers();
  104. retval = servers[index].add_curr_seed_to_generator(pi, retval);
  105. }
  106. return retval;
  107. }
  108. size_t PrsonaServerEntity::get_num_clients() const
  109. {
  110. return get_num_clients(0);
  111. }
  112. size_t PrsonaServerEntity::get_num_clients(
  113. size_t which) const
  114. {
  115. return servers[which].get_num_clients();
  116. }
  117. size_t PrsonaServerEntity::get_num_servers() const
  118. {
  119. return get_num_servers(0);
  120. }
  121. size_t PrsonaServerEntity::get_num_servers(
  122. size_t which) const
  123. {
  124. return servers[which].get_num_servers();
  125. }
  126. /*
  127. * ENCRYPTED DATA GETTERS
  128. */
  129. std::vector<TwistBipoint> PrsonaServerEntity::get_current_votes_by(
  130. Proof& pi,
  131. const Twistpoint& shortTermPublicKey) const
  132. {
  133. return get_current_votes_by(pi, shortTermPublicKey, 0);
  134. }
  135. /* Call this in order to get the current encrypted votes cast by a given user
  136. * (who is identified by their short term public key).
  137. * In practice, this is intended for clients,
  138. * who need to know their current votes in order to rerandomize them. */
  139. std::vector<TwistBipoint> PrsonaServerEntity::get_current_votes_by(
  140. Proof& pi,
  141. const Twistpoint& shortTermPublicKey,
  142. size_t which) const
  143. {
  144. return servers[which].get_current_votes_by(pi, shortTermPublicKey);
  145. }
  146. std::vector<std::vector<TwistBipoint>> PrsonaServerEntity::get_all_current_votes(
  147. Proof& pi) const
  148. {
  149. return get_all_current_votes(pi, 0);
  150. }
  151. std::vector<std::vector<TwistBipoint>> PrsonaServerEntity::get_all_current_votes(
  152. Proof& pi,
  153. size_t which) const
  154. {
  155. return servers[which].get_all_current_votes(pi);
  156. }
  157. EGCiphertext PrsonaServerEntity::get_current_user_encrypted_tally(
  158. Proof& pi,
  159. const Twistpoint& shortTermPublicKey) const
  160. {
  161. return get_current_user_encrypted_tally(pi, shortTermPublicKey, 0);
  162. }
  163. EGCiphertext PrsonaServerEntity::get_current_user_encrypted_tally(
  164. Proof& pi,
  165. const Twistpoint& shortTermPublicKey,
  166. size_t which) const
  167. {
  168. return servers[which].get_current_user_encrypted_tally(pi, shortTermPublicKey);
  169. }
  170. CurveBipoint PrsonaServerEntity::get_current_server_encrypted_tally(
  171. Proof& pi,
  172. const Twistpoint& shortTermPublicKey) const
  173. {
  174. return get_current_server_encrypted_tally(pi, shortTermPublicKey, 0);
  175. }
  176. CurveBipoint PrsonaServerEntity::get_current_server_encrypted_tally(
  177. Proof& pi,
  178. const Twistpoint& shortTermPublicKey,
  179. size_t which) const
  180. {
  181. return servers[which].get_current_server_encrypted_tally(pi, shortTermPublicKey);
  182. }
  183. std::vector<Twistpoint> PrsonaServerEntity::get_current_pseudonyms(
  184. Proof& pi) const
  185. {
  186. return get_current_pseudonyms(pi, 0);
  187. }
  188. std::vector<Twistpoint> PrsonaServerEntity::get_current_pseudonyms(
  189. Proof& pi,
  190. size_t which) const
  191. {
  192. return servers[which].get_current_pseudonyms(pi);
  193. }
  194. /*
  195. * PROOF COMMITMENT GETTERS
  196. */
  197. void PrsonaServerEntity::get_other_vote_row_commitments(
  198. std::vector<Proof>& pi,
  199. const Twistpoint& request) const
  200. {
  201. get_other_vote_row_commitments(pi, request, 0);
  202. }
  203. void PrsonaServerEntity::get_other_vote_row_commitments(
  204. std::vector<Proof>& pi,
  205. const Twistpoint& request,
  206. size_t whichNot) const
  207. {
  208. for (size_t i = 0; i < servers.size(); i++)
  209. {
  210. if (i == whichNot)
  211. continue;
  212. pi.push_back(servers[i].get_vote_row_commitment(request));
  213. }
  214. }
  215. void PrsonaServerEntity::get_other_vote_matrix_commitments(
  216. std::vector<Proof>& pi) const
  217. {
  218. get_other_vote_matrix_commitments(pi, 0);
  219. }
  220. void PrsonaServerEntity::get_other_vote_matrix_commitments(
  221. std::vector<Proof>& pi,
  222. size_t whichNot) const
  223. {
  224. for (size_t i = 0; i < servers.size(); i++)
  225. {
  226. if (i == whichNot)
  227. continue;
  228. pi.push_back(servers[i].get_vote_matrix_commitment());
  229. }
  230. }
  231. void PrsonaServerEntity::get_other_user_tally_commitments(
  232. std::vector<Proof>& pi,
  233. const Twistpoint& request) const
  234. {
  235. get_other_user_tally_commitments(pi, request, 0);
  236. }
  237. void PrsonaServerEntity::get_other_user_tally_commitments(
  238. std::vector<Proof>& pi,
  239. const Twistpoint& request,
  240. size_t whichNot) const
  241. {
  242. for (size_t i = 0; i < servers.size(); i++)
  243. {
  244. if (i == whichNot)
  245. continue;
  246. pi.push_back(servers[i].get_user_tally_commitment(request));
  247. }
  248. }
  249. void PrsonaServerEntity::get_other_server_tally_commitments(
  250. std::vector<Proof>& pi,
  251. const Twistpoint& request) const
  252. {
  253. get_other_server_tally_commitments(pi, request, 0);
  254. }
  255. void PrsonaServerEntity::get_other_server_tally_commitments(
  256. std::vector<Proof>& pi,
  257. const Twistpoint& request,
  258. size_t whichNot) const
  259. {
  260. for (size_t i = 0; i < servers.size(); i++)
  261. {
  262. if (i == whichNot)
  263. continue;
  264. pi.push_back(servers[i].get_server_tally_commitment(request));
  265. }
  266. }
  267. void PrsonaServerEntity::get_other_pseudonyms_commitments(
  268. std::vector<Proof>& pi) const
  269. {
  270. get_other_pseudonyms_commitments(pi, 0);
  271. }
  272. void PrsonaServerEntity::get_other_pseudonyms_commitments(
  273. std::vector<Proof>& pi,
  274. size_t whichNot) const
  275. {
  276. for (size_t i = 0; i < servers.size(); i++)
  277. {
  278. if (i == whichNot)
  279. continue;
  280. pi.push_back(servers[i].get_pseudonyms_commitment());
  281. }
  282. }
  283. /*
  284. * CLIENT INTERACTIONS
  285. */
  286. void PrsonaServerEntity::add_new_client(
  287. PrsonaClient& newUser)
  288. {
  289. add_new_client(newUser, 0);
  290. }
  291. /* Add a new client (who is identified only by their short term public key)
  292. * One server does the main work, then other servers import their (proven)
  293. * exported data. */
  294. void PrsonaServerEntity::add_new_client(
  295. PrsonaClient& newUser,
  296. size_t which)
  297. {
  298. Proof proofOfValidSTPK, proofOfValidVotes;
  299. std::vector<Proof> proofOfValidGenerator, proofOfCorrectAddition;
  300. Twistpoint freshGenerator = get_fresh_generator(proofOfValidGenerator, which);
  301. // Users can't actually announce a short term public key
  302. // if they don't know the fresh generator.
  303. newUser.receive_fresh_generator(proofOfValidGenerator, freshGenerator);
  304. Twistpoint shortTermPublicKey = newUser.get_short_term_public_key(proofOfValidSTPK);
  305. // Do the actual work of adding the client to the first server
  306. servers[which].add_new_client(proofOfCorrectAddition, proofOfValidSTPK, shortTermPublicKey);
  307. // Then, export the data to the rest of the servers
  308. std::vector<CurveBipoint> previousVoteTallies;
  309. std::vector<Twistpoint> currentPseudonyms;
  310. std::vector<EGCiphertext> currentUserEncryptedTallies;
  311. std::vector<std::vector<TwistBipoint>> voteMatrix;
  312. previousVoteTallies = servers[which].previousVoteTallies;
  313. currentPseudonyms = servers[which].currentPseudonyms;
  314. currentUserEncryptedTallies = servers[which].currentUserEncryptedTallies;
  315. voteMatrix = servers[which].voteMatrix;
  316. for (size_t j = 1; j < servers[which].get_num_servers(); j++)
  317. {
  318. size_t index = (which + j) % servers[which].get_num_servers();
  319. servers[index].import_new_user_update(proofOfCorrectAddition, previousVoteTallies, currentPseudonyms, currentUserEncryptedTallies, voteMatrix);
  320. }
  321. // Finally, give the user the information it needs
  322. // about its current tally and votes
  323. transmit_new_user_data(proofOfCorrectAddition, newUser);
  324. }
  325. // Receive a new vote row from a user (identified by short term public key).
  326. bool PrsonaServerEntity::receive_vote(
  327. const std::vector<Proof>& pi,
  328. const std::vector<TwistBipoint>& newVotes,
  329. const Twistpoint& shortTermPublicKey)
  330. {
  331. return receive_vote(pi, newVotes, shortTermPublicKey, 0);
  332. }
  333. bool PrsonaServerEntity::receive_vote(
  334. const std::vector<Proof>& pi,
  335. const std::vector<TwistBipoint>& newVotes,
  336. const Twistpoint& shortTermPublicKey,
  337. size_t which)
  338. {
  339. bool retval = true;
  340. for (size_t i = 0; i < servers[which].get_num_servers(); i++)
  341. {
  342. size_t index = (i + which) % servers[which].get_num_servers();
  343. retval = retval && servers[index].receive_vote(pi, newVotes, shortTermPublicKey);
  344. }
  345. return retval;
  346. }
  347. void PrsonaServerEntity::transmit_new_user_data(
  348. const std::vector<Proof>& pi,
  349. PrsonaClient& newUser) const
  350. {
  351. transmit_new_user_data(pi, newUser, 0);
  352. }
  353. void PrsonaServerEntity::transmit_new_user_data(
  354. const std::vector<Proof>& pi,
  355. PrsonaClient& newUser,
  356. size_t which) const
  357. {
  358. Twistpoint shortTermPublicKey = newUser.get_short_term_public_key();
  359. Proof baseProof;
  360. std::vector<Proof> serverEncryptedScoreProof;
  361. CurveBipoint serverEncryptedScore = get_current_server_encrypted_tally(baseProof, shortTermPublicKey, which);
  362. serverEncryptedScoreProof.push_back(baseProof);
  363. get_other_server_tally_commitments(serverEncryptedScoreProof, shortTermPublicKey, which);
  364. baseProof.clear();
  365. std::vector<Proof> userEncryptedScoreProof;
  366. EGCiphertext userEncryptedScore = get_current_user_encrypted_tally(baseProof, shortTermPublicKey, which);
  367. userEncryptedScoreProof.push_back(baseProof);
  368. get_other_user_tally_commitments(userEncryptedScoreProof, shortTermPublicKey, which);
  369. baseProof.clear();
  370. std::vector<Proof> voteMatrixProof;
  371. std::vector<std::vector<TwistBipoint>> voteMatrix = get_all_current_votes(baseProof, which);
  372. voteMatrixProof.push_back(baseProof);
  373. get_other_vote_matrix_commitments(voteMatrixProof, which);
  374. baseProof.clear();
  375. std::vector<Proof> pseudonymsProof;
  376. std::vector<Twistpoint> currentPseudonyms = get_current_pseudonyms(baseProof, which);
  377. pseudonymsProof.push_back(baseProof);
  378. get_other_pseudonyms_commitments(pseudonymsProof, which);
  379. newUser.receive_new_user_data(pi, serverEncryptedScoreProof, serverEncryptedScore, userEncryptedScoreProof, userEncryptedScore, voteMatrixProof, voteMatrix, pseudonymsProof, currentPseudonyms);
  380. }
  381. void PrsonaServerEntity::transmit_updates(
  382. PrsonaClient& currUser) const
  383. {
  384. transmit_updates(currUser, 0);
  385. }
  386. // After tallying scores and new vote matrix,
  387. // give those to a user for the new epoch
  388. void PrsonaServerEntity::transmit_updates(
  389. PrsonaClient& currUser,
  390. size_t which) const
  391. {
  392. Proof proofOfValidSTPK, proofOfScore, proofOfCorrectVotes;
  393. std::vector<Proof> proofOfValidGenerator;
  394. Twistpoint freshGenerator = get_fresh_generator(proofOfValidGenerator, which);
  395. // Get users the next fresh generator so they can correctly
  396. // ask for their new scores and vote row
  397. currUser.receive_fresh_generator(proofOfValidGenerator, freshGenerator);
  398. Proof baseProof;
  399. std::vector<Proof> fullProof;
  400. Twistpoint shortTermPublicKey = currUser.get_short_term_public_key();
  401. EGCiphertext encryptedScore = get_current_user_encrypted_tally(baseProof, shortTermPublicKey, which);
  402. fullProof.push_back(baseProof);
  403. get_other_user_tally_commitments(fullProof, shortTermPublicKey, which);
  404. currUser.receive_vote_tally(fullProof, encryptedScore);
  405. }
  406. /*
  407. * EPOCH
  408. */
  409. void PrsonaServerEntity::epoch()
  410. {
  411. epoch(0);
  412. }
  413. // Do the epoch process
  414. void PrsonaServerEntity::epoch(
  415. size_t which)
  416. {
  417. Twistpoint nextGenerator = PrsonaServer::EL_GAMAL_GENERATOR;
  418. std::vector<std::vector<std::vector<Proof>>> pi;
  419. std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
  420. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
  421. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
  422. std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
  423. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
  424. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
  425. std::vector<std::vector<std::vector<Twistpoint>>> userTallyMaskCommits;
  426. std::vector<std::vector<std::vector<Twistpoint>>> userTallyMessageCommits;
  427. std::vector<std::vector<std::vector<Twistpoint>>> userTallySeedCommits;
  428. std::vector<std::vector<Proof>> generator_proof_holder(1);
  429. pi.push_back(generator_proof_holder);
  430. // go from A_0 to A_0.5
  431. for (size_t i = 0; i < servers[which].get_num_servers(); i++)
  432. {
  433. size_t realI = (which + i) % servers[which].get_num_servers();
  434. servers[realI].build_up_midway_pseudonyms(pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, nextGenerator);
  435. for (size_t j = 1; j < servers[which].get_num_servers(); j++)
  436. {
  437. std::vector<std::vector<Twistpoint>> currUserTallyMaskCommits;
  438. std::vector<std::vector<Twistpoint>> currUserTallyMessageCommits;
  439. std::vector<std::vector<Twistpoint>> currUserTallySeedCommits;
  440. size_t realJ = (realI + j) % servers[which].get_num_servers();
  441. servers[realJ].accept_epoch_updates(pi[i + 1], permutationCommits[i], freshPseudonymCommits[i], freshPseudonymSeedCommits[i], serverTallyCommits[i], partwayVoteMatrixCommits[i], finalVoteMatrixCommits[i], currUserTallyMaskCommits, currUserTallyMessageCommits, currUserTallySeedCommits, nextGenerator, false);
  442. }
  443. }
  444. std::vector<Proof> generator_proof = pi[0][0];
  445. pi.clear();
  446. permutationCommits.clear();
  447. freshPseudonymCommits.clear();
  448. freshPseudonymSeedCommits.clear();
  449. serverTallyCommits.clear();
  450. partwayVoteMatrixCommits.clear();
  451. finalVoteMatrixCommits.clear();
  452. /* Imagine that server 0 is encrypting these, then would do a ZKP that it
  453. * knows a secret mask and encrypted the correct value everyone else already
  454. * knows. Everyone else then adds a mask and proves they added a secret mask
  455. * to the committed values. */
  456. std::vector<EGCiphertext> currentUserEncryptedTallies;
  457. std::vector<CurveBipoint> currentServerEncryptedTallies;
  458. tally_scores(nextGenerator, currentUserEncryptedTallies, currentServerEncryptedTallies, which);
  459. distribute_tallied_scores(currentUserEncryptedTallies, currentServerEncryptedTallies);
  460. // go from A_0.5 to A_1
  461. for (size_t i = 0; i < servers[which].get_num_servers(); i++)
  462. {
  463. size_t realI = (which + i) % servers[which].get_num_servers();
  464. servers[realI].break_down_midway_pseudonyms(generator_proof, pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits, nextGenerator);
  465. for (size_t j = 1; j < servers[which].get_num_servers(); j++)
  466. {
  467. size_t realJ = (realI + j) % servers[which].get_num_servers();
  468. servers[realJ].accept_epoch_updates(pi[i], permutationCommits[i], freshPseudonymCommits[i], freshPseudonymSeedCommits[i], serverTallyCommits[i], partwayVoteMatrixCommits[i], finalVoteMatrixCommits[i], userTallyMaskCommits[i], userTallyMessageCommits[i], userTallySeedCommits[i], nextGenerator, true);
  469. }
  470. }
  471. }
  472. void PrsonaServerEntity::print_scores() const
  473. {
  474. BGN bgnSystem = servers[0].bgnSystem;
  475. std::vector<CurveBipoint> scores = servers[0].previousVoteTallies;
  476. std::cout << "[";
  477. for (size_t i = 0; i < scores.size(); i++)
  478. std::cout << bgnSystem.decrypt(scores[i]) << (i == scores.size() - 1 ? "]" : " ");
  479. std::cout << std::endl;
  480. }
  481. void PrsonaServerEntity::print_votes() const
  482. {
  483. BGN bgnSystem = servers[0].bgnSystem;
  484. std::vector<std::vector<TwistBipoint>> voteMatrix = servers[0].voteMatrix;
  485. for (size_t i = 0; i < voteMatrix.size(); i++)
  486. {
  487. std::cout << (i == 0 ? "[[" : " [");
  488. for (size_t j = 0; j < voteMatrix[i].size(); j++)
  489. std::cout << bgnSystem.decrypt(voteMatrix[i][j]) << (j == voteMatrix[i].size() - 1 ? "]" : " ");
  490. std::cout << (i == voteMatrix.size() - 1 ? "]" : " ") << std::endl;
  491. }
  492. }
  493. void PrsonaServerEntity::print_current_votes_by(
  494. const Twistpoint& index) const
  495. {
  496. BGN bgnSystem = servers[0].bgnSystem;
  497. size_t realIndex = servers[0].binary_search(index);
  498. std::vector<TwistBipoint> scores = servers[0].voteMatrix[realIndex];
  499. std::cout << "[";
  500. for (size_t i = 0; i < scores.size(); i++)
  501. std::cout << bgnSystem.decrypt(scores[i]) << (i == scores.size() - 1 ? "]" : " ");
  502. std::cout << std::endl;
  503. }
  504. /*********************
  505. * PRIVATE FUNCTIONS *
  506. *********************/
  507. /*
  508. * SCORE TALLYING
  509. */
  510. /* Calculate scores, then scale the values appropriately,
  511. * so they are in the correct range to be used as vote weights.
  512. *
  513. * We're treating it as if we are one server, so that server gets the updated
  514. * weights to be sent to all other servers for the next epoch. */
  515. void PrsonaServerEntity::tally_scores(
  516. const Twistpoint& nextGenerator,
  517. std::vector<EGCiphertext>& userTallyScores,
  518. std::vector<CurveBipoint>& serverTallyScores,
  519. size_t which)
  520. {
  521. std::vector<EGCiphertext> retval;
  522. std::vector<Scalar> decryptedTalliedScores = servers[which].tally_scores();
  523. mpz_class maxScorePossibleThisRound = servers[which].get_max_possible_score().toInt() * PrsonaBase::get_max_allowed_vote();
  524. mpz_class topOfScoreRange = decryptedTalliedScores.size() * PrsonaBase::get_max_allowed_vote();
  525. userTallyScores.clear();
  526. serverTallyScores.clear();
  527. for (size_t i = 0; i < decryptedTalliedScores.size(); i++)
  528. {
  529. decryptedTalliedScores[i] = Scalar((decryptedTalliedScores[i].toInt() * topOfScoreRange) / maxScorePossibleThisRound);
  530. EGCiphertext currCiphertext;
  531. userTallyScores.push_back(currCiphertext);
  532. CurveBipoint currServerScore;
  533. serverTallyScores.push_back(currServerScore);
  534. Scalar currMask;
  535. currMask.set_random();
  536. // Give the server the new weights,
  537. // to get passed around to the other servers
  538. servers[which].bgnSystem.encrypt(serverTallyScores[i], decryptedTalliedScores[i]);
  539. userTallyScores[i].mask = servers[which].currentPseudonyms[i] * currMask;
  540. userTallyScores[i].encryptedMessage = (nextGenerator * currMask) + (servers[which].get_blinding_generator() * decryptedTalliedScores[i]);
  541. }
  542. }
  543. void PrsonaServerEntity::distribute_tallied_scores(
  544. const std::vector<EGCiphertext>& userScores,
  545. const std::vector<CurveBipoint>& serverScores)
  546. {
  547. for (size_t i = 0; i < servers[0].get_num_servers(); i++)
  548. servers[i].receive_tallied_scores(userScores, serverScores);
  549. }
  550. /*
  551. * BINARY SEARCH
  552. */
  553. // Completely normal binary search
  554. size_t PrsonaServerEntity::binary_search(
  555. const Twistpoint& shortTermPublicKey,
  556. size_t which) const
  557. {
  558. return servers[which].binary_search(shortTermPublicKey);
  559. }