def test_cast_ballot(self): # Arrange keypair = elgamal_keypair_from_secret(int_to_q(2)) election = election_factory.get_fake_election() metadata, context = election_factory.get_fake_ciphertext_election( election, keypair.public_key ) store = BallotStore() source = election_factory.get_fake_ballot(metadata) self.assertTrue(source.is_valid(metadata.ballot_styles[0].object_id)) # Act data = encrypt_ballot(source, metadata, context, SEED_HASH) result = accept_ballot(data, BallotBoxState.CAST, metadata, context, store) # Assert expected = store.get(source.object_id) self.assertEqual(expected.state, BallotBoxState.CAST) self.assertEqual(result.state, BallotBoxState.CAST) self.assertEqual(expected.object_id, result.object_id) # Test failure modes self.assertIsNone( accept_ballot(data, BallotBoxState.CAST, metadata, context, store) ) # cannot cast again self.assertIsNone( accept_ballot(data, BallotBoxState.SPOILED, metadata, context, store) ) # cannot cspoil a ballot already cast
def test_spoil_ballot(self): # Arrange keypair = elgamal_keypair_from_secret(int_to_q(2)) manifest = election_factory.get_fake_manifest() internal_manifest, context = election_factory.get_fake_ciphertext_election( manifest, keypair.public_key) store = DataStore() source = election_factory.get_fake_ballot(internal_manifest) self.assertTrue( source.is_valid(internal_manifest.ballot_styles[0].object_id)) # Act data = encrypt_ballot(source, internal_manifest, context, SEED) result = accept_ballot(data, BallotBoxState.SPOILED, internal_manifest, context, store) # Assert expected = store.get(source.object_id) self.assertEqual(expected.state, BallotBoxState.SPOILED) self.assertEqual(result.state, BallotBoxState.SPOILED) self.assertEqual(expected.object_id, result.object_id) # Test failure modes self.assertIsNone( accept_ballot(data, BallotBoxState.SPOILED, internal_manifest, context, store)) # cannot spoil again self.assertIsNone( accept_ballot(data, BallotBoxState.CAST, internal_manifest, context, store)) # cannot cast a ballot already spoiled
def cast_spoil(ballot_id: str, do_cast: bool, ballots_encrypted: List, store: BallotStore, metadata: InternalElectionDescription, context: CiphertextElectionContext) -> (bool, BallotStore): """ :param context: :param metadata: :param store: :param ballots_encrypted: :param ballot_id: :param do_cast: cast ballot if true, spoil otherwise (could be cleaner...) :return: Status code and the new store. store gets modified in accept_ballot without being explicitly returned """ # Search for the ballot with ballot_id in ballots_encrypted ballot = next((b for b in ballots_encrypted if b.object_id == ballot_id), None) if not ballot: return False, store if do_cast: accepted_ballot = accept_ballot(ballot, BallotBoxState.CAST, metadata, context, store) assert (store.get(accepted_ballot.object_id) == accepted_ballot) return True, store else: accepted_ballot = accept_ballot(ballot, BallotBoxState.SPOILED, metadata, context, store) assert (store.get(accepted_ballot.object_id) == accepted_ballot) return True, store
def handle_ballot(request: AcceptBallotRequest, state: BallotBoxState) -> Any: ballot = CiphertextBallot.from_json_object(request.ballot) description = ElectionDescription.from_json_object(request.description) internal_description = InternalElectionDescription(description) context = CiphertextElectionContext.from_json_object(request.context) accepted_ballot = accept_ballot( ballot, state, internal_description, context, BallotStore(), ) return accepted_ballot