Browse Source

all proofs work, all issues fixed, no optimizations yet made

tristangurtler 3 years ago
parent
commit
dda01bd883
8 changed files with 699 additions and 282 deletions
  1. 31 4
      prsona/inc/base.hpp
  2. 28 15
      prsona/inc/server.hpp
  3. 6 2
      prsona/inc/serverEntity.hpp
  4. 269 1
      prsona/src/base.cpp
  5. 1 0
      prsona/src/client.cpp
  6. 111 11
      prsona/src/main.cpp
  7. 177 209
      prsona/src/server.cpp
  8. 76 40
      prsona/src/serverEntity.cpp

+ 31 - 4
prsona/inc/base.hpp

@@ -24,6 +24,10 @@ class PrsonaBase {
         Curvepoint get_blinding_generator() const;
         Curvepoint get_blinding_generator(std::vector<Proof>& pi) const;
 
+        // BINARY SEARCH
+        size_t binary_search(
+            const std::vector<Curvepoint> list, const Curvepoint& index) const;
+
     protected:
         // Essentially constants, true for both servers and clients
         static Curvepoint EL_GAMAL_GENERATOR;
@@ -43,10 +47,6 @@ class PrsonaBase {
             const Curvepoint& currGenerator,
             size_t numServers);
 
-        // BINARY SEARCH
-        size_t binary_search(
-            const std::vector<Curvepoint> list, const Curvepoint& index) const;
-
         // SCHNORR PROOFS
         Proof schnorr_generation(
             const Curvepoint& generator,
@@ -179,6 +179,33 @@ class PrsonaBase {
             const std::vector<std::vector<Curvepoint>>& seedCommits
         ) const;
 
+        std::vector<Proof> generate_user_tally_proofs(
+            const std::vector<std::vector<Scalar>>& permutations,
+            const Scalar& power,
+            const Curvepoint& nextGenerator,
+            const std::vector<std::vector<Scalar>>& permutationSeeds,
+            const std::vector<std::vector<Scalar>>& userTallySeeds,
+            const std::vector<Curvepoint>& currPseudonyms,
+            const std::vector<Curvepoint>& userTallyMasks,
+            const std::vector<Curvepoint>& userTallyMessages,
+            const std::vector<std::vector<Curvepoint>>& permutationCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallySeedCommits
+        ) const;
+
+        bool verify_user_tally_proofs(
+            const std::vector<Proof>& pi,
+            const Curvepoint& nextGenerator,
+            const std::vector<Curvepoint>& currPseudonyms,
+            const std::vector<Curvepoint>& userTallyMasks,
+            const std::vector<Curvepoint>& userTallyMessages,
+            const std::vector<std::vector<Curvepoint>>& permutationCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallySeedCommits
+        ) const;
+
         template <typename T>
         std::vector<Proof> generate_proof_of_reordering(
             const std::vector<std::vector<Scalar>>& permutations,

+ 28 - 15
prsona/inc/server.hpp

@@ -112,7 +112,8 @@ class PrsonaServer : public PrsonaBase {
             std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymCommits,
             std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymSeedCommits,
             std::vector<std::vector<std::vector<TwistBipoint>>>& serverTallyCommits,
-            std::vector<std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>>& voteMatrixCommits,
+            std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& partwayVoteMatrixCommits,
+            std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& finalVoteMatrixCommits,
             Curvepoint& nextGenerator);
         void break_down_midway_pseudonyms(
             std::vector<Proof>& generatorProof,
@@ -121,9 +122,11 @@ class PrsonaServer : public PrsonaBase {
             std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymCommits,
             std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymSeedCommits,
             std::vector<std::vector<std::vector<TwistBipoint>>>& serverTallyCommits,
-            std::vector<std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>>& voteMatrixCommits,
-            std::vector<std::vector<std::vector<std::vector<Curvepoint>>>>& userTallyCommits,
-            std::vector<std::vector<std::vector<Curvepoint>>>& userTallyMaskSeedCommits,
+            std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& partwayVoteMatrixCommits,
+            std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& finalVoteMatrixCommits,
+            std::vector<std::vector<std::vector<Curvepoint>>>& userTallyMaskCommits,
+            std::vector<std::vector<std::vector<Curvepoint>>>& userTallyMessageCommits,
+            std::vector<std::vector<std::vector<Curvepoint>>>& userTallySeedCommits,
             const Curvepoint& nextGenerator);
 
         // EPOCH HELPERS
@@ -132,10 +135,13 @@ class PrsonaServer : public PrsonaBase {
             std::vector<std::vector<Curvepoint>>& freshPseudonymCommits,
             std::vector<std::vector<Curvepoint>>& freshPseudonymSeedCommits,
             std::vector<std::vector<TwistBipoint>>& serverTallyCommits,
-            std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& voteMatrixCommits,
-            std::vector<std::vector<std::vector<Curvepoint>>>& userTallyCommits,
-            std::vector<std::vector<Curvepoint>> & userTallyMaskSeedCommits,
+            std::vector<std::vector<std::vector<CurveBipoint>>>& partwayVoteMatrixCommits,
+            std::vector<std::vector<std::vector<CurveBipoint>>>& finalVoteMatrixCommits,
+            std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+            std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+            std::vector<std::vector<Curvepoint>>& userTallySeedCommits,
             const Scalar& power,
+            const Curvepoint& nextGenerator,
             bool doUserTallies);
 
         bool accept_epoch_updates(
@@ -144,9 +150,12 @@ class PrsonaServer : public PrsonaBase {
             const std::vector<std::vector<Curvepoint>>& freshPseudonymCommits,
             const std::vector<std::vector<Curvepoint>>& freshPseudonymSeedCommits,
             const std::vector<std::vector<TwistBipoint>>& serverTallyCommits,
-            const std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& voteMatrixCommits,
-            const std::vector<std::vector<std::vector<Curvepoint>>>& userTallyCommits,
-            const std::vector<std::vector<Curvepoint>>& userTallyMaskSeedCommits,
+            const std::vector<std::vector<std::vector<CurveBipoint>>>& partwayVoteMatrixCommits,
+            const std::vector<std::vector<std::vector<CurveBipoint>>>& finalVoteMatrixCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallySeedCommits,
+            const Curvepoint& nextGenerator,
             bool doUserTallies);
 
         std::vector<std::vector<Scalar>> generate_permutation_matrix(
@@ -199,14 +208,17 @@ class PrsonaServer : public PrsonaBase {
             bool inverted
         ) const;
 
-        std::vector<std::vector<std::vector<Curvepoint>>> generate_user_tally_matrix(
+        void generate_user_tally_matrix(
             const std::vector<std::vector<Scalar>>& permutations,
             const Scalar& power,
+            const Curvepoint& nextGenerator,
+            const std::vector<Curvepoint>& currPseudonyms,
             std::vector<Curvepoint>& masks,
+            std::vector<std::vector<Curvepoint>>& maskCommits,
             std::vector<Curvepoint>& messages,
-            std::vector<std::vector<Scalar>>& maskSeeds,
-            std::vector<std::vector<Curvepoint>>& maskSeedCommits,
-            std::vector<std::vector<Scalar>>& messageSeeds
+            std::vector<std::vector<Curvepoint>>& messageCommits,
+            std::vector<std::vector<Scalar>>& userTallySeeds,
+            std::vector<std::vector<Curvepoint>>& userTallySeedCommits
         ) const;
 
         template <typename T>
@@ -258,7 +270,8 @@ class PrsonaServer : public PrsonaBase {
             const std::vector<std::vector<Curvepoint>>& freshPseudonymCommits,
             const std::vector<std::vector<TwistBipoint>>& serverTallyCommits,
             const std::vector<std::vector<std::vector<CurveBipoint>>>& voteMatrixCommits,
-            const std::vector<std::vector<std::vector<Curvepoint>>>& userTallyCommits);
+            const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+            const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits);
 
         bool pseudonyms_sorted(
             const std::vector<Curvepoint> newPseudonyms

+ 6 - 2
prsona/inc/serverEntity.hpp

@@ -106,16 +106,20 @@ class PrsonaServerEntity {
 
         void print_scores() const;
         void print_votes() const;
+        void print_current_votes_by(const Curvepoint& index) const;
 
     private:
         std::vector<PrsonaServer> servers;
 
         // SCORE TALLYING
-        std::vector<EGCiphertext> tally_scores(
+        void tally_scores(
             const Curvepoint& nextGenerator,
+            std::vector<EGCiphertext>& userTallyScores,
+            std::vector<TwistBipoint>& serverTallyScores,
             size_t which);
         void distribute_tallied_scores(
-            const std::vector<EGCiphertext>& scores);
+            const std::vector<EGCiphertext>& userScores,
+            const std::vector<TwistBipoint>& serverScores);
         
         // BINARY SEARCH
         size_t binary_search(

+ 269 - 1
prsona/src/base.cpp

@@ -222,7 +222,7 @@ Proof PrsonaBase::add_to_generator_proof(
     const Scalar& seed) const
 {
     Proof retval;
-    if (!CLIENT_IS_MALICIOUS)
+    if (!SERVER_IS_MALICIOUS)
     {
         retval.hbc = "PROOF";
         return retval;
@@ -936,6 +936,9 @@ std::vector<Proof> PrsonaBase::generate_proof_of_reordering_plus_power(
     std::stringstream oracleInput;
     oracleInput << g << h;
 
+    for (size_t i = 0; i < oldValues.size(); i++)
+        oracleInput << oldValues[i];
+
     for (size_t i = 0; i < permutationCommits.size(); i++)
         for (size_t j = 0; j < permutationCommits[i].size(); j++)
             oracleInput << permutationCommits[i][j];
@@ -1040,6 +1043,9 @@ bool PrsonaBase::verify_proof_of_reordering_plus_power(
     std::stringstream oracleInput;
     oracleInput << g << h;
 
+    for (size_t i = 0; i < oldValues.size(); i++)
+        oracleInput << oldValues[i];
+
     for (size_t i = 0; i < permutationCommits.size(); i++)
         for (size_t j = 0; j < permutationCommits[i].size(); j++)
             oracleInput << permutationCommits[i][j];
@@ -1104,6 +1110,262 @@ bool PrsonaBase::verify_proof_of_reordering_plus_power(
     return true;
 }
 
+std::vector<Proof> PrsonaBase::generate_user_tally_proofs(
+    const std::vector<std::vector<Scalar>>& permutations,
+    const Scalar& power,
+    const Curvepoint& nextGenerator,
+    const std::vector<std::vector<Scalar>>& permutationSeeds,
+    const std::vector<std::vector<Scalar>>& userTallySeeds,
+    const std::vector<Curvepoint>& currPseudonyms,
+    const std::vector<Curvepoint>& userTallyMasks,
+    const std::vector<Curvepoint>& userTallyMessages,
+    const std::vector<std::vector<Curvepoint>>& permutationCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallySeedCommits) const
+{
+    std::vector<Proof> retval;
+
+    if (!SERVER_IS_MALICIOUS)
+    {
+        retval.push_back(Proof("PROOF"));
+        return retval;
+    }
+
+    Proof first;
+    retval.push_back(first);
+    
+    Curvepoint g = EL_GAMAL_GENERATOR;
+    Curvepoint h = elGamalBlindGenerator;
+
+    std::stringstream oracleInput;
+    oracleInput << g << h << nextGenerator;
+
+    for (size_t i = 0; i < currPseudonyms.size(); i++)
+        oracleInput << currPseudonyms[i];
+
+    for (size_t i = 0; i < userTallyMasks.size(); i++)
+        oracleInput << userTallyMasks[i];
+
+    for (size_t i = 0; i < userTallyMessages.size(); i++)
+        oracleInput << userTallyMessages[i];
+
+    for (size_t i = 0; i < permutationCommits.size(); i++)
+        for (size_t j = 0; j < permutationCommits[i].size(); j++)
+            oracleInput << permutationCommits[i][j];
+
+    for (size_t i = 0; i < userTallyMaskCommits.size(); i++)
+        for (size_t j = 0; j < userTallyMaskCommits[i].size(); j++)
+            oracleInput << userTallyMaskCommits[i][j];
+
+    for (size_t i = 0; i < userTallyMessageCommits.size(); i++)
+        for (size_t j = 0; j < userTallyMessageCommits[i].size(); j++)
+            oracleInput << userTallyMessageCommits[i][j];
+
+    for (size_t i = 0; i < userTallySeedCommits.size(); i++)
+        for (size_t j = 0; j < userTallySeedCommits[i].size(); j++)
+            oracleInput << userTallySeedCommits[i][j];
+
+    Scalar b1;
+    b1.set_random();
+    std::vector<std::vector<Scalar>> b2;
+    std::vector<std::vector<Scalar>> t1;
+    std::vector<std::vector<Scalar>> t2;
+
+    for (size_t i = 0; i < permutationCommits.size(); i++)
+    {
+        std::vector<Scalar> currb2Row;
+        std::vector<Scalar> currt1Row;
+        std::vector<Scalar> currt2Row;
+
+        for (size_t j = 0; j < permutationCommits[i].size(); j++)
+        {
+            Proof currProof;
+
+            Scalar currb2;
+            Scalar currt1;
+            Scalar currt2;
+
+            Curvepoint U1, U2, U3, U4, U5, U6, U7;
+
+            currb2.set_random();
+            currt1.set_random();
+            currt2.set_random();
+
+            U1 = g * currb2 + h * currt1;
+            U2 = userTallyMasks[j] *
+                (b1 * permutations[j][i] + currb2 * power) +
+                currPseudonyms[j] *
+                (permutations[j][i] * b1 * userTallySeeds[i][j] +
+                    power * currb2 * userTallySeeds[i][j] +
+                    permutations[j][i] * power * currt2) +
+                h * currt2;
+            U3 = userTallyMasks[j] * (b1 * currb2) +
+                currPseudonyms[j] *
+                (b1 * currb2 * userTallySeeds[i][j] +
+                    permutations[j][i] * b1 * currt2 +
+                    power * currb2 * currt2);
+            U4 = currPseudonyms[j] * (b1 * currb2 * currt2);
+            U5 = userTallyMessages[j] * currb2 +
+                nextGenerator * (permutations[j][i] * currt2 +
+                    userTallySeeds[i][j] * currb2) +
+                h * currt2;
+            U6 = nextGenerator * (currb2 * currt2);
+            U7 = g * currt2;
+
+            currProof.curvepointUniversals.push_back(U2);
+            currProof.curvepointUniversals.push_back(U3);
+            currProof.curvepointUniversals.push_back(U5);
+
+            oracleInput << U1 << U2 << U3 << U4 << U5 << U6 << U7;
+
+            currb2Row.push_back(currb2);
+            currt1Row.push_back(currt1);
+            currt2Row.push_back(currt2);
+
+            retval.push_back(currProof);
+        }
+
+        b2.push_back(currb2Row);
+        t1.push_back(currt1Row);
+        t2.push_back(currt2Row);
+    }
+
+    Scalar x = oracle(oracleInput.str());
+    retval[0].challengeParts.push_back(x);
+
+    Scalar f1 = power * x + b1;
+    retval[0].responseParts.push_back(f1);
+
+    for (size_t i = 0; i < permutationCommits.size(); i++)
+    {
+        for (size_t j = 0; j < permutationCommits[i].size(); j++)
+        {
+            size_t piIndex = i * permutationCommits.size() + j + 1;
+
+            Scalar f2 = permutations[j][i] * x + b2[i][j];
+            Scalar z1 = permutationSeeds[j][i] * x + t1[i][j];
+            Scalar z2 = userTallySeeds[i][j] * x + t2[i][j];
+
+            retval[piIndex].responseParts.push_back(f2);
+            retval[piIndex].responseParts.push_back(z1);
+            retval[piIndex].responseParts.push_back(z2);
+        }
+    }
+
+    return retval;
+}
+
+bool PrsonaBase::verify_user_tally_proofs(
+    const std::vector<Proof>& pi,
+    const Curvepoint& nextGenerator,
+    const std::vector<Curvepoint>& currPseudonyms,
+    const std::vector<Curvepoint>& userTallyMasks,
+    const std::vector<Curvepoint>& userTallyMessages,
+    const std::vector<std::vector<Curvepoint>>& permutationCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallySeedCommits) const
+{
+    if (pi.empty())
+        return false;
+
+    if (!SERVER_IS_MALICIOUS)
+        return pi[0].hbc == "PROOF";
+    
+    Curvepoint g = EL_GAMAL_GENERATOR;
+    Curvepoint h = elGamalBlindGenerator;
+
+    std::stringstream oracleInput;
+    oracleInput << g << h << nextGenerator;
+
+    for (size_t i = 0; i < currPseudonyms.size(); i++)
+        oracleInput << currPseudonyms[i];
+
+    for (size_t i = 0; i < userTallyMasks.size(); i++)
+        oracleInput << userTallyMasks[i];
+
+    for (size_t i = 0; i < userTallyMessages.size(); i++)
+        oracleInput << userTallyMessages[i];
+
+    for (size_t i = 0; i < permutationCommits.size(); i++)
+        for (size_t j = 0; j < permutationCommits[i].size(); j++)
+            oracleInput << permutationCommits[i][j];
+
+    for (size_t i = 0; i < userTallyMaskCommits.size(); i++)
+        for (size_t j = 0; j < userTallyMaskCommits[i].size(); j++)
+            oracleInput << userTallyMaskCommits[i][j];
+
+    for (size_t i = 0; i < userTallyMessageCommits.size(); i++)
+        for (size_t j = 0; j < userTallyMessageCommits[i].size(); j++)
+            oracleInput << userTallyMessageCommits[i][j];
+
+    for (size_t i = 0; i < userTallySeedCommits.size(); i++)
+        for (size_t j = 0; j < userTallySeedCommits[i].size(); j++)
+            oracleInput << userTallySeedCommits[i][j];
+
+    Scalar x = pi[0].challengeParts[0];
+    Scalar f1 = pi[0].responseParts[0];
+
+    for (size_t i = 0; i < permutationCommits.size(); i++)
+    {
+        for (size_t j = 0; j < permutationCommits[i].size(); j++)
+        {
+            size_t piIndex = i * permutationCommits.size() + j + 1;
+
+            Curvepoint U1, U2, U3, U4, U5, U6, U7;
+            U2 = pi[piIndex].curvepointUniversals[0];
+            U3 = pi[piIndex].curvepointUniversals[1];
+            U5 = pi[piIndex].curvepointUniversals[2];
+
+            Scalar f2 = pi[piIndex].responseParts[0];
+            Scalar z1 = pi[piIndex].responseParts[1];
+            Scalar z2 = pi[piIndex].responseParts[2];
+
+            U1 = g * f2 + h * z1 - permutationCommits[j][i] * x;
+            
+            U4 = userTallyMasks[j] * (f1 * f2 * x) +
+                currPseudonyms[j] * (f1 * f2 * z2) +
+                h * (z2 * x * x) -
+                userTallyMaskCommits[i][j] * (x * x * x) -
+                U2 * (x * x) -
+                U3 * x;
+
+            U6 = userTallyMessages[j] * (f2 * x) +
+                nextGenerator * (f2 * z2) +
+                h * (z2 * x) -
+                userTallyMessageCommits[i][j] * (x * x) -
+                U5 * x;
+
+            U7 = g * z2 - userTallySeedCommits[i][j] * x;
+
+            oracleInput << U1 << U2 << U3 << U4 << U5 << U6 << U7;
+        }
+    }
+
+    if (x != oracle(oracleInput.str()))
+    {
+        std::cerr << "User tallies not generated by permutation matrix." << std::endl;
+        return false;
+    }
+
+    for (size_t i = 0; i < userTallySeedCommits.size(); i++)
+    {
+        Curvepoint sum = userTallySeedCommits[i][0];
+
+        for (size_t j = 1; j < userTallySeedCommits[i].size(); j++)
+            sum = sum + userTallySeedCommits[i][j];
+
+        if (sum != Curvepoint())
+        {
+            std::cerr << "seed commits did not sum to 0, aborting." << std::endl;
+            return false;
+        }
+    }
+
+    return true;
+}
+
 template <typename T>
 std::vector<Proof> PrsonaBase::generate_proof_of_reordering(
     const std::vector<std::vector<Scalar>>& permutations,
@@ -1132,6 +1394,9 @@ std::vector<Proof> PrsonaBase::generate_proof_of_reordering(
     std::stringstream oracleInput;
     oracleInput << g << h << otherG << otherH;
 
+    for (size_t i = 0; i < oldValues.size(); i++)
+        oracleInput << oldValues[i];
+
     for (size_t i = 0; i < permutationCommits.size(); i++)
         for (size_t j = 0; j < permutationCommits[i].size(); j++)
             oracleInput << permutationCommits[i][j];
@@ -1225,6 +1490,9 @@ bool PrsonaBase::verify_proof_of_reordering(
     std::stringstream oracleInput;
     oracleInput << g << h << otherG << otherH;
 
+    for (size_t i = 0; i < oldValues.size(); i++)
+        oracleInput << oldValues[i];
+
     for (size_t i = 0; i < permutationCommits.size(); i++)
         for (size_t j = 0; j < permutationCommits[i].size(); j++)
             oracleInput << permutationCommits[i][j];

+ 1 - 0
prsona/src/client.cpp

@@ -109,6 +109,7 @@ bool PrsonaClient::receive_vote_tally()
 {
     Proof pi;
     Curvepoint shortTermPublicKey = get_short_term_public_key();
+
     EGCiphertext score =
         servers->get_current_user_encrypted_tally(pi, shortTermPublicKey);
 

+ 111 - 11
prsona/src/main.cpp

@@ -273,15 +273,115 @@ void test_vote_proof(
         << endl << endl;
 }
 
+void check_vote_matrix_updates()
+{
+    size_t numServers = 2;
+    size_t numUsers = 3;
+
+    cout << "Testing how the vote matrix updates." << endl;
+
+    PrsonaBase::set_client_malicious();
+
+    // Entities we operate with
+    PrsonaServerEntity servers(numServers);
+    vector<Proof> elGamalBlindGeneratorProof;
+    BGNPublicKey bgnPublicKey = servers.get_bgn_public_key();
+    Curvepoint elGamalBlindGenerator =
+        servers.get_blinding_generator(elGamalBlindGeneratorProof);
+
+    vector<PrsonaClient> users;
+    for (size_t i = 0; i < numUsers; i++)
+    {
+        PrsonaClient currUser(
+            elGamalBlindGeneratorProof,
+            elGamalBlindGenerator,
+            bgnPublicKey,
+            &servers);
+        users.push_back(currUser);
+        servers.add_new_client(users[i]);
+    }
+
+    Proof pseudonymsProof;
+    vector<Curvepoint> currentPseudonyms =
+        servers.get_current_pseudonyms(pseudonymsProof);
+
+    cout << "Making votes." << endl;
+
+    for (size_t i = 0; i < numUsers; i++)
+    {   
+        Proof ownerProof;
+        Curvepoint shortTermPublicKey =
+            users[i].get_short_term_public_key(ownerProof);
+
+        size_t myIndex =
+            users[i].binary_search(currentPseudonyms, shortTermPublicKey);
+
+        cout << "User " << i+1 << " has initial index " << myIndex << endl;
+
+        vector<Scalar> votes;
+        vector<bool> replaces;
+        for (size_t j = 0; j < numUsers; j++)
+        {
+            if (j == myIndex)
+                votes.push_back(Scalar(2));
+            else if (j > myIndex)
+                votes.push_back(Scalar(1));
+            else
+                votes.push_back(Scalar(0));
+            replaces.push_back(true);
+        }
+
+        vector<CurveBipoint> currEncryptedVotes =
+            servers.get_current_votes_by(ownerProof, shortTermPublicKey);
+        vector<Proof> currVoteProof;
+    
+        currEncryptedVotes = users[i].make_votes(
+                                currVoteProof,
+                                ownerProof,
+                                currEncryptedVotes,
+                                votes,
+                                replaces);
+
+        servers.receive_vote(
+                currVoteProof,
+                currEncryptedVotes,
+                shortTermPublicKey);
+        cout << "User " << i+1 << " now has the following votes:" << endl;
+        servers.print_current_votes_by(shortTermPublicKey);
+    }
+    
+    servers.print_votes();
+    
+    epoch(servers);
+
+    cout << "First epoch done." << endl;
+        
+    transmit_epoch_updates(users, servers);
+
+    cout << "Updates given to users." << endl;
+
+    servers.print_votes();
+
+    for (size_t i = 0; i < numUsers; i++)
+    {   
+        Proof ownerProof;
+        Curvepoint shortTermPublicKey =
+            users[i].get_short_term_public_key(ownerProof);
+
+        cout << "User " << i+1 << " now has the following votes:" << endl;
+        servers.print_current_votes_by(shortTermPublicKey);
+    }
+}
+
 int main(int argc, char *argv[])
 {
     initialize_prsona_classes();
 
     // Defaults
     size_t numServers = 2;
-    size_t numUsers = 3;
-    size_t numRounds = 1;
-    size_t numVotesPerRound = 1;
+    size_t numUsers = 5;
+    size_t numRounds = 3;
+    size_t numVotesPerRound = 3;
     bool maliciousServers = true;
     bool maliciousClients = true;
     string seedStr = "seed";
@@ -372,15 +472,15 @@ int main(int argc, char *argv[])
             << " seconds per user" << endl << endl;
     }
 
-    // // Pick random users for our tests
-    // uniform_int_distribution<size_t> userDistribution(0, numUsers - 1);
-    // size_t user_a = userDistribution(generator);
-    // size_t user_b = user_a;
-    // while (user_b == user_a)
-    //     user_b = userDistribution(generator);
+    // Pick random users for our tests
+    uniform_int_distribution<size_t> userDistribution(0, numUsers - 1);
+    size_t user_a = userDistribution(generator);
+    size_t user_b = user_a;
+    while (user_b == user_a)
+        user_b = userDistribution(generator);
 
-    // test_reputation_proof(generator, users[user_a], users[user_b]);
-    // test_vote_proof(generator, users[user_a], servers);
+    test_reputation_proof(generator, users[user_a], users[user_b]);
+    test_vote_proof(generator, users[user_a], servers);
 
     return 0;
 }

+ 177 - 209
prsona/src/server.cpp

@@ -395,7 +395,8 @@ void PrsonaServer::build_up_midway_pseudonyms(
     std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymCommits,
     std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymSeedCommits,
     std::vector<std::vector<std::vector<TwistBipoint>>>& serverTallyCommits,
-    std::vector<std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>>& voteMatrixCommits,
+    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& partwayVoteMatrixCommits,
+    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& finalVoteMatrixCommits,
     Curvepoint& nextGenerator)
 {
     nextSeed.set_random();
@@ -404,25 +405,31 @@ void PrsonaServer::build_up_midway_pseudonyms(
     std::vector<std::vector<Curvepoint>> currFreshPseudonymCommits;
     std::vector<std::vector<Curvepoint>> currFreshPseudonymSeedCommits;
     std::vector<std::vector<TwistBipoint>> currServerTallyCommits;
-    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>> currVoteMatrixCommits;
-    std::vector<std::vector<std::vector<Curvepoint>>> currUserTallyCommits;
-    std::vector<std::vector<Curvepoint>> currUserTallyMaskSeedCommits;
+    std::vector<std::vector<std::vector<CurveBipoint>>> currPartwayVoteMatrixCommits;
+    std::vector<std::vector<std::vector<CurveBipoint>>> currFinalVoteMatrixCommits;
+    std::vector<std::vector<Curvepoint>> currUserTallyMaskCommits;
+    std::vector<std::vector<Curvepoint>> currUserTallyMessageCommits;
+    std::vector<std::vector<Curvepoint>> currUserTallySeedCommits;
     pi.push_back(epoch_calculations(
         currPermutationCommits,
         currFreshPseudonymCommits,
         currFreshPseudonymSeedCommits,
         currServerTallyCommits,
-        currVoteMatrixCommits,
-        currUserTallyCommits,
-        currUserTallyMaskSeedCommits,
+        currPartwayVoteMatrixCommits,
+        currFinalVoteMatrixCommits,
+        currUserTallyMaskCommits,
+        currUserTallyMessageCommits,
+        currUserTallySeedCommits,
         nextSeed,
+        nextGenerator,
         false));
 
     permutationCommits.push_back(currPermutationCommits);
     freshPseudonymCommits.push_back(currFreshPseudonymCommits);
     freshPseudonymSeedCommits.push_back(currFreshPseudonymSeedCommits);
     serverTallyCommits.push_back(currServerTallyCommits);
-    voteMatrixCommits.push_back(currVoteMatrixCommits);
+    partwayVoteMatrixCommits.push_back(currPartwayVoteMatrixCommits);
+    finalVoteMatrixCommits.push_back(currFinalVoteMatrixCommits);
 
     pi[0][0].push_back(
         add_to_generator_proof(nextGenerator, nextSeed));
@@ -440,9 +447,11 @@ void PrsonaServer::break_down_midway_pseudonyms(
     std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymCommits,
     std::vector<std::vector<std::vector<Curvepoint>>>& freshPseudonymSeedCommits,
     std::vector<std::vector<std::vector<TwistBipoint>>>& serverTallyCommits,
-    std::vector<std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>>& voteMatrixCommits,
-    std::vector<std::vector<std::vector<std::vector<Curvepoint>>>>& userTallyCommits,
-    std::vector<std::vector<std::vector<Curvepoint>>>& userTallyMaskSeedCommits,
+    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& partwayVoteMatrixCommits,
+    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& finalVoteMatrixCommits,
+    std::vector<std::vector<std::vector<Curvepoint>>>& userTallyMaskCommits,
+    std::vector<std::vector<std::vector<Curvepoint>>>& userTallyMessageCommits,
+    std::vector<std::vector<std::vector<Curvepoint>>>& userTallySeedCommits,
     const Curvepoint& nextGenerator)
 {
     if (!initialize_fresh_generator(generatorProof, nextGenerator))
@@ -457,27 +466,34 @@ void PrsonaServer::break_down_midway_pseudonyms(
     std::vector<std::vector<Curvepoint>> currFreshPseudonymCommits;
     std::vector<std::vector<Curvepoint>> currFreshPseudonymSeedCommits;
     std::vector<std::vector<TwistBipoint>> currServerTallyCommits;
-    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>> currVoteMatrixCommits;
-    std::vector<std::vector<std::vector<Curvepoint>>> currUserTallyCommits;
-    std::vector<std::vector<Curvepoint>> currUserTallyMaskSeedCommits;
+    std::vector<std::vector<std::vector<CurveBipoint>>> currPartwayVoteMatrixCommits;
+    std::vector<std::vector<std::vector<CurveBipoint>>> currFinalVoteMatrixCommits;
+    std::vector<std::vector<Curvepoint>> currUserTallyMaskCommits;
+    std::vector<std::vector<Curvepoint>> currUserTallyMessageCommits;
+    std::vector<std::vector<Curvepoint>> currUserTallySeedCommits;
     pi.push_back(epoch_calculations(
         currPermutationCommits,
         currFreshPseudonymCommits,
         currFreshPseudonymSeedCommits,
         currServerTallyCommits,
-        currVoteMatrixCommits,
-        currUserTallyCommits,
-        currUserTallyMaskSeedCommits,
+        currPartwayVoteMatrixCommits,
+        currFinalVoteMatrixCommits,
+        currUserTallyMaskCommits,
+        currUserTallyMessageCommits,
+        currUserTallySeedCommits,
         inverseSeed,
+        nextGenerator,
         true));
 
     permutationCommits.push_back(currPermutationCommits);
     freshPseudonymCommits.push_back(currFreshPseudonymCommits);
     freshPseudonymSeedCommits.push_back(currFreshPseudonymSeedCommits);
     serverTallyCommits.push_back(currServerTallyCommits);
-    voteMatrixCommits.push_back(currVoteMatrixCommits);
-    userTallyCommits.push_back(currUserTallyCommits);
-    userTallyMaskSeedCommits.push_back(currUserTallyMaskSeedCommits);
+    partwayVoteMatrixCommits.push_back(currPartwayVoteMatrixCommits);
+    finalVoteMatrixCommits.push_back(currFinalVoteMatrixCommits);
+    userTallyMaskCommits.push_back(currUserTallyMaskCommits);
+    userTallyMessageCommits.push_back(currUserTallyMessageCommits);
+    userTallySeedCommits.push_back(currUserTallySeedCommits);
 
     currentSeed = nextSeed;
 }
@@ -491,41 +507,28 @@ std::vector<std::vector<Proof>> PrsonaServer::epoch_calculations(
     std::vector<std::vector<Curvepoint>>& freshPseudonymCommits,
     std::vector<std::vector<Curvepoint>>& freshPseudonymSeedCommits,
     std::vector<std::vector<TwistBipoint>>& serverTallyCommits,
-    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& voteMatrixCommits,
-    std::vector<std::vector<std::vector<Curvepoint>>>& userTallyCommits,
-    std::vector<std::vector<Curvepoint>> & userTallyMaskSeedCommits,
+    std::vector<std::vector<std::vector<CurveBipoint>>>& partwayVoteMatrixCommits,
+    std::vector<std::vector<std::vector<CurveBipoint>>>& finalVoteMatrixCommits,
+    std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+    std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+    std::vector<std::vector<Curvepoint>>& userTallySeedCommits,
     const Scalar& power,
+    const Curvepoint& nextGenerator,
     bool doUserTallies)
 {
     std::vector<std::vector<Proof>> retval;
 
-    std::vector<Curvepoint> nextPseudonyms;
-    for (size_t i = 0; i < currentPseudonyms.size(); i++)
-        nextPseudonyms.push_back(currentPseudonyms[i] * power);
-
-    std::vector<size_t> order = sort_data(nextPseudonyms);
-    for (size_t i = 0; i < currentPseudonyms.size(); i++)
-        nextPseudonyms[i] = currentPseudonyms[order[i]] * power;
-
-    std::cout << "Generating permutation matrix." << std::endl;
-
     std::vector<std::vector<Scalar>> permutations =
         generate_permutation_matrix(power);
 
-    std::cout << "Generating permutation commitment matrix." << std::endl;
-
     std::vector<std::vector<Scalar>> permutationSeeds;
     permutationCommits.clear();
     permutationCommits = 
         generate_commitment_matrix(permutations, permutationSeeds);
 
-    std::cout << "Generating permutation proof." << std::endl;
-
     retval.push_back(generate_valid_permutation_proof(
         permutations, permutationSeeds, permutationCommits));
 
-    std::cout << "Generating pseudonym matrix." << std::endl;
-
     std::vector<std::vector<Scalar>> freshPseudonymSeeds;
     freshPseudonymSeedCommits.clear();
     freshPseudonymCommits.clear();
@@ -536,17 +539,6 @@ std::vector<std::vector<Proof>> PrsonaServer::epoch_calculations(
             freshPseudonymSeeds,
             freshPseudonymSeedCommits);
 
-    // for (size_t i = 0; i < freshPseudonymCommits.size(); i++)
-    // {
-    //     Curvepoint sum = freshPseudonymCommits[i][0];
-    //     for (size_t j = 1; j < freshPseudonymCommits[i].size(); j++)
-    //         sum = sum + freshPseudonymCommits[i][j];
-    //     std::cout << "Fresh pseudonym commit row " << i + 1 << " of " << permutationCommits.size()
-    //         << (sum == nextPseudonyms[i] ? ": PASS" : ": FAIL") << std::endl;
-    // }
-
-    std::cout << "Generating pseudonym proof." << std::endl;
-
     retval.push_back(
         generate_proof_of_reordering_plus_power(
             permutations,
@@ -558,8 +550,6 @@ std::vector<std::vector<Proof>> PrsonaServer::epoch_calculations(
             freshPseudonymCommits,
             freshPseudonymSeedCommits));
 
-    std::cout << "Generating server tally matrix." << std::endl;
-
     std::vector<std::vector<Scalar>> serverTallySeeds;
     serverTallyCommits.clear();
     serverTallyCommits = 
@@ -567,8 +557,6 @@ std::vector<std::vector<Proof>> PrsonaServer::epoch_calculations(
             permutations,
             serverTallySeeds);
 
-    std::cout << "Generating server tally proof." << std::endl;
-
     retval.push_back(
         generate_proof_of_reordering<TwistBipoint>(
             permutations,
@@ -580,109 +568,88 @@ std::vector<std::vector<Proof>> PrsonaServer::epoch_calculations(
             bgnSystem.get_public_key().get_bipoint_twistgen(),
             bgnSystem.get_public_key().get_bipoint_twist_subgroup_gen()));
 
-    std::cout << "Doing V * P." << std::endl;
-
-    std::vector<std::vector<std::vector<Scalar>>> firstVoteMatrixSeeds;
-    std::vector<std::vector<std::vector<Scalar>>> secondVoteMatrixSeeds;
-    voteMatrixCommits.push_back(
-        generate_vote_tensor(
-            permutations,
-            voteMatrix,
-            firstVoteMatrixSeeds,
-            false));
-
-    std::cout << "Finishing V * P calculation." << std::endl;
+    std::vector<std::vector<std::vector<Scalar>>> partwayVoteMatrixSeeds;
+    std::vector<std::vector<std::vector<Scalar>>> finalVoteMatrixSeeds;
+    partwayVoteMatrixCommits.clear();
+    partwayVoteMatrixCommits = generate_vote_tensor(
+        permutations,
+        voteMatrix,
+        partwayVoteMatrixSeeds,
+        false);
 
     std::vector<std::vector<CurveBipoint>> partialVoteMatrix = 
-        calculate_next_vote_matrix(voteMatrixCommits[0]);
+        calculate_next_vote_matrix(partwayVoteMatrixCommits);
 
-    std::cout << "Doing P^T * (V * P)." << std::endl;
-
-    voteMatrixCommits.push_back(
-        generate_vote_tensor(
-            permutations,
-            partialVoteMatrix,
-            secondVoteMatrixSeeds,
-            true));
-
-    std::cout << "Proving V * P." << std::endl;
+    finalVoteMatrixCommits.clear();
+    finalVoteMatrixCommits = generate_vote_tensor(
+        permutations,
+        partialVoteMatrix,
+        finalVoteMatrixSeeds,
+        true);
 
     generate_vote_tensor_proofs(
         retval,
         permutations,
         permutationSeeds,
-        firstVoteMatrixSeeds,
+        partwayVoteMatrixSeeds,
         voteMatrix,
         permutationCommits,
-        voteMatrixCommits[0],
+        partwayVoteMatrixCommits,
         false);
 
-    std::cout << "Proving P^T * (V * P)." << std::endl;
-
     generate_vote_tensor_proofs(
         retval,
         permutations,
         permutationSeeds,
-        secondVoteMatrixSeeds,
+        finalVoteMatrixSeeds,
         partialVoteMatrix,
         permutationCommits,
-        voteMatrixCommits[1],
+        finalVoteMatrixCommits,
         true);
 
     if (doUserTallies)
     {
-        std::cout << "Generating user tally matrix." << std::endl;
-
         std::vector<Curvepoint> userTallyMasks;
-        std::vector<std::vector<Scalar>> userTallyMaskSeeds;
-        userTallyMaskSeedCommits.clear();
         std::vector<Curvepoint> userTallyMessages;
-        std::vector<std::vector<Scalar>> userTallyMessageSeeds;
-        userTallyCommits = 
-            generate_user_tally_matrix(
-                permutations,
-                power,
-                userTallyMasks,
-                userTallyMessages,
-                userTallyMaskSeeds,
-                userTallyMaskSeedCommits,
-                userTallyMessageSeeds);
-
-        std::cout << "Proving user tally mask matrix." << std::endl;
+        std::vector<std::vector<Scalar>> userTallySeeds;
+        userTallyMaskCommits.clear();
+        userTallyMessageCommits.clear();
+        userTallySeedCommits.clear();
+        generate_user_tally_matrix(
+            permutations,
+            power,
+            nextGenerator,
+            currentPseudonyms,
+            userTallyMasks,
+            userTallyMaskCommits,
+            userTallyMessages,
+            userTallyMessageCommits,
+            userTallySeeds,
+            userTallySeedCommits);
 
         retval.push_back(
-            generate_proof_of_reordering_plus_power(
+            generate_user_tally_proofs(
                 permutations,
                 power,
+                nextGenerator,
                 permutationSeeds,
-                userTallyMaskSeeds,
+                userTallySeeds,
+                currentPseudonyms,
                 userTallyMasks,
-                permutationCommits,
-                userTallyCommits[0],
-                userTallyMaskSeedCommits));
-
-        std::cout << "Proving user tally message matrix." << std::endl;
-
-        retval.push_back(
-            generate_proof_of_reordering<Curvepoint>(
-                permutations,
-                permutationSeeds,
-                userTallyMessageSeeds,
                 userTallyMessages,
                 permutationCommits,
-                userTallyCommits[1],
-                EL_GAMAL_GENERATOR,
-                elGamalBlindGenerator));
+                userTallyMaskCommits,
+                userTallyMessageCommits,
+                userTallySeedCommits));
     }
 
-    std::cout << "Giving self updates." << std::endl;
-
     // Replace internal values
     update_data(
         freshPseudonymCommits,
         serverTallyCommits,
-        voteMatrixCommits[1],
-        userTallyCommits);
+        finalVoteMatrixCommits,
+        userTallyMaskCommits,
+        userTallyMessageCommits);
 
     return retval;
 }
@@ -693,14 +660,17 @@ bool PrsonaServer::accept_epoch_updates(
     const std::vector<std::vector<Curvepoint>>& freshPseudonymCommits,
     const std::vector<std::vector<Curvepoint>>& freshPseudonymSeedCommits,
     const std::vector<std::vector<TwistBipoint>>& serverTallyCommits,
-    const std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>& voteMatrixCommits,
-    const std::vector<std::vector<std::vector<Curvepoint>>>& userTallyCommits,
-    const std::vector<std::vector<Curvepoint>>& userTallyMaskSeedCommits,
+    const std::vector<std::vector<std::vector<CurveBipoint>>>& partwayVoteMatrixCommits,
+    const std::vector<std::vector<std::vector<CurveBipoint>>>& finalVoteMatrixCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallySeedCommits,
+    const Curvepoint& nextGenerator,
     bool doUserTallies)
 {
     bool verification;
 
-    if ((userTallyCommits.empty() && doUserTallies) || (!userTallyCommits.empty() && !doUserTallies))
+    if ((userTallyMaskCommits.empty() && doUserTallies) || (!userTallyMaskCommits.empty() && !doUserTallies))
     {
         std::cerr << "user tallies are not in expected state." << std::endl;
         return false;
@@ -709,83 +679,76 @@ bool PrsonaServer::accept_epoch_updates(
     if (pi.empty())
         return false;
 
-    std::cout << "Verifying valid permutation matrix." << std::endl;
+    size_t currOffset = 0;
 
     verification =
-        verify_valid_permutation_proof(pi[0], permutationCommits);
+        verify_valid_permutation_proof(pi[currOffset], permutationCommits);
+    currOffset++;
     if (!verification)
     {
         std::cerr << "Could not verify valid permutation matrix." << std::endl;
         return false;
     }
 
-    std::cout << "Verifying valid pseudonym vector." << std::endl;
-
     verification = 
         verify_proof_of_reordering_plus_power(
-            pi[1],
+            pi[currOffset],
             currentPseudonyms,
             permutationCommits,
             freshPseudonymCommits,
             freshPseudonymSeedCommits);
+    currOffset++;
     if (!verification)
     {
         std::cerr << "Could not verify valid pseudonym vector." << std::endl;
         return false;
     }
 
-    std::cout << "Verifying valid server tally vector." << std::endl;
-
     verification = 
         verify_proof_of_reordering<TwistBipoint>(
-            pi[2],
+            pi[currOffset],
             previousVoteTallies,
             permutationCommits,
             serverTallyCommits,
             bgnSystem.get_public_key().get_bipoint_twistgen(),
             bgnSystem.get_public_key().get_bipoint_twist_subgroup_gen());
+    currOffset++;
     if (!verification)
     {
         std::cerr << "Could not verify valid server tally vector." << std::endl;
         return false;
     }
 
-    std::cout << "Verifying valid first half vote matrix." << std::endl;
-
-    size_t currOffset = 3;
     verification = verify_vote_tensor_proofs(
         pi,
         currOffset,
         voteMatrix,
         permutationCommits,
-        voteMatrixCommits[0],
+        partwayVoteMatrixCommits,
         false);
+    currOffset += voteMatrix.size();
     if (!verification)
     {
         std::cerr << "Could not verify first half vote matrix." << std::endl;
         return false;
     }
 
-    std::cout << "Verifying valid second half vote matrix." << std::endl;
-
     std::vector<std::vector<CurveBipoint>> partialVoteMatrix =
-        calculate_next_vote_matrix(voteMatrixCommits[0]);
-    currOffset += voteMatrix.size();
+        calculate_next_vote_matrix(partwayVoteMatrixCommits);
     verification = verify_vote_tensor_proofs(
         pi,
         currOffset,
         partialVoteMatrix,
         permutationCommits,
-        voteMatrixCommits[1],
+        finalVoteMatrixCommits,
         true);
+    currOffset += voteMatrix.size();
     if (!verification)
     {
         std::cerr << "Could not verify second half vote matrix." << std::endl;
         return false;
     }
 
-    currOffset += voteMatrix.size();
-
     if (doUserTallies)
     {
         std::vector<Curvepoint> userTallyMasks;
@@ -796,45 +759,30 @@ bool PrsonaServer::accept_epoch_updates(
             userTallyMessages.push_back(currentUserEncryptedTallies[i].encryptedMessage);
         }
 
-        std::cout << "Verifying valid user tally masks." << std::endl;
-
-        verification = verify_proof_of_reordering_plus_power(
+        verification = verify_user_tally_proofs(
             pi[currOffset],
+            nextGenerator,
+            currentPseudonyms,
             userTallyMasks,
-            permutationCommits,
-            userTallyCommits[0],
-            userTallyMaskSeedCommits);
-        if (!verification)
-        {
-            std::cerr << "Could not verify user tally masks." << std::endl;
-            return false;
-        }
-
-        currOffset++;
-
-        std::cout << "Verifying valid user tally messages." << std::endl;
-
-        verification = verify_proof_of_reordering<Curvepoint>(
-            pi[currOffset],
             userTallyMessages,
             permutationCommits,
-            userTallyCommits[1],
-            EL_GAMAL_GENERATOR,
-            elGamalBlindGenerator);
+            userTallyMaskCommits,
+            userTallyMessageCommits,
+            userTallySeedCommits);
+        currOffset++;
         if (!verification)
         {
-            std::cerr << "Could not verify user tally messages." << std::endl;
+            std::cerr << "Could not verify user tallies." << std::endl;
             return false;
         }
     }
 
-    std::cout << "Verifying pseudonyms are all different." << std::endl;
-
     verification = update_data(
         freshPseudonymCommits,
         serverTallyCommits,
-        voteMatrixCommits[1],
-        userTallyCommits);
+        finalVoteMatrixCommits,
+        userTallyMaskCommits,
+        userTallyMessageCommits);
 
     return verification;
 }
@@ -861,17 +809,6 @@ std::vector<std::vector<Scalar>> PrsonaServer::generate_permutation_matrix(
     for (size_t i = 0; i < order.size(); i++)
         retval[order[i]][i] = Scalar(1);
 
-    std::cout << "[";
-    for (size_t i = 0; i < order.size(); i++)
-    {
-        std::cout << "[";
-        for (size_t j = 0; j < order.size(); j++)
-        {
-            std::cout << retval[i][j] << (j == order.size() - 1 ? "]" : " ");
-        }
-        std::cout << (i == order.size() - 1 ? "]" : " ") << std::endl << (i == order.size() - 1 ? "" : " ");
-    }
-
     return retval;
 }
 
@@ -1076,17 +1013,18 @@ bool PrsonaServer::verify_vote_tensor_proofs(
     return retval;
 }
 
-std::vector<std::vector<std::vector<Curvepoint>>> PrsonaServer::generate_user_tally_matrix(
+void PrsonaServer::generate_user_tally_matrix(
     const std::vector<std::vector<Scalar>>& permutations,
     const Scalar& power,
+    const Curvepoint& nextGenerator,
+    const std::vector<Curvepoint>& currPseudonyms,
     std::vector<Curvepoint>& masks,
+    std::vector<std::vector<Curvepoint>>& maskCommits,
     std::vector<Curvepoint>& messages,
-    std::vector<std::vector<Scalar>>& maskSeeds,
-    std::vector<std::vector<Curvepoint>>& maskSeedCommits,
-    std::vector<std::vector<Scalar>>& messageSeeds) const
+    std::vector<std::vector<Curvepoint>>& messageCommits,
+    std::vector<std::vector<Scalar>>& userTallySeeds,
+    std::vector<std::vector<Curvepoint>>& userTallySeedCommits) const
 {
-    std::vector<std::vector<std::vector<Curvepoint>>> retval;
-
     masks.clear();
     messages.clear();
     for (size_t i = 0; i < currentUserEncryptedTallies.size(); i++)
@@ -1095,24 +1033,53 @@ std::vector<std::vector<std::vector<Curvepoint>>> PrsonaServer::generate_user_ta
         messages.push_back(currentUserEncryptedTallies[i].encryptedMessage);
     }
 
-    retval.push_back(
-        generate_reordered_plus_power_matrix<Curvepoint>(
-            permutations,
-            power,
-            masks,
-            maskSeeds,
-            maskSeedCommits,
-            elGamalBlindGenerator));
+    maskCommits.clear();
+    messageCommits.clear();
+    userTallySeeds.clear();
+    userTallySeedCommits.clear();
 
-    retval.push_back(
-        generate_reordered_matrix<Curvepoint>(
-            permutations,
-            messages,
-            messageSeeds,
-            elGamalBlindGenerator,
-            false));
+    for (size_t i = 0; i < permutations.size(); i++)
+    {
+        std::vector<Scalar> currSeeds;
+        std::vector<Curvepoint> currRow;
+        for (size_t j = 0; j < permutations[i].size(); j++)
+        {
+            currSeeds.push_back(Scalar(0));
+            currRow.push_back(Curvepoint());
+        }
+        userTallySeeds.push_back(currSeeds);
+        maskCommits.push_back(currRow);
+        messageCommits.push_back(currRow);
+        userTallySeedCommits.push_back(currRow);
+    }
 
-    return retval;
+    for (size_t i = 0; i < permutations.size(); i++)
+    {
+        size_t last = permutations[i].size() - 1;
+        for (size_t j = 0; j < permutations[i].size(); j++)
+        {
+            if (j != last)
+            {
+                userTallySeeds[i][j].set_random();
+                userTallySeeds[i][last] =
+                    userTallySeeds[i][last] -
+                    userTallySeeds[i][j];
+            }
+
+            maskCommits[i][j] =
+                masks[j] * permutations[j][i] * power +
+                currPseudonyms[j] * power * permutations[j][i] * userTallySeeds[i][j] +
+                elGamalBlindGenerator * userTallySeeds[i][j];
+
+            messageCommits[i][j] =
+                messages[j] * permutations[j][i] +
+                nextGenerator * permutations[j][i] * userTallySeeds[i][j] +
+                elGamalBlindGenerator * userTallySeeds[i][j];
+
+            userTallySeedCommits[i][j] =
+                EL_GAMAL_GENERATOR * userTallySeeds[i][j];
+        }
+    }
 }
 
 template <typename T>
@@ -1228,7 +1195,8 @@ bool PrsonaServer::update_data(
     const std::vector<std::vector<Curvepoint>>& freshPseudonymCommits,
     const std::vector<std::vector<TwistBipoint>>& serverTallyCommits,
     const std::vector<std::vector<std::vector<CurveBipoint>>>& voteMatrixCommits,
-    const std::vector<std::vector<std::vector<Curvepoint>>>& userTallyCommits)
+    const std::vector<std::vector<Curvepoint>>& userTallyMaskCommits,
+    const std::vector<std::vector<Curvepoint>>& userTallyMessageCommits)
 {
     std::vector<Curvepoint> newPseudonyms;
     std::vector<TwistBipoint> newVoteTallies;
@@ -1240,10 +1208,10 @@ bool PrsonaServer::update_data(
         TwistBipoint voteTallySum = serverTallyCommits[i][0];
 
         Curvepoint userTallyMask, userTallyMessage;
-        if (!userTallyCommits.empty())
+        if (!userTallyMaskCommits.empty())
         {
-            userTallyMask = userTallyCommits[i][0][0];
-            userTallyMessage = userTallyCommits[i][0][1];
+            userTallyMask = userTallyMaskCommits[i][0];
+            userTallyMessage = userTallyMessageCommits[i][0];
         }
 
         for (size_t j = 1; j < freshPseudonymCommits[i].size(); j++)
@@ -1251,19 +1219,19 @@ bool PrsonaServer::update_data(
             pseudonymSum = pseudonymSum + freshPseudonymCommits[i][j];
             voteTallySum = voteTallySum + serverTallyCommits[i][j];
 
-            if (!userTallyCommits.empty())
+            if (!userTallyMaskCommits.empty())
             {
                 userTallyMask = userTallyMask +
-                    userTallyCommits[i][j][0];
+                    userTallyMaskCommits[i][j];
                 userTallyMessage = userTallyMessage +
-                    userTallyCommits[i][j][1];
+                    userTallyMessageCommits[i][j];
             }
         }
 
         newPseudonyms.push_back(pseudonymSum);
         newVoteTallies.push_back(voteTallySum);
 
-        if (!userTallyCommits.empty())
+        if (!userTallyMaskCommits.empty())
         {
             newUserTallies.push_back(
                 EGCiphertext(userTallyMask, userTallyMessage));

+ 76 - 40
prsona/src/serverEntity.cpp

@@ -450,9 +450,11 @@ void PrsonaServerEntity::epoch(size_t which)
     std::vector<std::vector<std::vector<Curvepoint>>> freshPseudonymCommits;
     std::vector<std::vector<std::vector<Curvepoint>>> freshPseudonymSeedCommits;
     std::vector<std::vector<std::vector<TwistBipoint>>> serverTallyCommits;
-    std::vector<std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>>> voteMatrixCommits;
-    std::vector<std::vector<std::vector<std::vector<Curvepoint>>>> userTallyCommits;
-    std::vector<std::vector<std::vector<Curvepoint>>> userTallyMaskSeedCommits;
+    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>> partwayVoteMatrixCommits;
+    std::vector<std::vector<std::vector<std::vector<CurveBipoint>>>> finalVoteMatrixCommits;
+    std::vector<std::vector<std::vector<Curvepoint>>> userTallyMaskCommits;
+    std::vector<std::vector<std::vector<Curvepoint>>> userTallyMessageCommits;
+    std::vector<std::vector<std::vector<Curvepoint>>> userTallySeedCommits;
 
     std::vector<std::vector<Proof>> generator_proof_holder(1);
     pi.push_back(generator_proof_holder);
@@ -462,35 +464,36 @@ void PrsonaServerEntity::epoch(size_t which)
     {   
         size_t realI = (which + i) % servers[which].get_num_servers();
 
-        std::cout << "Building up on server " << realI << "." << std::endl;
-
         servers[realI].build_up_midway_pseudonyms(
             pi,
             permutationCommits,
             freshPseudonymCommits,
             freshPseudonymSeedCommits,
             serverTallyCommits,
-            voteMatrixCommits,
+            partwayVoteMatrixCommits,
+            finalVoteMatrixCommits,
             nextGenerator);
 
         for (size_t j = 1; j < servers[which].get_num_servers(); j++)
         {
-            std::vector<std::vector<std::vector<Curvepoint>>> currUserTallyCommits;
-            std::vector<std::vector<Curvepoint>> currUserTallyMaskSeedCommits;
+            std::vector<std::vector<Curvepoint>> currUserTallyMaskCommits;
+            std::vector<std::vector<Curvepoint>> currUserTallyMessageCommits;
+            std::vector<std::vector<Curvepoint>> currUserTallySeedCommits;
 
             size_t realJ = (realI + j) % servers[which].get_num_servers();
 
-            std::cout << "Giving to server " << realJ << "." << std::endl;
-
             servers[realJ].accept_epoch_updates(
                 pi[i + 1],
                 permutationCommits[i],
                 freshPseudonymCommits[i],
                 freshPseudonymSeedCommits[i],
                 serverTallyCommits[i],
-                voteMatrixCommits[i],
-                currUserTallyCommits,
-                currUserTallyMaskSeedCommits,
+                partwayVoteMatrixCommits[i],
+                finalVoteMatrixCommits[i],
+                currUserTallyMaskCommits,
+                currUserTallyMessageCommits,
+                currUserTallySeedCommits,
+                nextGenerator,
                 false);
         }
     }
@@ -501,24 +504,28 @@ void PrsonaServerEntity::epoch(size_t which)
     freshPseudonymCommits.clear();
     freshPseudonymSeedCommits.clear();
     serverTallyCommits.clear();
-    voteMatrixCommits.clear();
-
-    std::cout << "Tallying scores." << std::endl;
+    partwayVoteMatrixCommits.clear();
+    finalVoteMatrixCommits.clear();
 
     /* Imagine that server 0 is encrypting these, then would do a ZKP that it
      * knows a secret mask and encrypted the correct value everyone else already
      * knows. Everyone else then adds a mask and proves they added a secret mask
      * to the committed values. */
-    std::vector<EGCiphertext> currentUserEncryptedTallies =
-        tally_scores(nextGenerator, which);
-    distribute_tallied_scores(currentUserEncryptedTallies);
+    std::vector<EGCiphertext> currentUserEncryptedTallies;
+    std::vector<TwistBipoint> currentServerEncryptedTallies;
+    tally_scores(
+        nextGenerator,
+        currentUserEncryptedTallies,
+        currentServerEncryptedTallies,
+        which);
+    distribute_tallied_scores(
+        currentUserEncryptedTallies,
+        currentServerEncryptedTallies);
     
     // go from A_0.5 to A_1
     for (size_t i = 0; i < servers[which].get_num_servers(); i++)
     {
         size_t realI = (which + i) % servers[which].get_num_servers();
-
-        std::cout << "Breaking down on server " << realI << "." << std::endl;
         
         servers[realI].break_down_midway_pseudonyms(
             generator_proof,
@@ -527,16 +534,16 @@ void PrsonaServerEntity::epoch(size_t which)
             freshPseudonymCommits,
             freshPseudonymSeedCommits,
             serverTallyCommits,
-            voteMatrixCommits,
-            userTallyCommits,
-            userTallyMaskSeedCommits,
+            partwayVoteMatrixCommits,
+            finalVoteMatrixCommits,
+            userTallyMaskCommits,
+            userTallyMessageCommits,
+            userTallySeedCommits,
             nextGenerator);
         
         for (size_t j = 1; j < servers[which].get_num_servers(); j++)
         {
-            size_t realJ = (which + j) % servers[which].get_num_servers();
-
-            std::cout << "Giving to server " << realJ << "." << std::endl;
+            size_t realJ = (realI + j) % servers[which].get_num_servers();
 
             servers[realJ].accept_epoch_updates(
                 pi[i],
@@ -544,9 +551,12 @@ void PrsonaServerEntity::epoch(size_t which)
                 freshPseudonymCommits[i],
                 freshPseudonymSeedCommits[i],
                 serverTallyCommits[i],
-                voteMatrixCommits[i],
-                userTallyCommits[i],
-                userTallyMaskSeedCommits[i],
+                partwayVoteMatrixCommits[i],
+                finalVoteMatrixCommits[i],
+                userTallyMaskCommits[i],
+                userTallyMessageCommits[i],
+                userTallySeedCommits[i],
+                nextGenerator,
                 true);
         }
     }
@@ -584,6 +594,23 @@ void PrsonaServerEntity::print_votes() const
     }
 }
 
+void PrsonaServerEntity::print_current_votes_by(
+    const Curvepoint& index) const
+{
+    BGN bgnSystem = servers[0].bgnSystem;
+    size_t realIndex =
+        servers[0].binary_search(index);
+    std::vector<CurveBipoint> scores = servers[0].voteMatrix[realIndex];
+
+    std::cout << "[";
+    for (size_t i = 0; i < scores.size(); i++)
+    {
+            std::cout << bgnSystem.decrypt(scores[i])
+                << (i == scores.size() - 1 ? "]" : " ");
+    }
+    std::cout << std::endl;
+}
+
 /*********************
  * PRIVATE FUNCTIONS *
  *********************/
@@ -597,8 +624,10 @@ void PrsonaServerEntity::print_votes() const
  *
  * We're treating it as if we are one server, so that server gets the updated
  * weights to be sent to all other servers for the next epoch. */
-std::vector<EGCiphertext> PrsonaServerEntity::tally_scores(
+void PrsonaServerEntity::tally_scores(
     const Curvepoint& nextGenerator,
+    std::vector<EGCiphertext>& userTallyScores,
+    std::vector<TwistBipoint>& serverTallyScores,
     size_t which)
 {
     std::vector<EGCiphertext> retval;
@@ -609,6 +638,8 @@ std::vector<EGCiphertext> PrsonaServerEntity::tally_scores(
     mpz_class topOfScoreRange =
         decryptedTalliedScores.size() * PrsonaBase::get_max_allowed_vote();
 
+    userTallyScores.clear();
+    serverTallyScores.clear();
     for (size_t i = 0; i < decryptedTalliedScores.size(); i++)
     {
         decryptedTalliedScores[i] =
@@ -618,29 +649,34 @@ std::vector<EGCiphertext> PrsonaServerEntity::tally_scores(
             );
 
         EGCiphertext currCiphertext;
-        retval.push_back(currCiphertext);
+        userTallyScores.push_back(currCiphertext);
+        TwistBipoint currServerScore;
+        serverTallyScores.push_back(currServerScore);
         Scalar currMask;
         currMask.set_random();
 
         // Give the server the new weights,
         // to get passed around to the other servers
         servers[which].bgnSystem.encrypt(
-            servers[which].previousVoteTallies[i], decryptedTalliedScores[i]);
-        
-        retval[i].mask = servers[which].currentPseudonyms[i] * currMask;
-        retval[i].encryptedMessage =
+            serverTallyScores[i], decryptedTalliedScores[i]);
+
+        userTallyScores[i].mask = servers[which].currentPseudonyms[i] * currMask;
+        userTallyScores[i].encryptedMessage =
             (nextGenerator * currMask) +
             (servers[which].get_blinding_generator() * decryptedTalliedScores[i]);
     }
-
-    return retval;
 }
 
 void PrsonaServerEntity::distribute_tallied_scores(
-    const std::vector<EGCiphertext>& scores)
+    const std::vector<EGCiphertext>& userScores,
+    const std::vector<TwistBipoint>& serverScores)
 {
     for (size_t i = 0; i < servers[0].get_num_servers(); i++)
-        servers[i].currentUserEncryptedTallies = scores;
+    {
+        servers[i].currentUserEncryptedTallies = userScores;
+        servers[i].previousVoteTallies = serverScores;
+    }
+
 }
 
 /*