serverEntity.cpp 23 KB

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