-
Notifications
You must be signed in to change notification settings - Fork 0
/
voter.py
executable file
·145 lines (131 loc) · 5.29 KB
/
voter.py
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
#!/usr/bin/env python
import argparse
import json
import random
import subprocess
import uniqueid as uid
import threading
import queue
import sys
import time
class Voter:
def __init__(self, template, multichainCLI, datadir, chain, stream, publicKeyFile, intervalWait):
self.template = template
self.multichainCLI = multichainCLI
self.datadir = datadir
self.chain = chain
self.stream = stream
self.publicKeyFile = publicKeyFile
self.intervalWait = intervalWait
self.processQueue = queue.Queue()
self.processThread = threading.Thread(target=self.handleProcessing)
self.processThread.daemon = True
self.processThread.start()
self.lastBallotTime = time.time()
with open(self.template, 'r') as fd:
ballotTemplate = json.load(fd)
self.ballotElections = ballotTemplate['elections']
self.ballotProps = ballotTemplate['propositions']
def isFinished(self):
return self.processQueue.empty()
def getEmptyBallot(self):
return (self.ballotElections, self.ballotProps)
def processBallot(self, ballot, ticket):
try:
if not uid.validateIDFromHex(ticket, self.publicKeyFile):
print('Could not validate ballot/ticket')
return False
except:
print('Could not validate ballot/ticket')
return False
if time.time() - self.lastBallotTime > self.intervalWait:
self.submitBallot(ballot, ticket)
else:
self.processQueue.put([ballot, ticket])
return True
def handleProcessing(self):
while True:
time.sleep(self.intervalWait)
if self.processQueue.empty():
continue
self.lastBallotTime = time.time()
toProcess = self.processQueue.get()
self.submitBallot(toProcess[0], toProcess[1])
def submitBallot(self, ballot, ticket):
ballotJson = json.dumps(ballot)
ballotHex = ballotJson.encode('utf-8').hex()
args = (self.multichainCLI, self.chain, '-datadir={}'.format(self.datadir),
'publish', self.stream, ticket[-256:], ballotHex)
popen = subprocess.Popen(args)
popen.wait()
def autoFillBallot(self):
ballotCopy = {}
for election in self.ballotElections:
position = election['position']
options = []
for option in election['options']:
for _, name in option.items():
options.append(name)
ballotCopy[position] = random.choice(options)
return ballotCopy
def get_choice_elect(self, elect):
print("Choices for " + elect['position'])
choices = ""
choices_list = []
for choice in elect['options']:
cur_choice = list(choice.values())[0] # Hacky I know
choices_list.append(cur_choice)
choices += cur_choice + ", "
if elect['writein']:
choices += "or Write In"
else:
choices = choices[:-2]
print(choices)
while True:
selection = input("Please choose one: ")
if selection in choices or elect['writein']:
return selection
def get_choice_prop(self, prop):
print(prop['proposition'])
print(prop['description'])
choices = ['Yes', 'No']
while True:
selection = input("Yes or No: ")
if selection in choices:
return selection
def cli_ballot(self):
print("\nPlease fill out your choices for the elections and propositions")
while True:
this_ballot = {}
print("Elections")
for elect in self.ballotElections:
selection = self.get_choice_elect(elect)
this_ballot[elect['position']] = selection
print("Propositions")
for prop in self.ballotProps:
selection = self.get_choice_prop(prop)
this_ballot[prop['proposition']] = selection
print("Is this your correct ballot?")
print(this_ballot)
selection = input("Yes/No: ")
if selection == "Yes":
return this_ballot
def runVoterInterface(args):
vInstance = Voter(args.template, args.multichain, args.datadir, args.chain, args.stream, args.publickey, args.interval)
# Run the interface indefinitely
while True:
ballot = vInstance.cli_ballot()
print('Enter your unique voting ID:')
givenID = input()
vInstance.processBallot(ballot, givenID)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Run the interactive voting application')
parser.add_argument('template', help='path to the ballot template')
parser.add_argument('multichainCLI', help='path to the multichain CLI')
parser.add_argument('datadir', help='path to the multichain data directory')
parser.add_argument('chain', help='name of the blockchain')
parser.add_argument('stream', help='name of the blockchain stream')
parser.add_argument('publickey', help='path to the public key')
parser.add_argument('interval', type=float, help='interval of how often to write a vote',
default=3.0)
runVoterInterface(parser.parse_args())