Skip to content

Commit

Permalink
Packaged the blockchain and the corresponding Flask-app.
Browse files Browse the repository at this point in the history
  • Loading branch information
Nevavuori Petteri committed May 15, 2018
1 parent 8ff268c commit 3b7b8df
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 0 deletions.
Empty file added notebooks/__init__.py
Empty file.
Empty file.
1 change: 1 addition & 0 deletions notebooks/blockchain/apps/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .blockchain import BlockchainApp
100 changes: 100 additions & 0 deletions notebooks/blockchain/apps/blockchain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import threading
import requests

from flask import Flask, request, jsonify

from ..chains import Blockchain

blockchain_app = Flask(__name__)
blockchain = Blockchain()


@blockchain_app.route('/blocks', methods=['GET', 'POST'])
def blocks():

if request.method == 'POST':

prev_block = blockchain.get_previous_block()
prev_hash = blockchain.hash_block(prev_block)
prev_proof = prev_block['proof']

proof = blockchain.proof_of_work(prev_proof)

block = blockchain.create_block(proof, prev_hash)

response = {
'message': 'Congratulations, you just mined a Block!',
'block': block
}

return (jsonify(response), 200)

if request.method == 'GET':

response = {
'blockchain': blockchain.chain,
'length': len(blockchain.chain),
}

return (jsonify(response), 200)


@blockchain_app.route('/blocks/validate', methods=['GET'])
def validate():

if blockchain.is_chain_valid(blockchain.chain):

response = {
'message': 'Chain is valid.',
'valid': True
}
return (jsonify(response), 200)

response = {
'message': 'Chain is not valid!',
'valid': False
}
return (jsonify(response), 500)


@blockchain_app.route('/shutdown')
def shutdown():

request.environ.get('werkzeug.server.shutdown')()

return jsonify({'message': 'Shutting down'}), 200


class BlockchainApp:

def __init__(self):

self.host = 'localhost'
self.port = 5000
self.host_url = 'http://{}:{}'.format(self.host, self.port)
self.thread = threading.Thread(
target=blockchain_app.run,
kwargs={'host': self.host, 'port': self.port})

def start(self):
self.thread.start()

def stop(self):
if self.thread.is_alive():
return requests.get('{}/shutdown'.format(self.host_url))

def mine_block(self):
return requests.post('{}/blocks'.format(self.host_url))

def get_blockchain(self):
return requests.get('{}/blocks'.format(self.host_url))

def validate_blockchain(self):
return requests.get('{}/blocks/validate'.format(self.host_url))

def __enter__(self):
self.start()
return self

def __exit__(self, *args):
self.stop()
71 changes: 71 additions & 0 deletions notebooks/blockchain/chains.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import datetime
import hashlib
import json


class Blockchain:

def __init__(self):
self.chain = []
self.create_block(proof=1, previous_hash='0')

def create_block(self, proof, previous_hash):
block = {
'index': len(self.chain),
'timestamp': str(datetime.datetime.now()),
'proof': proof,
'previous_hash': previous_hash,
}
self.chain.append(block)
return block

def get_previous_block(self):
return self.chain[-1]

def hash_proof(self, previous_proof, next_proof):
"Calculate the SHA256-hash"
return (hashlib
.sha256(str(next_proof**2 - previous_proof**2).encode())
.hexdigest())

def hash_block(self, block):
"Calculate the SHA256-hash for a block."

encoded_block = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(encoded_block).hexdigest()

def proof_of_work(self, previous_proof):
"Calculate a new proof related to the previous block."

next_proof = 1
check_proof = False

while check_proof is False:

if self.hash_proof(previous_proof, next_proof)[:4] == '0000':
check_proof = True

else:
next_proof += 1

return next_proof

def is_chain_valid(self, chain):
"Validate that block and proof hashes are correct across the chain."

for i in range(len(chain)):

if i == 0:
continue

if chain[i]['previous_hash'] != self.hash_block(chain[i - 1]):
return False

previous_proof = chain[i - 1]['proof']
next_proof = chain[i]['proof']

if self.hash_proof(previous_proof, next_proof)[:4] != '0000':

return False

return True

0 comments on commit 3b7b8df

Please sign in to comment.