Develop a Blockchain using Python, Flask & Postman: Part 2

Aditya Kumar
The Startup
Published in
8 min readNov 4, 2019
blog post cover photo; blockchain development part 2
Original business vector created by pikisuperstar — www.freepik.com (Edited)

Here is the link to Github Repository for the Project https://github.com/adi2381/py-blockchain

Welcome to Part 2 of Blockchain Development using Python, Flask & Postman.

I will begin by explaining the phases of blockchain development and further steps associated with them and some theories regarding the methods as well.

Getting Started

Install Necessary Software

  • Download Anaconda
  • Download Visual Studio Code
  • Download Postman

Install Dependencies

Flask — pip install flask

Flask-Cors — pip install -U flask-cors

Python-Requests — pip install requests

Pycrypto — pip install pycrypto

Hashlib — pip install hashlib

Running the Project

  • Clone Repository to your system
  • Create a blockchain folder and put everything in it
  • Open the above-created directory in Visual Studio Code and then any python file, that will load all the python related extensions
  • On the top click on the terminal and create a new terminal
  • Type in activate to activate the anaconda base environment
  • Run the following command to run the file, this will create a file and by default run on port 5000

python node.py

  • Run the following command in a new terminal with -p to specify a new port on which you can run new node

python node.py -p 5001

  • Open Postman application and if you’re using it for the first time, just set the default settings according to your self then once you’re on the main window you will have an address bar to make API requests and make sure you set the methods appropriate when making requests such as POST, DELETE or GET
  • Common API calls — POST Method is called when you want to add data, GET Method is called when you want to obtain some data and DELETE method is called when you want to delete some data.
  • Below is an image containing all the API calls that can be made in this project and the result they yield
A graphical chart containing all the API calls for the project
API Calls chart

Phases of Blockchain Project

Chain of Blocks: This phase involves creating a chain of blocks in which each block in the chain contains “index”, “previous_hash”, “transaction”, “proof of work number (a.k.a nonce)” and “timestamp” as it’s data.

The index is the index number of the block, previous_hash contains the hash of the previous block in the blockchain, the transaction contains a list of transactions and proof of work number is the number generated automatically upon successful mining of the block.

from time import time
from utility.printable import Printable
class Block(Printable):
def __init__(self, index, previous_hash, transactions, proof, time=time()):
self.index = index
self.previous_hash = previous_hash
self.timestamp = time
self.transactions = transactions
self.proof = proof

Hashing the blocks: We need to hash the blocks in order to avoid the manipulation of blockchain is such a way that someone cannot alter the value of 2nd block in our blockchain (of 10 blocks) to something else.

So, we use the SHA256 algorithm for hashing the blocks. Through hashing we get the hash of the previous block in the next block of our blockchain and if the hash matches then the block is valid else invalid.

import hashlib as hl
import json
def hash_string_256(string):
return hl.sha256(string).hexdigest()
def hash_block(block):
hashable_block = block.__dict__.copy()
hashable_block['transactions'] = [tx.to_ordered_dict() for tx in hashable_block['transactions']]
return hash_string_256(json.dumps(hashable_block, sort_keys=True).encode())

Mining Block: Mining a block means that any unprocessed and open transactions are added to a block. In order to successfully mine a block, the previous_hash, keys, proof of work and all should be valid. Also, to distribute the block to other peer nodes, we broadcast a copy of it.

def mine_block(self):
if self.public_key == None:
return None
last_block = self.__chain[-1]
hashed_block = hash_block(last_block)
proof = self.proof_of_work()
reward_transaction = Transaction(
'MINING', self.public_key, '', MINING_REWARD)
copied_transactions = self.__open_transactions[:]
for tx in copied_transactions:
if not Wallet.verify_transaction(tx):
return None
copied_transactions.append(reward_transaction)
block = Block(len(self.__chain), hashed_block,
copied_transactions, proof)
self.__chain.append(block)
self.__open_transactions = []
self.save_data()
for node in self.__peer_nodes:
url = 'http://{}/broadcast-block'.format(node)
converted_block = block.__dict__.copy()
converted_block['transactions'] = [
tx.__dict__ for tx in converted_block['transactions']]
try:
response = requests.post(url, json={'block': converted_block})
if response.status_code == 400 or response.status_code == 500:
print('Block declined, needs resolving')
except requests.exceptions.ConnectionError:
continue
return block

Verification & Validation: In order to validate the blockchain we first secure the individual blocks where we begin by storing the entire value of block 1 in block 2 and then the entire value of block 2 in block 3. This way block 3 will recognize if any changes have been made in block 2 as block 3 created a snapshot of block 2 which means that when block 3 was generated it also contained a copy of the entire value of block 2. So, in this way, it can cross-check for illegal modifications and verify the chain.

To summarize, in order to verify the blocks, we basically hash the previous blocks in our blockchain and this hash value is then stored in a field of the next block called “previous_hash”, if the value of this previous_hash field doesn’t match the recalculated new hash then that means that the previous block was tampered with and hence it makes the blockchain invalid.

To achieve the above we use the python enumerate and tuple unpacking, we wrap our blockchain list with enumerating so it returns a tuple which contains two values, index of the element and the element itself. These values are then cross-checked with the previous block for verification & consistency.

