DEV Community

vinayak
vinayak

Posted on • Originally published at itsvinayak.hashnode.dev on

How To Build A Blockchain In Python

Blockchain is a shared, immutable ledger that simplifies the method of recording transactions and tracking assets in a network. It's a constantly growing list of records known as a block. These blocks are connected, creating a chain known as a blockchain.

The fundamental feature of blockchain :

  • Immutable and Unhackable records

  • Distributed ledger technology

  • Persistent in storing data (no loss of data)

Setting up Virtualenv & Installing Dependencies 🔌

create a virtualenv, using python's built-in module called venv. Here env is the name of the environment.

python3 -m venv env 
Enter fullscreen mode Exit fullscreen mode

for activating this virtualenv, we need to source it.

source ./env/bin/activate 
Enter fullscreen mode Exit fullscreen mode

Installing Dependencies

we need flask as a dependency for serving our blockchain

pip install Flask==2.2.2 
Enter fullscreen mode Exit fullscreen mode

Setting up Folder Structure 🗂

  • create a base folder, and name it blockchain

  • inside this folder create a file called blockchain.py which will hold our blockchain code.

  • create another file called server.py this will contain our server code, to server our blockchain.

Creating a Blockchain

Import Dependencies

 import datetime import json import hashlib import time 
Enter fullscreen mode Exit fullscreen mode

Now, create a class called blockchain , which will hold all our logic and chain itself. Inside this blockchain class, we will have some functions.

  • init : initialize the blockchain, and creates a Genius Block
 def __init__ (self) -> None: """ initialize the blockchain """ self.chain = [] # create the genesis block self.create_block(proof=1, previous_hash="0") 
Enter fullscreen mode Exit fullscreen mode
  • create_block : this function creates a new block and adds it to the blockchain, it takes proof and the previous hash as an argument
 def create_block(self, proof, previous_hash): """ add a new block to the blockchain """ block = {} block["index"] = len(self.chain) + 1 block["timestamp"] = str(datetime.datetime.now()) block["proof"] = proof block["previous_hash"] = previous_hash self.chain.append(block) return block 
Enter fullscreen mode Exit fullscreen mode
  • get_previous_block : This function gets the previous block, which is added to the blockchain
 def get_previous_block(self): """ get the previous block """ return self.chain[-1] 
Enter fullscreen mode Exit fullscreen mode
  • proof_of_work : proof of work is a Consensus Protocol in blockchain used to define finding a number such that the hash of the number, is hard to find because it takes a lot of time, and computing power.
 def proof_of_work(self, previous_proof): start_time = time.time() new_proof = 1 check_proof = False while check_proof is False: hash_operation = hashlib.sha256( str(new_proof **2 - previous_proof** 2).encode() ).hexdigest() if hash_operation[:4] == "0000": check_proof = True else: new_proof += 1 elapsed = time.time() - start_time print(' time take to get new_proof using pow : ', elapsed) return new_proof 
Enter fullscreen mode Exit fullscreen mode
  • hash : hash function takes a block and converts it into hash using sha256 , and returns the hash
 def hash(self, block) -> str: """ hash the block using sha256, and return the hash """ encoded_block = str(json.dumps(block, sort_keys=True)).encode('utf-8') hash = hashlib.sha256(encoded_block).hexdigest() return hash 
Enter fullscreen mode Exit fullscreen mode
  • is_chain_valid : check if the blockchain is valid
 def is_chain_valid(self, chain): """ check if the blockchain is valid """ if chain == [] or chain == None: # if the chain is empty or None, then the chain is not passed as a parameter chain = self.chain previous_block = chain[0] block_index = 1 while block_index < len(chain): block = chain[block_index] if block["previous_hash"] != self.hash(previous_block): return False previous_proof = previous_block["proof"] proof = block["proof"] hash_operation = hashlib.sha256( str(proof **2 - previous_proof** 2).encode() ).hexdigest() if hash_operation[:4] != "0000": return False previous_block = block block_index += 1 return True 
Enter fullscreen mode Exit fullscreen mode

Creating a web server

Creating a Flask web server

import os from flask import Flask, jsonify # env PORT = os.getenv('PORT', 8080) DEBUG = os.getenv('DEBUG', True) app = Flask( __name__ ) @app.route('/', methods=['GET']) def home(): return "<h1>Welcome to the Blockchain</h1>", 200 if __name__ == " __main__": app.run(host="0.0.0.0", port=PORT, debug=DEBUG) 
Enter fullscreen mode Exit fullscreen mode

Importing our blockchain

importing and initializing blockchain will create Genius Block

from blockchain import Blockchain blockchain = Blockchain() 
Enter fullscreen mode Exit fullscreen mode

Adding mine_block function

This mine_block function helps used to mine a block in a given blockchain

@app.route('/mine_block', methods=['GET']) def mine_block(): previous_block = blockchain.get_previous_block() previous_proof = previous_block['proof'] proof = blockchain.proof_of_work(previous_proof) previous_hash = blockchain.hash(previous_block) block = blockchain.create_block(proof, previous_hash) response = {} response['message'] = "Blocked is just mined !!" response['index'] = block['index'] response['timestamp'] = block['timestamp'] response['previous_hash'] = block['previous_hash'] response['proof'] = block['proof'] return jsonify(response), 201 
Enter fullscreen mode Exit fullscreen mode

Adding get_chain function

This get_chain function will return a JSON list of blocks and its attribute.

@app.route('/get_chain', methods=['GET']) def get_chain(): blockchain_clone = blockchain.get_chain() return jsonify(blockchain_clone), 200 
Enter fullscreen mode Exit fullscreen mode

Adding is_valid function

This function checks if the current blockchain Is valid or not

@app.route('/is_valid', methods=['GET']) def is_valid(): is_valid = blockchain.is_chain_valid(blockchain.chain) if is_valid: response = {} response['message'] = "Blockchain is valid" return jsonify(response), 200 else: response = {} response['message'] = "Blockchain is not valid" return jsonify(response), 200 
Enter fullscreen mode Exit fullscreen mode

Starting webserver

To start the web server, we will execute the server.py

python3 server.py 
Enter fullscreen mode Exit fullscreen mode

All codes with docker files are present on GitHub

Top comments (0)