Build A Blockchain In Python (Example)

The best way to learn Blockchain is to learn by doing.

Are you overwhelmed by the rise in the price of the Bitcoin cryptocurrency? You want to “understand” how Blockchain works – the underlying technology behind Bitcoin but everything is limited to “knowing” because it is only possible to skim through articles and video tutorials about Blockchain without examples.

This article will help you create your own blockchain. If you follow through to the end of this tutorial, you will be able to create a working blockchain yourself and understand how it works.

Get Ready

Remember that a blockchain is a sequential immutable chain, the records of which are called “blocks”. They can contain transactions, files or any other data you like. The important thing is that they are linked together using a hash function (hash).

If you are not familiar with Blockchain, this article is for you.

Who is the guide for? Those of you who can read and write basic Python code and know about HTTP — the protocol that is used to communicate between two parties on the internet.

What to prepare? Python 3.6+ using pip.  You also need to install wonderful Requests and Flask library. To do so, simply run the command below.

pip install Flask==0.12.2 requests==2.18.4 

If you are using the Windows environment, you can directly go to python.org to download the latest version of Python.

Getting Started With Building a Blockchain

Step 1: Blockchain Creation

Open Text Editor or your favorite IDE, create a new file blockchain.py. See the source code here. The first step is to make a functional blockchain solution. At first, we need to create a Blockchain class. 

Introduction to Blockchain class

There we will create a constructor that will initiate the chain and transaction list. The chain list will store our blockchain, whereas the transactions will be stored in the current_transacations array. Blockchain class:

class Blockchain(object):
    def __init__(self):
        self.chain = []
        self.current_transactions = []
        
    def new_block(self):
        # Creates a new Block and adds it to the chain
        pass
    
    def new_transaction(self):
        # Adds a new transaction to the list of transactions
        pass
    
    @staticmethod
    def hash(block):
        # Hashes a Block
        pass

    @property
    def last_block(self):
        # Returns the last Block in the chain
        pass

Structure of a block

A block contains vital information about transactions and chains. Any block on the chain will contain the following information:

  • index
  • timestamp in Unix time
  • transactions list
  • proof
  • Previous block hash

Example:

