-
Notifications
You must be signed in to change notification settings - Fork 2
/
voting.vif
170 lines (141 loc) · 5.7 KB
/
voting.vif
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Voting with delegation.
# Information about voters
# a mapping
voters: IFL(public({weight: int128, voted: bool, delegate: address, vote: int128}[address]), voters)
#voters: IFL({
# # weight is accumulated by delegation
# weight: int128,
# # if true, that person already voted (which includes voting by delegating)
# voted: bool,
# # person delegated to
# delegate: address,
# # index of the voted proposal, which is not meaningful unless `voted` is True.
# vote: int128
#}[address], voters)
# This is a type for a list of proposals.
proposals: IFL(public({name: bytes32, vote_count: int128}[int128]), this)
#proposals: IFL(public({
# # short name (up to 32 bytes)
# name: bytes32,
# # int128ber of accumulated votes
# vote_count: int128
#}[int128]), this)
voter_count: IFL(int128, this)
chairperson: IFL(address, chairperson)
num_proposals: IFL(int128, this)
@public
@constant
@IFL_voters
def delegated(addr: address) -> bool:
return not not self.voters[addr].delegate
@public
@constant
@IFL_voters
def directly_voted(addr: address) -> bool:
return self.voters[addr].voted and (not self.voters[addr].delegate)
# Setup global variables
@public
@IFL_this
def __init__(_names: bytes32[2]):
self.chairperson = msg.sender
self.voter_count = 0
for i in range(2):
self.proposals[i] = {
name: _names[i],
vote_count: 0
}
self.num_proposals += 1
# Give a `voter` the right to vote on this ballot.
# This may only be called by the `chairperson`.
@public
@IFL_chairperson
def give_right_to_vote(voter: address):
# Throws if the sender is not the chairperson. And now it is not necessary since we have IFL!
#assert msg.sender == self.chairperson
assert not self.voters[voter].voted
assert self.voters[voter].weight == 0
self.voters[voter].weight = 1
self.voter_count += 1
@public
@IFL_this
def forward_weight(delegater: address):
assert self.voters[delegater].weight > 0
assert not not self.voters[delegater].delegate
target: address = self.voters[delegater].delegate
#Range only accepts literal values
for i in range(4): # Change 4 to a bigger one
if (not not self.voters[target].delegate):
target = self.voters[target].delegate
assert target != delegater
else:
break
weight_to_forward: int128 = self.voters[delegater].weight
self.voters[delegater].weight = 0
self.voters[target].weight += weight_to_forward
if(self.voters[target].voted):
#if(endorse(self.voters[target].voted, chairperson, this)):
#if (endorse(self.voters[target].voted, voters, this)):
#if(not endorse(self.voters[target].delegate, chairperson, this)):
if(not self.voters[target].delegate):
self.proposals[endorse(self.voters[target].vote, voters, this)].vote_count += weight_to_forward
self.voters[target].weight = 0
@public
@IFL_voters
def delegate(to: address):
assert not self.voters[endorse(msg.sender, bot, voters)].voted
# Throws if the sender tries to delegate their vote to themselves or to
# the default address value of 0x0000000000000000000000000000000000000000
# (the latter might not be problematic, but I don't want to think about it).
assert to != msg.sender and not not to
self.voters[endorse(msg.sender, bot, this)].voted = True
self.voters[endorse(msg.sender, bot, this)].delegate = to
# This call will throw if and only if this delegation would cause a loop
# of length <= 5 that ends up delegating back to the delegator.
#self.forward_weight(msg.sender)
assert self.voters[endorse(msg.sender, bot, voters)].weight > 0
assert not not self.voters[endorse(msg.sender, bot, voters)].delegate
target: address = self.voters[endorse(msg.sender, bot, voters)].delegate
#Range only accepts literal values
for i in range(endorse(4, bot, this)): # Change 4 to a bigger one
if(not not self.voters[target].delegate):
# if (endorse(not not self.voters[target].delegate, chairperson, this)):
target = self.voters[target].delegate
assert target != msg.sender
else:
break
weight_to_forward: int128 = self.voters[endorse(msg.sender, bot, voters)].weight
self.voters[endorse(msg.sender, bot, this)].weight = 0
self.voters[target].weight += weight_to_forward
if(self.voters[target].voted):
#if(endorse(self.voters[target].voted, chairperson, this)):
#if (endorse(self.voters[target].voted, voters, this)):
#if(not endorse(self.voters[target].delegate, chairperson, this)):
if(not self.voters[target].delegate):
self.proposals[endorse(self.voters[target].vote, voters, this)].vote_count += weight_to_forward
self.voters[target].weight = 0
@public
@IFL_voters
def vote(proposal: int128):
# can't vote twice
assert not self.voters[endorse(msg.sender, bot, voters)].voted
# can only vote on legitimate proposals
assert proposal < self.num_proposals
self.voters[endorse(msg.sender, bot, voters)].vote = proposal
self.voters[endorse(msg.sender, bot, voters)].voted = True
# transfer msg.sender's weight to proposal
self.proposals[proposal].vote_count += self.voters[endorse(msg.sender, bot, voters)].weight
self.voters[endorse(msg.sender, bot, this)].weight = 0
@public
@IFL_this
def winning_proposal() -> int128:
winning_vote_count: int128 = 0
winning_proposal: int128 = 0
for i in range(2):
if self.proposals[i].vote_count > winning_vote_count:
winning_vote_count = self.proposals[i].vote_count
winning_proposal = i
return winning_proposal
@public
@IFL_this
def winner_name() -> bytes32:
return self.proposals[self.winning_proposal()].name