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
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
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])
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
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)