block = {
    'index': 1,
    'timestamp': 1506057125.900785,
    'transactions': [
        {
            'sender': "8527147fe1f5426f9dd545de4b27ee00",
            'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",
            'amount': 5,
        }
    ],
    'proof': 324984774000,
    'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}

Most of the information within the block are self-explanatory. Here, the two crucial variables are the previous_hash, which contains the hash value of the previous block. This is important as it makes sure that the blockchain is immutable, and no malicious actor can update, delete or add any data to the chain.

Adding Transaction To A Block

We will use new_transaction() to add a transaction to a block:

class Blockchain(object):
    ...
    
    def new_transaction(self, sender, recipient, amount):
        """
        Creates a new transaction to go into the next mined Block
        :param sender: <str> Address of the Sender
        :param recipient: <str> Address of the Recipient
        :param amount: <int> Amount
        :return: <int> The index of the Block that will hold this transaction
        """

        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1

Once the addition is done, the method then sends the block index to the chain. It is the next block that is going to be mined.

Creating new Blocks

Once the blockchain class is initialized, we need to create the genesis block. In addition, we will need to add a proof to the genesis block. We will create new_block(), new_transaction() and hash() methods as follows:

import hashlib
import json
from time import time


class Blockchain(object):
    def __init__(self):
        self.current_transactions = []
        self.chain = []

        # Create the genesis block
        self.new_block(previous_hash=1, proof=100)

    def new_block(self, proof, previous_hash=None):
        """
        Create a new Block in the Blockchain
        :param proof: <int> The proof given by the Proof of Work algorithm
        :param previous_hash: (Optional) <str> Hash of previous Block
        :return: <dict> New Block
        """

        block = {
            'index': len(self.chain) + 1,
            'timestamp': time(),
            'transactions': self.current_transactions,
            'proof': proof,
            'previous_hash': previous_hash or self.hash(self.chain[-1]),
        }

        # Reset the current list of transactions
        self.current_transactions = []

        self.chain.append(block)
        return block

    def new_transaction(self, sender, recipient, amount):
        """
        Creates a new transaction to go into the next mined Block
        :param sender: <str> Address of the Sender
        :param recipient: <str> Address of the Recipient
        :param amount: <int> Amount
        :return: <int> The index of the Block that will hold this transaction
        """
        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1

    @property
    def last_block(self):
        return self.chain[-1]

    @staticmethod
    def hash(block):
        """
        Creates a SHA-256 hash of a Block
        :param block: <dict> Block
        :return: <str>
        """

        # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
        block_string = json.dumps(block, sort_keys=True).encode()
        return hashlib.sha256(block_string).hexdigest()

Proof-Of-Work

What is Proof of Work? It is a consensus method that is utilized to add new blocks into the chain. It poses a challenge to the miner, and once the miner solves the problem, the block is then verified. The miner, in return, gets a reward based on the problem complexity. Bitcoin’s Proof of Work is known as Hashcash. It ensures that the bitcoin network consensus work as intended.

We will look at a simple example to understand this in depth.

The hash of the integer x * y must end in 0. Then the hash is of the form: hash(x * y) = ac23dc...0. Now we will try with x=5.  Our code stands as below.

from hashlib import sha256
x = 5
y = 0  # We don't know what y should be yet...
while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0":
    y += 1
print(f'The solution is y = {y}')

The solution here is y = 21. Since then, the generated hash ends in 0.

hash(5 * 21) = 1253e9373e...5e3600155e860

Triển khai Bằng chứng công việc (Pow) cơ bản

Our next step in building blockchain.py is the Proof-of-Work implementation. Hãy triển khai một thuật toán tương tự cho blockchain của chúng ta. Quy tắc sẽ tương tự như ví dụ trên:

Find a number p that, when hashed with the previous block’s hash, produces a hash with 4 leading 0.

import hashlib
import json

from time import time
from uuid import uuid4


class Blockchain(object):
    ...
        
    def proof_of_work(self, last_proof):
        """
        Simple Proof of Work Algorithm:
         - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
         - p is the previous proof, and p' is the new proof
        :param last_proof: <int>
        :return: <int>
        """

        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        return proof

    @staticmethod
    def valid_proof(last_proof, proof):
        """
        Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes?
        :param last_proof: <int> Previous Proof
        :param proof: <int> Current Proof
        :return: <bool> True if correct, False if not.
        """

        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()
        return guess_hash[:4] == "0000"

You can increase the difficulty of the hash by adding more zeroes. Here we will put 4 zeroes. Our blockchain layer is almost done and can be done using HTTP Requests.

Step 2: API Integration

Great, we create a blockchain that works! Now, to use it effectively, we need to create an API(Application Programming Interface).

To do so, we are going to use the popular Python Framework: Flask.

Flask is a micro-framework, which means that it is lightweight, and you can add the libraries that you need. It also enables you to create Python function endpoint easily. We need to create three endpoints as below.

  • /transactions/new to create a new transaction for a block.
  • /mine to ask our server to mine a new block.
  • /chain to return the entire Blockchain.

Flask framework

Our “server” will form a single node in our blockchain network. Let’s create a codeframe like this:

import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4

from flask import Flask


class Blockchain(object):
    ...


# Instantiate our Node
app = Flask(__name__)

# Generate a globally unique address for this node
node_identifier = str(uuid4()).replace('-', '')

# Instantiate the Blockchain
blockchain = Blockchain()


@app.route('/mine', methods=['GET'])
def mine():
    return "We'll mine a new Block"
  
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
    return "We'll add a new transaction"

@app.route('/chain', methods=['GET'])
def full_chain():
    response = {
        'chain': blockchain.chain,
        'length': len(blockchain.chain),
    }
    return jsonify(response), 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
  • Line 15: Initialize the node.
  • Line 18: Generate a random name for the button.
  • Line 21: Initialize the Blockchain class.
  • Lines 24–26: Create the /mine endpoint using the GET method.
  • Lines 28–30: Create the /transactions/new endpoint using the POST method, as we will be sending data there.
  • Lines 32–38: Create an endpoint /chain that uses the GET method to return the entire Blockchain.
  • Lines 40–41: Launch the server on port 5000.

Transaction endpoint

Below is the data (content) of a request for a transaction. That’s what the user sends to the server:

{
 "sender": "my address",
 "recipient": "someone else's address",
 "amount": 5
}

Since we already have a method to add transactions to a block, we will now write a function to add transactions:

import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4

from flask import Flask, jsonify, request

...

@app.route('/transactions/new', methods=['POST'])
def new_transaction():
    values = request.get_json()

    # Check that the required fields are in the POST'ed data
    required = ['sender', 'recipient', 'amount']
    if not all(k in values for k in required):
        return 'Missing values', 400

    # Create a new Transaction
    index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])

    response = {'message': f'Transaction will be added to Block {index}'}
    return jsonify(response), 201

Mining Endpoint

  1. Proof of Work calculation
  2. Forge new blockchain and then add it to the chain
  3. Reward the miner for his work (this is us) by adding a transaction that grants us 1 coin.
import hashlib
import json

from time import time
from uuid import uuid4

from flask import Flask, jsonify, request

...

@app.route('/mine', methods=['GET'])
def mine():
    # We run the proof of work algorithm to get the next proof...
    last_block = blockchain.last_block
    last_proof = last_block['proof']
    proof = blockchain.proof_of_work(last_proof)

    # We must receive a reward for finding the proof.
    # The sender is "0" to signify that this node has mined a new coin.
    blockchain.new_transaction(
        sender="0",
        recipient=node_identifier,
        amount=1,
    )

    # Forge the new Block by adding it to the chain
    previous_hash = blockchain.hash(last_block)
    block = blockchain.new_block(proof, previous_hash)

    response = {
        'message': "New Block Forged",
        'index': block['index'],
        'transactions': block['transactions'],
        'proof': block['proof'],
        'previous_hash': block['previous_hash'],
    }
    return jsonify(response), 200

Notice that the recipient of the mined block is our node address. Now, everything is done and we can start interacting with the blockchain.

Step 3: Blockchain Interaction

The last step is to interact with the blockchain. We are going to use Postman to interact with the blockchain network using the API we just created.

Run the code below on the Python Console

$ python blockchain.py

Conclusion

This leads us to the end of our How to build a blockchain. Hopefully this guide will inspire you to start a new project, or simply keep you motivated as you enter the blockchain world.

Reference:

101blockchains

comdy