-
Notifications
You must be signed in to change notification settings - Fork 1
/
counter.rb
executable file
·67 lines (49 loc) · 1.54 KB
/
counter.rb
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
#!/usr/bin/env ruby
require 'rest-client'
require 'json'
require 'optparse'
require './validator'
class Counter
ELECTION_PRIVATE_KEY_PATH = 'data/election_private.pem'.freeze
attr_reader :chain, :election_private_key, :validator
def initialize(chain)
@chain = chain
@election_private_key = CryptoHelper.rsa_key(ELECTION_PRIVATE_KEY_PATH)
@validator = Validator.new(chain)
end
def election_results
'This is not a valid chain' unless validator.valid_chain?
count_votes
end
private
def count_votes
results = Hash.new(0)
current_index = 1
while current_index < chain.length
block = chain[current_index]
vote_ciphertext = block['transaction']['vote']
vote_plaintext = CryptoHelper.rsa_private_decrypt(vote_ciphertext, election_private_key)
ring_sig = CryptoHelper.ringsig_from(block['transaction']['ring_signature'])
if validator.valid_vote?(vote_plaintext, ring_sig.key_image)
candidate = vote_plaintext.split('|')[1]
results[candidate] += 1
end
current_index += 1
end
results
end
end
if $PROGRAM_NAME == __FILE__
usage = 'usage: ./counter.rb -c CHAIN_URL'
options = {}
OptionParser.new do |opt|
opt.on('-c', '--chain CHAIN_URL') { |o| options[:chain_url] = o }
end.parse!
abort(usage) unless options[:chain_url]
chain = JSON.parse(RestClient.get(options[:chain_url]))['chain']
counter = Counter.new(chain)
start = Time.now
puts counter.election_results
finish = Time.now
puts "Counted in #{finish-start} seconds"
end