How To Build A Blockchain In Python
Tags: python, blockchain, python3, build
Published: 2022-12-27 09:59:08

---
title: How To Build A Blockchain In Python
published: true
date: 2022-12-27 09:48:00 UTC
tags: #python #blockchain #python3 #build
canonical_url: https://itsvinayak.hashnode.dev/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

```

for activating this virtualenv, we need to source it.

```
source ./env/bin/activate

```

## Installing Dependencies

we need flask as a dependency for serving our blockchain

```
pip install Flask==2.2.2

```

## 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

```

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

```

- **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

```

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

```

- **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

```

- **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

```

- **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

```

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

```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1672133874564/2511ad5b-0796-4885-bde3-4e423fdde0bf.png)

### Importing our blockchain

importing and initializing blockchain will create **Genius Block**

```
from blockchain import Blockchain
blockchain = Blockchain()

```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1672134036492/54dc04c5-0ab3-4416-954f-3a878611174a.png)

### 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

```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1672133917106/82cd2e94-10d0-4861-b652-f69c69d28f87.png)

### 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

```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1672133950052/22de6b12-6571-4bc5-a121-3a41da116f3e.png)

### 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

```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1672133986615/f680ef82-87a9-4cce-8839-8de41f0be03b.png)

# Starting webserver

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

```
python3 server.py

```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1672133833836/928c9ed9-c68c-4116-aa11-488cea318f17.png)

[All codes with docker files are present on GitHub](https://github.com/itsvinayak/blockchain)