def vote(request, template_name='vote.html'): eb = ElectionBusiness() context = {} signer = Signer() if eb.isOccurring(): # Check if elector already voted. if Voted.objects.filter(elector__user=request.user).count() > 0: messages.warning(request, 'You have already voted.') return render(request, template_name, context) positions = Position.objects.all() if request.method == 'POST': try: for p in positions: pname = 'position{}'.format(p.id) candidate_id = request.POST.get(pname,"") candidate = Candidate.objects.get(id=int(candidate_id)) cv, created = CandidateVote.objects.get_or_create(candidate=candidate) cv.quantity = cv.quantity + 1 cv.save() elector = Elector.objects.get(user=request.user) voted = Voted.objects.create(elector=elector) voted.system_signature = signer.sign(str(elector.id)) voted.save() messages.success(request, 'Your vote was registred successfully') except Exception as e: messages.error(request, str(e)) else: context['positions'] = positions context['quantity_of_positions'] = positions.count() else: messages.error(request, 'Election has finished.') return render(request, template_name, context)
def isLastBlock(self): eb = ElectionBusiness() if self.shouldAddBlock(): ec = eb.getCurrentElectionConfig() if (Voted.objects.count()-ec.min_votes_in_last_block)/Elector.objects.count() > ec.attendance_rate: return True if eb.isLocked() and eb.hadFinished(): return True return False
def shouldAddLastBlock(self): if self.isLastBlock(): if Voted.objects.count() == Elector.objects.count(): return True eb = ElectionBusiness() if eb.isLocked() and eb.hadFinished(): return True return False
def __call__(self, request): # Code to be executed for each request before # the view (and later middleware) are called. eb = ElectionBusiness() election_is_occurring = eb.isOccurring() election_is_locked = eb.isLocked() request.election_is_occurring = election_is_occurring request.election_is_locked = election_is_locked response = self.get_response(request) response.election_is_occurring = election_is_occurring response.election_is_locked = election_is_locked # Code to be executed for each request/response after # the view is called. return response
def checkMinVotes(self, bblock): ec = ElectionBusiness().getCurrentElectionConfig() if self.shouldAddBlock(): electors = json.loads(bblock.electors) if self.isLastBlock(): if self.shouldAddLastBlock(): return True if (len(electors) * Position.objects.count()) >= ec.min_votes_in_block: return True return False
def checkGuessRate(self, bblock): ec = ElectionBusiness().getCurrentElectionConfig() last_public_block = BBlock.objects.filter(reason='').order_by('-timestamp_iso')[0] max_difference = 0 i = 0 cv = json.loads(bblock.candidate_votes) pcv = json.loads(last_public_block.candidate_votes) while i < len(cv): if cv[i]['quantity'] - pcv[i]['quantity'] > max_difference: max_difference = cv[i]['quantity'] - pcv[i]['quantity'] i = i + 1 guess_rate = max_difference / ((bblock.total_votes - last_public_block.total_votes) / Position.objects.count()) if Decimal(str(guess_rate)) <= ec.guess_rate: return True return False
def shouldAddBlock(self): eb = ElectionBusiness() # While election is occurring, new blocks should be generated. if eb.isOccurring(): return True if eb.isLocked() and eb.hadFinished(): return True ec = eb.getCurrentElectionConfig() if not ec: raise DatabaseError('There is not Election Configuration for the current election') # Independently of election is occurring, if we have votes, a new block must be generated. if Voted.objects.filter(hash_val__isnull=True).count() > 0: return True # If election is not occurring and we do not have votes we do not need to generate a block. return False
def add(self): if not self.shouldAddBlock(): return finish_election = False if self.shouldAddLastBlock(): finish_election = True if BBlock.objects.all().count() == 0: raise DatabaseError('It is not possible to add a block without genesis block') previous_block = BBlock.objects.all().order_by('-timestamp_iso')[0] # Put these outside the transaction hc = HashCalculator() database_hash = hc.databaseHash() source_code_hash = hc.sourceCodeHash() # Get the last block which has electors divulged. last_public_block = BBlock.objects.filter(reason='').order_by('-timestamp_iso')[0] with transaction.atomic(): #bblock = BBlock.objects.create() bblock = BBlock() bblock.database_hash = database_hash bblock.hash_of_database_hash = bblock.calculateHashOfDatabaseHash() bblock.source_code_hash = source_code_hash bblock.hash_of_source_code_hash = bblock.calculateHashOfSourceCodeHash() bblock.timestamp_iso = datetime.datetime.now().isoformat() same_qtt_votes = False cv_quantity = 0 while not same_qtt_votes: # Workaround to lock electors who will be locked. #Voted.objects.filter(hash_val__isnull=True).update(hash_val='x') #electors = list(Voted.objects.filter(hash_val='x').values('id', 'elector_id', 'system_signature').order_by('id')) electors = list(Voted.objects.filter(hash_val__isnull=True).values('id', 'elector_id', 'system_signature').order_by('id')) candidate_votes = list(CandidateVote.objects.all().values('id', 'candidate_id', 'quantity').order_by('id')) cv_quantity = self.__count_votes(candidate_votes) if (cv_quantity - last_public_block.total_votes) == (len(electors) * Position.objects.count()): same_qtt_votes = True elector_id_list = [] for e in electors: elector_id_list.append(e['id']) bblock.candidate_votes = json.dumps(candidate_votes, cls=DjangoJSONEncoder) bblock.electors = json.dumps(electors, cls=DjangoJSONEncoder) bblock.parent_hash = previous_block.block_hash bblock.total_votes = cv_quantity ret = self.shouldIncludeElectors(bblock) if not ret[0]: bblock.electors = json.dumps([], cls=DjangoJSONEncoder) bblock.reason = ret[1] bblock.block_hash = bblock.calculateHash() else: bblock.reason = '' bblock.block_hash = bblock.calculateHash() Voted.objects.filter(id__in=elector_id_list).update(hash_val=bblock.block_hash) bblock.save() if finish_election: ec = ElectionBusiness().getCurrentElectionConfig() ec.locked = False ec.save()
def start_election(request, template_name='election/start_election.html'): has_error = False # If election is locked, the tests will not be executed. if request.election_is_locked: msg = 'Election has already started' messages.warning(request, msg) return render(request, template_name) if ElectionConfig.objects.all().count() != 1: has_error = True msg = 'Election Configuration is not configured properly.' messages.error(request, msg) ec = ElectionBusiness().getCurrentElectionConfig() if ec: if ec.start_time >= ec.end_time: has_error = True msg = 'Election Configuration start time is greater than end time.' messages.error(request, msg) if ec.end_time < datetime.now(): has_error = True msg = 'End time of Election Configuration is a past date' messages.error(request, msg) if Position.objects.all().count() == 0: has_error = True msg = 'There are not poisitions configurated for the election' messages.error(request, msg) for position in Position.objects.all(): if position.candidate_set.count() == 0: has_error = True msg = 'Position "{}" does not have candidates'.format( position.description) messages.error(request, msg) #Check positions without candidates #Check electors if Elector.objects.all().count() == 0: messages.error(request, 'There are not electors configurated for the election') has_error = True # Delete votes, results, blocks, etc... if not has_error: Voted.objects.all().delete() CandidateVote.objects.all().delete() for candidate in Candidate.objects.all(): cv = CandidateVote.objects.create(candidate=candidate, quantity=0) cv.save() BBlock.objects.all().delete() ec = ElectionConfig.objects.all()[0] ec.locked = True ec.save() # Add genesis block BBlockHandler().add_genesis() return redirect('home')