def list_election_candidates(election_id):  # noqa: E501
    """List candidates

     # noqa: E501

    :param election_id: Id of the election
    :type election_id: int

    :rtype: Candidate
    """
    try:
        election_id = Web3.toChecksumAddress(election_id)
    except ValueError:
        message = ('Election ID %s is not an Ethereum address' % election_id)
        error = Error(code=1, message=message)
        return error, 400
    contract = current_app.config['FACTORY_CONTRACT']
    if not contract.call('electionExist', [election_id]):
        message = ("Election with id %s does not exist" % election_id)
        error = Error(code=2, message=message)
        return error, 404
    provider = contract.provider
    election_abi = current_app.config['ELECTION_ABI']
    contract = Ethereum(provider, election_id, election_abi)
    candidates_number = contract.call('numCandidates')
    candidates = list()
    for index in range(candidates_number):
        candidates.append(lookup_candidate(election_id, index))

    return candidates
Exemple #2
0
def get_candidate_votes(election_id, candidate_id):  # noqa: E501
    """Get votes for a candidate

     # noqa: E501

    :param election_id: Id of the election
    :type election_id: int
    :param candidate_id: Id of the candidate
    :type candidate_id: int

    :rtype: Object
    """
    try:
        election_id = Web3.toChecksumAddress(election_id)
    except ValueError:
        message = ('Election ID %s is not an Ethereum address' %
                   election_id)
        error = Error(
            code=1,
            message=message
        )
        return error, 400
    contract = current_app.config['FACTORY_CONTRACT']
    if not contract.call('electionExist', [election_id]):
        message = ("Election with id %s does not exist" % election_id)
        error = Error(
            code=2,
            message=message
        )
        return error, 404
    provider = contract.provider
    election_abi = current_app.config['ELECTION_ABI']
    contract = Ethereum(provider, election_id, election_abi)
    candidates_number = contract.call('numCandidates')
    if candidate_id < 0 or candidate_id > candidates_number:
        message = ("Candidate with id %s does not exist" % candidate_id)
        error = Error(
            code=2,
            message=message
        )
        return error, 404
    candidate = contract.call('candidates', [candidate_id])
    votes = {
        'votes': candidate[2]
    }
    return votes
def lookup_candidate(election_id, candidate_id):  # noqa: E501
    """Lookup Candidate

     # noqa: E501

    :param election_id: Id of the election
    :type election_id: int
    :param candidate_id: Id of the candidate
    :type candidate_id: int

    :rtype: Candidate
    """
    try:
        election_id = Web3.toChecksumAddress(election_id)
    except ValueError:
        message = ('Election ID %s is not an Ethereum address' % election_id)
        error = Error(code=1, message=message)
        return error, 400
    contract = current_app.config['FACTORY_CONTRACT']
    if not contract.call('electionExist', [election_id]):
        message = ("Election with id %s does not exist" % election_id)
        error = Error(code=2, message=message)
        return error, 404
    provider = contract.provider
    election_abi = current_app.config['ELECTION_ABI']
    contract = Ethereum(provider, election_id, election_abi)
    candidates_number = contract.call('numCandidates')
    if candidate_id < 0 or candidate_id > candidates_number:
        message = ("Candidate with id %s does not exist" % candidate_id)
        error = Error(code=2, message=message)
        return error, 404
    candidate = contract.call('candidates', [candidate_id])
    candidate_repr = Candidate(id=candidate_id,
                               name=candidate[0],
                               description=candidate[1],
                               votes=candidate[2])
    return candidate_repr
Exemple #4
0
def create_candidate_vote(election_id, candidate_id):  # noqa: E501
    """Vote for a candidate

     # noqa: E501

    :param election_id: Id of the election
    :type election_id: int
    :param candidate_id: Id of the candidate
    :type candidate_id: int

    :rtype: None
    """
    try:
        election_id = Web3.toChecksumAddress(election_id)
    except ValueError:
        message = ('Election ID %s is not an Ethereum address' %
                   election_id)
        error = Error(
            code=1,
            message=message
        )
        return error, 400
    contract = current_app.config['FACTORY_CONTRACT']
    if not contract.call('electionExist', [election_id]):
        message = ("Election with id %s does not exist" % election_id)
        error = Error(
            code=2,
            message=message
        )
        return error, 404
    provider = contract.provider
    election_abi = current_app.config['ELECTION_ABI']
    contract = Ethereum(provider, election_id, election_abi)
    candidates_number = contract.call('numCandidates')
    if candidate_id < 0 or candidate_id > candidates_number:
        message = ("Candidate with id %s does not exist" % candidate_id)
        error = Error(
            code=2,
            message=message
        )
        return error, 404
    if connexion.request.is_json:
        info = connexion.request.get_json()

    has_voted = contract.call('voted', [info['account']])
    if has_voted:
        error = Error(
            code=6,
            message='Already voted before'
        )
        return error, 401

    contract.send('vote', info['account'], info['pkey'], [candidate_id])
