serverEntity.cpp 22 KB

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