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
Example #2
0
    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
Example #4
0
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