def _apply_vote(self, pubkey, config_vote_data, authorized_keys, state): config_vote = ConfigVote() config_vote.ParseFromString(config_vote_data) proposal_id = config_vote.proposal_id config_candidates = _get_config_candidates(state) candidate = _first( config_candidates.candidates, lambda candidate: candidate.proposal_id == proposal_id) if candidate is None: raise InvalidTransaction( "Proposal {} does not exist.".format(proposal_id)) candidate_index = _index_of(config_candidates.candidates, candidate) approval_threshold = _get_approval_threshold(state) vote_record = _first(candidate.votes, lambda record: record.public_key == pubkey) if vote_record is not None: raise InvalidTransaction( '{} has already voted'.format(pubkey)) candidate.votes.add( public_key=pubkey, vote=config_vote.vote) accepted_count = 0 rejected_count = 0 for vote_record in candidate.votes: if vote_record.vote == ConfigVote.ACCEPT: accepted_count += 1 elif vote_record.vote == ConfigVote.REJECT: rejected_count += 1 if accepted_count >= approval_threshold: _set_config_value(state, candidate.proposal.setting, candidate.proposal.value) del config_candidates.candidates[candidate_index] elif rejected_count >= approval_threshold or \ (rejected_count + accepted_count) == len(authorized_keys): LOGGER.debug('Proposal for %s was rejected', candidate.proposal.setting) del config_candidates.candidates[candidate_index] else: LOGGER.debug('Vote recorded for %s', candidate.proposal.setting) _save_config_candidates(state, config_candidates)
def create_vote_proposal(self, proposal_id, setting, vote): vote = ConfigVote(proposal_id=proposal_id, vote=vote) payload = ConfigPayload(action=ConfigPayload.VOTE, data=vote.SerializeToString()) return self._create_tp_process_request(setting, payload)