Exemple #5
0
def create_election():  # noqa: E501
    """
    Create an election on the voting systemd

    Returns:
        :obj:`~democracy_server.models.election.Election`: Created election
            representation
    """
    if connexion.request.is_json:
        election = CreateElection.from_dict(connexion.request.get_json())
    factory = current_app.config['FACTORY_CONTRACT']
    account = election.account
    pkey = election.pkey
    name = election.name
    description = election.description
    candidates = election.candidates
    election = factory.call('electionNames', [name])
    if len(candidates) < 2:
        message = ('At least two candidates are needed to start an election.'
                   '%s provided' % str(len(candidates)))
        error = Error(code=5, message=message)
        return error, 400
    if election != "0x0000000000000000000000000000000000000000":
        message = ('Election with name \'%s\' already exists on the system' %
                   name)
        error = Error(code=3, message=message)
        return error, 400
    try:
        factory.send('createElection', account, pkey, [name, description])
    except ValueError as transact_error:
        message = str(transact_error)
        error = Error(code=100, message=message)
        return error, 500
    election = factory.call('electionNames', [name])
    provider = factory.provider
    election_abi = current_app.config['ELECTION_ABI']
    contract = Ethereum(provider, election, election_abi)
    for candidate in candidates:
        contract.send('addCandidate', account, pkey,
                      [candidate.name, candidate.description])
    contract.send('commit', account, pkey)

    return show_election_by_id(election), 201
Exemple #6
0
def show_election_by_id(election_id):  # noqa: E501
    """Lookup election

     # noqa: E501

    :param election_id: The id of the election to retrieve
    :type election_id: str

    :rtype: Election
    """
    try:
        election_id = Web3.toChecksumAddress(election_id)
    except ValueError:
        message = ('Election ID %s is not an Ethereum address' % election_id)
        error = Error(code=1, message=message)
        return error, 400

    contract = current_app.config['FACTORY_CONTRACT']
    if not contract.call('electionExist', [election_id]):
        message = ("Election with id %s does not exist" % election_id)
        error = Error(code=2, message=message)
        return error, 404
    provider = contract.provider
    election_abi = current_app.config['ELECTION_ABI']
    contract = Ethereum(provider, election_id, election_abi)
    candidates_number = contract.call('numCandidates')
    candidates = list()
    for index in range(candidates_number):
        candidate = contract.call('candidates', [index])
        name = candidate[0]
        description = candidate[1]
        votes = candidate[2]
        candidates.append(
            Candidate(name=name, description=description, votes=votes))
    election = Election(id=election_id,
                        name=contract.call('name'),
                        description=contract.call('description'),
                        candidates=candidates)
    return election
def main():
    logging.basicConfig(level=logging.INFO)
    """
    Swagger server entrypoint function. It makes use of argparse library to
    build a beatiful command line
    """
    python_dir = os.path.dirname(os.path.relpath(__file__))
    specification_dir = os.path.join(python_dir, 'swagger')
    swagger_file = os.path.abspath(
        os.path.join(specification_dir, 'swagger.yaml'))
    parser = argparse.ArgumentParser()
    parser.add_argument('--factory-abi',
                        dest='factory',
                        required=True,
                        help='Smart contract Factory JSON interface')
    parser.add_argument('--election-abi',
                        dest='election',
                        required=True,
                        help='Smart contract Election JSON interface')
    parser.add_argument('--address',
                        required=True,
                        help='Smart contract address')
    parser.add_argument('--infura',
                        required=True,
                        help='Infure URL to build the provider')
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        default=8080,
                        help='Port to run the API')
    parser.add_argument('--swagger-file',
                        dest='swagger_file',
                        default=swagger_file)
    parser.add_argument('-d', '--debug', action='store_true', default=False)
    args = parser.parse_args()
    swagger_file = os.path.abspath(args.swagger_file)
    if args.debug:
        logging.basicConfig(level=logging.DEBUG)
    app = connexion.FlaskApp(__name__,
                             specification_dir=os.path.dirname(swagger_file),
                             debug=args.debug)

    with open(args.factory, 'r') as _file:
        json_repr = json.loads(_file.read())
        if isinstance(json_repr, dict) and 'abi' in json_repr:
            factory_abi = json_repr['abi']
        else:
            factory_abi = json_repr
    with open(args.election, 'r') as _file:
        json_repr = json.loads(_file.read())
        if isinstance(json_repr, dict) and 'abi' in json_repr:
            election_abi = json_repr['abi']
        else:
            election_abi = json_repr

    provider = Web3.HTTPProvider(args.infura)
    factory_contract = Ethereum(provider, args.address, factory_abi)
    app.app.json_encoder = encoder.JSONEncoder
    app.add_api(os.path.basename(swagger_file),
                arguments={'title': 'Ethereum Voting'},
                pythonic_params=True)
    app.app.config['FACTORY_CONTRACT'] = factory_contract
    app.app.config['ELECTION_ABI'] = election_abi
    app.run(port=args.port)