1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package org.gnunet.voting;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Simulation of the voting protocol.
*
* @author Florian Dold
*/
public class VotingSimulation {
public static void main(String... args) {
final int authorityCount = 10;
final int authorityThreshold = 6;
final VotingParameters parameters = VotingParameters.generateRandomParameters(64, 10, authorityCount, authorityThreshold);
List<Authority> availableAuthorities = spawnAuthorities(authorityCount, authorityCount);
final ElectionSupervisor supervisor = new ElectionSupervisor(availableAuthorities, parameters);
supervisor.inviteAuthorities();
// todo: what if to little authorities accepted the invitation?
supervisor.startKeyGeneration();
// make sure that every authority and the supervisor has the same public key
supervisor.ascertainGroupPublicKey();
CallForVoters callForVoters = supervisor.createCallForVote();
List<Voter> voters = spawnVoters(callForVoters, 100, 50);
int checkTally = countCheckTally(voters);
for (Voter voter : voters) {
voter.vote();
}
// todo: make sure every authority has the same votes
for (Authority authority : callForVoters.authorities) {
authority.distributeTallyKey();
}
// todo: blame authorities that failed the zero knowledge proof
for (Authority authority : callForVoters.authorities) {
int tally = authority.decryptTally();
if (tally != checkTally) {
throw new AssertionError();
}
}
}
private static int countCheckTally(List<Voter> voters) {
int tally = 0;
for (Voter voter : voters) {
tally += voter.b ? 1 : -1;
}
return tally;
}
/**
* Create all authorities involved in the election, where some authorities are bogus authorities.
*
* @param authorityCount number of returned authorities
* @param authorityThreshold minimum number of honest authorities
* @return list of authorities
*/
public static List<Authority> spawnAuthorities(int authorityCount, int authorityThreshold) {
List<Authority> authorities = Lists.newArrayList();
Collection<Integer> honestAuthorityIndices = VotingSimulation.randomIndices(authorityCount, authorityThreshold);
for (int i = 0; i < authorityCount; ++i) {
if (honestAuthorityIndices.contains(i)) {
authorities.add(new Authority());
}
}
return authorities;
}
/**
* Create voters, where some voters may be malicious.
*
* @param callForVote description of the election for the voter
* @param voterCount number of all voters
* @param honestVoterCount number of honest, non-malicious voters
*/
private static List<Voter> spawnVoters(CallForVoters callForVote, int voterCount, int honestVoterCount) {
List<Voter> voters = Lists.newArrayList();
for (int i = 0; i < voterCount; ++i) {
voters.add(new Voter(callForVote));
}
return voters;
}
/*
* Return between authorityThreshold and authorityCount indices
*/
private static List<Integer> randomIndices(int authorityCount, int authorityThreshold) {
ArrayList<Integer> x = Lists.newArrayListWithCapacity(authorityCount);
for (int i = 0; i < authorityCount; ++i) {
x.add(i);
}
Collections.shuffle(x);
int len;
if (authorityCount == authorityThreshold) {
len = authorityThreshold;
} else {
len = CryptoUtil.random.nextInt(authorityCount - authorityThreshold) + authorityThreshold;
}
return Collections.unmodifiableList(x.subList(0, len));
}
}
|