int main(int argc, char *argv[]) { /*************************** INIT ***************************/ /* most of the init code is copied directly from HElibs general test (https://github.com/shaih/HElib/blob/master/src%2FTest_General.cpp) */ cerr << "*************************** INIT ***************************" << "\n"; argmap_t argmap; argmap["R"] = "1"; argmap["p"] = "113"; argmap["r"] = "1"; argmap["d"] = "1"; argmap["c"] = "2"; argmap["k"] = "80"; argmap["L"] = "0"; argmap["s"] = "0"; argmap["m"] = "0"; long R = atoi(argmap["R"]); long p = atoi(argmap["p"]); long r = atoi(argmap["r"]); long d = atoi(argmap["d"]); long c = atoi(argmap["c"]); long k = atoi(argmap["k"]); // long z = atoi(argmap["z"]); long L = atoi(argmap["L"]); if (L==0) { // determine L based on R,r L = 3*R+3; if (p>2 || r>1) { // add some more primes for each round long addPerRound = 2*ceil(log((double)p)*r*3)/(log(2.0)*NTL_SP_NBITS) +1; L += R * addPerRound; } } long s = atoi(argmap["s"]); long chosen_m = atoi(argmap["m"]); long w = 64; // Hamming weight of secret key // long L = z*R; // number of levels long m = FindM(k, L, c, p, d, s, chosen_m, true); cerr << "\n\nR=" << R << ", p=" << p << ", r=" << r << ", d=" << d << ", c=" << c << ", k=" << k << ", w=" << w << ", L=" << L << ", m=" << m << endl; FHEcontext context(m, p, r); buildModChain(context, L, c); context.zMStar.printout(); cerr << endl; FHESecKey secretKey(context); const FHEPubKey& publicKey = secretKey; secretKey.GenSecKey(w); // A Hamming-weight-w secret key ZZX G; if (d == 0) G = context.alMod.getFactorsOverZZ()[0]; else G = makeIrredPoly(p, d); cerr << "G = " << G << "\n"; cerr << "generating key-switching matrices... "; addSome1DMatrices(secretKey); // compute key-switching matrices that we need cerr << "done\n"; cerr << "computing masks and tables for rotation..."; EncryptedArray ea(context, G); cerr << "done\n"; long nslots = ea.size(); cerr << "slots = " << nslots << "\n"; // set this to the maximum amount of delegates you want to use int delegateLimit = 10; if(delegateLimit > nslots) { cerr << "delegateLimit must be <= nslots\n"; exit(1); } cerr << "delegateLimit = " << delegateLimit << "\n"; /*************************** INIT ***************************/ cerr << "*************************** INIT ***************************" << "\n\n"; cerr << "Reading delegate votes"; vector<vector <long> > delegateVotes = readDelegateVotes("delegate_votes.txt", nslots, delegateLimit); cerr << "done\n"; cerr << "Encoding delegate votes...\n"; vector<PlaintextArray> delegateVotesEncoded = encodeVotes(delegateVotes, ea); cerr << "Encrypting delegate votes...\n"; vector<Ctxt> delegateVotesEncrypted = encryptVotes(delegateVotesEncoded, ea, publicKey); cerr << "Reading direct votes"; vector<vector <long> > votes = readVotes("direct_votes.txt", nslots); cerr << "done\n"; cerr << "Encoding direct votes...\n"; vector<PlaintextArray> votesEncoded = encodeVotes(votes, ea); cerr << "Encrypting direct votes...\n"; vector<Ctxt> votesEncrypted = encryptVotes(votesEncoded, ea, publicKey); cerr << "Reading delegations"; vector<vector <long> > delegations = readVotes("delegations.txt", nslots); cerr << "done\n"; cerr << "Encoding delegations...\n"; vector<PlaintextArray> delegationsEncoded = encodeVotes(delegations, ea); cerr << "Encrypting delegations...\n"; vector<Ctxt> delegationsEncrypted = encryptVotes(delegationsEncoded, ea, publicKey); cerr << "Tallying delegations (+)...\n"; Ctxt delegateWeights = tallyVotes(delegationsEncrypted); vector<Ctxt> weightFactors = getWeightFactors(delegateWeights, ea, publicKey, delegateLimit); cerr << "Applying weights (x)...\n"; vector<Ctxt> weightedDelegateVotes = applyWeights(weightFactors, delegateVotesEncrypted, ea, secretKey); cerr << "Tallying direct votes (+)...\n"; Ctxt directTally = tallyVotes(votesEncrypted); cerr << "Final tally (+)...\n"; Ctxt tally = liquidTally(directTally, weightedDelegateVotes); cerr << "Decrypting final tally...\n"; PlaintextArray totals = decrypt(tally, ea, secretKey); printTally(totals); }
// I believe this correctly implements Cloneproof Schwartz Set Dropping, aka // the Schulze method. // http://wiki.electorama.com/wiki/Schulze_method static int VRR_CSSD( VRR* it, int winnersLength, NameVote** winnersP, int* defeatCount ) { int numc = it->numc; int i, j; int* tally; int* ss; minij* mins; int numWinners; int mind; // minimum defeat, index and strength int tie = 0; if ( debug ) { fprintf(stderr,"pre cssd defeat count:"); for ( i = 0; i < numc; i++ ) { fprintf(stderr," %d", defeatCount[i] ); } fprintf(stderr,"\n"); } tally = malloc( sizeof(int)*numc*numc ); assert( tally != NULL ); ss = malloc( sizeof(int)*numc ); assert( ss != NULL ); mins = malloc( sizeof(minij)*numc ); assert( mins != NULL ); // Copy original VRR tally into local tally where defeats can be deleted. for ( i = 0; i < numc; i++ ) { for ( j = 0; j < numc; j++ ) { if ( i != j ) { tally[i*numc+j] = xy(i,j); } else { //tally[i*numc+j] = -1; // i==j should never be accessed } } } numWinners = getSchwartzSet( it, tally, defeatCount, ss ); while ( 1 ) { int ji, ki; mind = INT_MAX; tie = 0; if ( it->explain != NULL ) { assert(numWinners > 0); fprintf((FILE*)it->explain, "<p>Top choices: %s", indexName(it->ni, ss[0])); for ( i = 1; i < numWinners; ++i ) { fprintf((FILE*)it->explain, ", %s", indexName(it->ni, ss[i]) ); } fprintf((FILE*)it->explain, "</p>"); } if ( debug ) { printTally(stdout,tally,numc); fprintf(stderr,"ss (%d):", numWinners ); for ( i = 0; i < numWinners; i++ ) { fprintf(stderr," %d", ss[i] ); } fprintf(stderr,"\n"); } // find weakest defeat between members of schwartz set for ( ji = 0; ji < numWinners - 1; ji++ ) { j = ss[ji]; for ( ki = ji + 1; ki < numWinners; ki++ ) { int k; int vj, vk; int ihi, ilo; int vhi, vlo; int m; k = ss[ki]; vk = tally[k*numc + j]; // k beat j vk times // OR k prefered to j vk times vj = tally[j*numc + k]; // j beat k vj times // OR j prefered to k vj times if ((vk == -1) && (vj == -1)) { continue; } if ( vk > vj ) { ihi = k; ilo = j; vhi = vk; vlo = vj; } else /*if ( vj > vk )*/ { // A tie is indeed a weak defeat, probably the weakest, and // it doesn't matter in which direction it is considered for deletion. ihi = j; ilo = k; vhi = vj; vlo = vk; } if ( winningVotes ) { m = vhi; } else if ( margins ) { m = vhi - vlo; } else { assert(0); } if ( m < mind ) { tie = 1; mind = m; mins[0].ihi = ihi; mins[0].ilo = ilo; } else if ( m == mind ) { mins[tie].ihi = ihi; mins[tie].ilo = ilo; tie++; } } } if ( tie == 0 ) { if ( debug ) { fprintf(stderr, "tie = 0, no weakest defeat found to cancel\n"); } goto finish; } // all are tied if ( tie == numWinners) { if ( debug ) { fprintf(stderr, "tie==numWinners==%d, mind=%d\n", tie, mind); } goto finish; } for ( i = 0; i < tie; ++i ) { int mindk = mins[i].ihi; int mindj = mins[i].ilo; if ( it->explain != NULL ) { fprintf((FILE*)it->explain, "<p>Weakest defeat is %s (%d) v %s (%d). %s has one fewer defeat.</p>\n", indexName(it->ni, mindk), tally[mindk*numc + mindj], indexName(it->ni, mindj), tally[mindj*numc + mindk], indexName(it->ni, mindj) ); } tally[mindk*numc + mindj] = -1; tally[mindj*numc + mindk] = -1; defeatCount[mindj]--; } numWinners = getSchwartzSet( it, tally, defeatCount, ss ); if ( numWinners == 1 ) { goto finish; } if ( debug ) { assert(numWinners > 0); fprintf(stderr, "ss={ %d", ss[0] ); for ( j = 1; j < numWinners; j++ ) { fprintf(stderr, ", %d", ss[j] ); } fprintf(stderr, " }\n"); } } finish: free( mins ); free( ss ); free( tally ); VRR_makeWinners( it, defeatCount ); free( defeatCount ); return VRR_returnWinners( it, winnersLength, winnersP ); }