BlockchainConsensusAlgorithm/DPOS/dpos_api.py

164 lines
5.0 KiB
Python

# Interacting with the Dexter's blockchain with multiple nodes using HTTP requests
from flask import Flask, jsonify, request
from blockChain import Blockchain
# Initialise our node with identifier and instantiate the Blockchain class
app = Flask(__name__)
blockchain = Blockchain()
# API endpoint to mine a block, it is an HTTP GET request
@app.route('/mine', methods=['GET'])
# Method to mine a block
def mine():
# To ensure that only delegates elected by voting can mine a new block
current_port = "localhost:" + str(port)
if current_port in blockchain.delegates:
# To ensure that a new block is mined only if there are atleast 2 transactions
if len(blockchain.unverified_transactions) >= 2:
last_block = blockchain.last_block
previous_hash = blockchain.hash(last_block)
block = blockchain.new_block(previous_hash)
response = {
'message': "New block mined!",
'index': block['index'],
'transactions': block['transactions'],
'previous_hash': block['previous_hash']
}
print(len(blockchain.unverified_transactions))
return jsonify(response), 200
else:
response = {
'message': 'Not enough transactions to mine a new block and add to chain!'
}
print(len(blockchain.unverified_transactions))
return jsonify(response), 400
else:
response = {
'message': 'You are not authorised to mine block! Only delegates can mine.'
}
return jsonify(response), 400
# Endpoint for a new transaction
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
values = request.get_json()
required = ['Customer name', 'Item name', 'Total billing amount']
if not all(k in values for k in required):
return 'Missing values! Please enter customer name, item name and billing amount.', 400
index = blockchain.new_transaction(values['Customer name'], values['Item name'], values['Total billing amount'])
response = {
'message': f'Transaction will be added to block {index}'
}
return jsonify(response), 201
# Endpoint for viewing the blockchain
@app.route('/chain', methods=['GET'])
def full_chain():
response = {
'chain': blockchain.chain,
'length': len(blockchain.chain)
}
return jsonify(response), 200
# Endpoint for adding HTTP address of new nodes along with their stakes in the network.
@app.route('/nodes/add', methods=['POST'])
def add_nodes():
values = request.get_json()
required = ['nodes', 'stake']
if not all(k in values for k in required):
return 'Error', 400
blockchain.add_node(values['nodes'], values['stake'])
response = {
'message': 'New nodes are added!',
'total_nodes': list(blockchain.nodes)
}
print(blockchain.nodes)
return jsonify(response), 201
# Endpoint to start the voting process
@app.route('/voting', methods=['GET'])
def voting():
if port == 5000:
show_votes = blockchain.add_vote()
response = {
'message': 'The voting results are as follows:',
'nodes': blockchain.voteNodespool
}
return jsonify(response), 200
else:
response = {
'message': 'You are not authorized to conduct the election process!'
}
return jsonify(response), 400
# Endpoint to view the list of all three elected delegate nodes
@app.route('/delegates/show', methods=['GET'])
def delegates():
show_delegates = blockchain.selection()
response = {
'message': 'The 3 delegate nodes selected for block mining are:',
'node_delegates': blockchain.delegates
}
return jsonify(response), 200
# Endpoint to synchronise the list of elected delegates with all other nodes in the network
@app.route('/delegates/sync', methods=['GET'])
def sync_delegates():
sync_delegates = blockchain.sync()
response = {
'message': 'The delegate nodes are:',
'node_delegates': blockchain.delegates
}
return jsonify(response), 200
# Endpoint to resolve and replace current chain with the longest validated one,achieving consensus
@app.route('/chain/resolve', methods=['GET'])
def consensus():
replaced = blockchain.resolve_chain()
if replaced:
response = {
'message': 'Our chain was replaced',
'new_chain': blockchain.chain
}
else:
response = {
'message': 'Our chain is authoritative',
'chain': blockchain.chain
}
return jsonify(response), 200
if __name__ == '__main__':
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('-p', '--port', default=5000, type=int, help='Listening on port')
args = parser.parse_args()
port = args.port
app.run(host='0.0.0.0', port=port)