from utility.hash_util import hash_string_256, hash_block
from wallet import Wallet
class Verification:
@staticmethod
def valid_proof(transactions, last_hash, proof):
guess = (str([tx.to_ordered_dict() for tx in transactions]) + str(last_hash) + str(proof)).encode()
guess_hash = hash_string_256(guess)
return guess_hash[0:2] == '00'

@classmethod
def verify_chain(cls, blockchain):
for (index, block) in enumerate(blockchain):
if index == 0:
continue
if block.previous_hash != hash_block(blockchain[index - 1]):
return False
if not cls.valid_proof(block.transactions[:-1], block.previous_hash, block.proof):
print('Proof of work is invalid')
return False
return True

Storing Data to Disk: To save data, we basically created a blockchain.txt file in which all the transaction details are stored, this file is created the moment you make your first transaction or mine the block. There are also different files created for each node. The data is stored in JSON format however there is a sample pickle file also in the legacy_blockchain folder. The reason why JSON was so we can inspect the data, JSON stores the data in the form of dictionaries so it’s easier to inspect the data and search for any anomalies whereas pickle, on the other hand, saves the data in binary format.

Generate Wallet: A wallet is used to store your funds, information about your transactions and your public and private keys. The private key is just for the user and must be stored securely. If it is lost, coins can’t be accessed anymore because the private key is used to create a signature for outgoing transactions. The signature includes the transaction data and is then created with the private key. So, we create an encoded string from the transaction data. The public key can’t read this encoded string but it can verify that the signature that the encoded string holds is associated with the signature of our private key and hence cross verify. The private key cannot be lost at any cost because then you can’t verify that the public key really belongs to you as the private key has a unique signature associated with you. Below is just the starting part of the wallet.py file to give you an idea about it.

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
import Crypto.Random
import binascii
class Wallet:def __init__(self, node_id):
self.private_key = None
self.public_key = None
self.node_id = node_id
def create_keys(self):
private_key, public_key = self.generate_keys()
self.private_key = private_key
self.public_key = public_key

Perform Transactions: There is mining_reward in the project which you can call by the API Request of localhost:5000/mine, this will give you 10 coins. You can further then use these coins to make transactions. Also, once you perform a transaction, they are added to the list of open_transactions which means they haven’t been verified yet (being verified here means being part of a block/mined into the block). To verify the transaction, you can call the same MINE API call which will add the transaction into a block. Below code is just to show the data in our transactions and to point out that we specifically use Ordered_dict majorly to store everything because the normal python dictionary doesn’t fetch or store the data in an ordered form and since in blockchain it’s all about having a serialized form of consistent data, we use ordered_dict. The main transaction methods can be found in the blockchain.py file.

class Transaction(Printable):
def __init__(self, sender, recipient, signature, amount):
self.sender = sender
self.recipient = recipient
self.amount = amount
self.signature = signature

def to_ordered_dict(self):
return OrderedDict([('sender', self.sender), ('recipient', self.recipient), ('amount', self.amount)])

Add Routes: In this phase, we use Flask to create routes. Now, routes are nothing but endpoints and endpoints are simply URL’s which have to be accessed in order to perform some action. For example, when you use localhost:5000/mine API call where “localhost:5000/mine” is a URL, you are requesting the URL to perform the Mining Block action for you. So, in order to test all the functionalities in the project, similar API calls have been created using Flask. API calls can be found in the node.py file. Below is one section of that file, it includes Creating a wallet which is a POST request and fetching a wallet which is a GET request.

from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
from wallet import Wallet
from blockchain import Blockchain
app = Flask(__name__)
CORS(app)
@app.route('/wallet', methods=['POST'])
def create_keys():
wallet.create_keys()
if wallet.save_keys():
# We reinitialise blockchain since we're using a POST request and also
# instruct function to use global blockchain variable
global blockchain
blockchain = Blockchain(wallet.public_key, port)
response = {
'public_key': wallet.public_key,
'private_key': wallet.private_key,
'funds': blockchain.get_balance()
}
return jsonify(response), 201
else:
response = {
'message': 'Saving keys failed.'
}
return jsonify(response), 500
@app.route('/wallet', methods=['GET'])
def load_keys():
if wallet.load_keys():
global blockchain
blockchain = Blockchain(wallet.public_key, port)
response = {
'public_key': wallet.public_key,
'private_key': wallet.private_key,
'funds': blockchain.get_balance()
}
return jsonify(response), 201
else:
response = {
'message': 'Loading the keys failed.'
}
return jsonify(response), 500

In the above phases, I’ve explained in short about what we generally do in each other those phases, for a brief explanation, please refer to the files in the Github repository which contains docstrings and comments explaining everything

To Conclude

This project explores the functionalities of blockchain and how to implement them mainly in a pythonic way. However, with all the security implemented in the project and stability, it’s still nowhere robust enough to be able to be compared to a live blockchain project and their robustness and security. The project still has scope for improvement, for example, implementing Merkle root for the blocks and also adding a frontend to show the functionalities live instead of through API calls in Postman application.

Following is the link to Github repository for this project, feel free to contribute or clone it and create your very own blockchain project referencing it. If you do create blockchain projects like this once do let me know about it, I’d love to check it out!

https://github.com/adi2381/py-blockchain

Thank you for Reading!

Link for First Part

--

--