@@ -35,10 +35,13 @@ def append_content(content)
3535
3636 def process_create_election_message ( _message_identifier , message , _content )
3737 raise RejectedMessage , "There must be at least 2 Trustees" if message . fetch ( :trustees , [ ] ) . count < 2
38+
39+ @state = { quorum : message [ :scheme ] [ :quorum ] }
3840 end
3941
4042 def process_start_key_ceremony_message ( _message_identifier , _message , _content )
41- @state = { joint_election_key : 1 , trustees : [ ] }
43+ state [ :joint_election_key ] = 1
44+ state [ :trustees ] = [ ]
4245 end
4346
4447 def process_key_ceremony_message ( message_identifier , _message , content )
@@ -86,76 +89,81 @@ def process_start_tally_message(_message_identifier, _message, _content)
8689 end
8790 end
8891
89- state [ :compensations ] = { }
90- state [ :joint_compensations ] = { }
91- state [ :compensated ] = 0
9292 state [ :shares ] = [ ]
93+ state [ :missing ] = [ ]
94+ state [ :compensations ] = [ ]
9395 state [ :joint_shares ] = build_questions_struct ( 1 )
96+ state [ :joint_compensations ] = build_questions_struct ( 1 )
9497
9598 emit_response "tally.cast"
9699 append_content results
97100 end
98101
99102 def process_tally_message ( message_identifier , message , content )
100103 if message_identifier . subtype == "missing_trustee"
101- state [ :compensations ] [ message [ :trustee_id ] ] = [ ]
102- state [ :joint_compensations ] [ message [ :trustee_id ] ] = build_questions_struct ( 1 )
104+ state [ :missing ] << message [ :trustee_id ] unless state [ :shares ] . include? ( message [ :trustee_id ] )
103105
104106 return
105107 end
106108
107109 raise RejectedMessage , "The owner_id doesn't match the sender trustee" if content [ :owner_id ] != message_identifier . author_id
108110
109- case message_identifier . subtype
110- when "share"
111- process_tally_share_message content
112- when "compensation"
113- process_compensation_message content
114- end
111+ process_tally_message_by_subtype message_identifier . subtype , content
115112
116- return unless state [ :shares ] . count + state [ :compensated ] == election . trustees . count
113+ return unless state [ :missing ] . count + state [ :shares ] . count == election . trustees . count &&
114+ state [ :shares ] . count >= state [ :quorum ]
117115
118- results = build_questions_struct ( 0 )
119- state [ :joint_shares ] . each do |question , answers |
120- answers . each do |answer , joint_share |
121- results [ question ] [ answer ] = ( ( joint_share / state [ :joint_election_key ] ) **( 1.0 / state [ :trustees ] . count ) ) . round
122- end
116+ if state [ :missing ] . any?
117+ return unless state [ :shares ] . count == state [ :compensations ] . count
118+
119+ join_compensations
123120 end
124121
125- emit_response "end_tally" , results : results
122+ emit_response "end_tally" , results : join_shares
126123 end
127124
128- def process_tally_share_message ( content )
129- raise RejectedMessage , "The trustee already sent their share" if state [ :shares ] . include? ( content [ :owner_id ] )
125+ def process_tally_message_by_subtype ( subtype , content )
126+ case subtype
127+ when "share"
128+ raise RejectedMessage , "The trustee already sent their share" if state [ :shares ] . include? ( content [ :owner_id ] )
130129
131- state [ :shares ] << content [ :owner_id ]
130+ state [ :shares ] << content [ :owner_id ]
131+ state [ :missing ] . delete ( content [ :owner_id ] )
132132
133- content [ :contests ] . each do |question , answers |
134- answers . each do |answer , share |
135- state [ :joint_shares ] [ question ] [ answer ] *= share
133+ content [ :contests ] . each do |question , answers |
134+ answers . each do |answer , share |
135+ state [ :joint_shares ] [ question ] [ answer ] *= share
136+ end
137+ end
138+ when "compensation"
139+ raise RejectedMessage , "The trustee already sent their compensation" if state [ :compensations ] . include? ( content [ :owner_id ] )
140+
141+ state [ :compensations ] << content [ :owner_id ]
142+
143+ content [ :contests ] . each do |question , answers |
144+ answers . each do |answer , compensation |
145+ state [ :joint_compensations ] [ question ] [ answer ] *= compensation
146+ end
136147 end
137148 end
138149 end
139150
140- def process_compensation_message ( content )
141- compensation = state [ :compensations ] [ content [ :trustee_id ] ]
142- raise RejectedMessage , "The trustee already sent their compensation for #{ content [ :trustee_id ] } " if compensation . include? ( content [ :owner_id ] )
143-
144- compensation << content [ :owner_id ]
145- content [ :contests ] . each do |question , answers |
151+ def join_compensations
152+ state [ :joint_compensations ] . each do |question , answers |
146153 answers . each do |answer , value |
147- state [ :joint_compensations ] [ content [ :trustee_id ] ] [ question ] [ answer ] *= value
154+ state [ :joint_shares ] [ question ] [ answer ] *=
155+ ( value **( 1.0 / state [ :compensations ] . count ) * state [ :joint_election_key ] ) . round
148156 end
149157 end
158+ end
150159
151- return unless state [ :compensations ] . count + state [ :compensations ] [ content [ :trustee_id ] ] . count == election . trustees . count
152-
153- state [ :joint_compensations ] [ content [ :trustee_id ] ] . each do |question , answers |
154- answers . each do |answer , value |
155- state [ :joint_shares ] [ question ] [ answer ] * = ( value . round **( 1.0 / state [ :shares ] . count ) ) . round
160+ def join_shares
161+ results = build_questions_struct ( 0 )
162+ state [ :joint_shares ] . each do |question , answers |
163+ answers . each do |answer , joint_share |
164+ results [ question ] [ answer ] = ( ( joint_share / state [ :joint_election_key ] ) **( 1.0 / state [ :trustees ] . count ) ) . round
156165 end
157166 end
158- state [ :compensated ] += 1
159167 end
160168
161169 def build_questions_struct ( initial_value )
0 commit comments