Blockchain and Cryptocurrency Tutorial using Python

Blockchain and Cryptocurrency Tutorial using Python

Introduction

        Blockchain and Cryptocurrency are the two most popular buzz words in the technology industry today. Blockchain is the technology on which the most popular Cryptocurrency Bitcoin is built upon. I was searching online for a tutorial to understand about Blockchain and how it is used in cryptocurrencies, but I could not find simple examples, hence I decided to come up with this post. In this post, we will understand about Blockchain by building our own cryptocurrency, that I have named as Alpha, using Python.

Blockchain and Cryptocurrency

        Blockchain in simple terms is a chain of blocks or a list of records. It is an open, distributed ledger that can record transactions between two parties efficiently and in a verifiable and permanent way and it cannot be edited. In a broader sense it is a domain and a technology. Cryptocurrency is one of the practical applications of Blockchain technology. 
        A blockchain is managed by a peer-to-peer network collectively adhering to a protocol for inter-node communication and validating new blocks. Hence it can be used as a distributed ledger.
        Here are a few terms related to Blockchain that you should understand before proceeding with this tutorial:
  1. Genesis Block: This is the first block in a blockchain. This has to be created to start the chaining process in a Blockchain.
  2. Consensus: In simple terms, it is a way of reaching agreement in a group. As part of this all the parties in the blockchain network decide on a protocol or a set of rules to be followed in order to use the network and the process to allow new blocks to be added to it.
  3. PoW (Proof of Work): It is one of the ways of reaching consensus in a blockchain network. PoW consensus is used in Bitcoin. As part of this,  people need to solve hard problems to create new blocks in a blockchain network.
Requirements to Run the Application:
1. Anaconda
2. Intellij IDE with Python Community Edition Plugin

 Anaconda bundles up Python installation and the most widely used Python libraries for your machine.  If Anaconda is not installed, then Python needs to be installed separately and the individual Python libraries need to be downloaded using the pip install command which would be very time consuming. Hence Anaconda should be setup on your machine. To setup and verify if Anaconda is installed, please refer to my post on: Anaconda Setup.

In this tutorial I will help you to build our own Blockchain based Cryptocurrency using Python in a few simple steps.

Step 1: Create file: setup.py

setup.py is used to to build and install the application. Add basic information about the application in setup.py. Once you have this file created, you can build and install the application using the commands:
python setup.py build
python setup.py install
Here is setup.py:
from setuptools import setup

setup(name='BlockchainCryptocurrency',
      version='1.0.0',
      description='A Simple Blockchain based Cryptocurrency'
      )

Step 2: Create file: alpha.py

In alpha.py, we will be building a simple Blockchain and a simple cryptocurrency based on it.
Here is alpha.py:
import hashlib
import datetime
import json
import pprint


class Block:
    def __init__(self, timestamp, transaction, previous_block=''):
        self.timestamp = timestamp
        self.previousBlock = previous_block
        self.transaction = transaction
        self.difficultyIncrement = 7777
        self.hash = self.calculate_block_hash_key(transaction, timestamp, self.difficultyIncrement)

    def calculate_block_hash_key(self, data, timestamp, difficulty_increment):
        data = str(data) + str(timestamp) + str(difficulty_increment)
        data = data.encode()
        hash_key = hashlib.sha256(data)
        return hash_key.hexdigest()

    def mine_new_block(self, difficulty):
        difficulty_check = "3" * difficulty
        while self.hash[:difficulty] != difficulty_check:
            self.hash = self.calculate_block_hash_key(self.transaction, self.timestamp, self.difficultyIncrement)
            self.difficultyIncrement = self.difficultyIncrement + 1


class Blockchain:
    def __init__(self):
        self.chain = [self.genesis_block()]
        self.difficulty = 4
        self.pendingTransaction = []
        self.reward = 20

    def genesis_block(self):
        genesis_block = Block(str(datetime.datetime.now()), "This is the Genesis Block")
        return genesis_block

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

    def mine_pending_transaction(self, miner_reward_address):
        new_block = Block(str(datetime.datetime.now()), self.pendingTransaction)
        new_block.mine_new_block(self.difficulty)
        new_block.previousBlock = self.get_the_last_block().hash

        print("Previous Block's Hash key: " + new_block.previousBlock)
        transaction_chain = []
        for transaction in new_block.transaction:
            single_transaction = json.dumps(transaction.__dict__, indent=0, separators=(',', ': ')).replace("\n", "")
            transaction_chain.append(single_transaction)
        pprint.pprint(transaction_chain)

        self.chain.append(new_block)
        print("Block's Hash key: " + new_block.hash)
        print("New Block has been added"+ "\n")

        reward_transaction = Transaction("System", miner_reward_address, self.reward)
        self.pendingTransaction.append(reward_transaction)
        self.pendingTransaction = []

    def is_chain_valid(self):
        for x in range(1, len(self.chain)):
            current_block = self.chain[x]
            previous_block = self.chain[x - 1]

            if (current_block.previousBlock != previous_block.hash):
                return "\n"+"The Blockchain is not valid!"
        return "\n"+"The Blockchain is stable and valid"

    def create_transaction(self, transaction):
        self.pendingTransaction.append(transaction)

    def get_the_balance(self, wallet_address):
        balance = 0
        for block in self.chain:
            if block.previousBlock == "":
                continue
            for transaction in block.transaction:
                if transaction.fromWallet == wallet_address:
                    balance -= transaction.amount
                if transaction.toWallet == wallet_address:
                    balance += transaction.amount
        #Round Balance to 2 decimal places
        balance = round(balance,2)
        return balance


class Transaction:
    def __init__(self, fromWallet, toWallet, amount):
        self.fromWallet = fromWallet
        self.toWallet = toWallet
        self.amount = amount


alpha = Blockchain()
alpha.create_transaction(Transaction("Jane", "Jim", 7.4))
alpha.create_transaction(Transaction("Jane", "Mary", 3))

print("Frank started mining")

alpha.mine_pending_transaction("Frank")
alpha.create_transaction(Transaction("John", "Jim", 40.47))
alpha.create_transaction(Transaction("Steve", "Jane", 11))
alpha.create_transaction(Transaction("Mary", "John", 60))
alpha.create_transaction(Transaction("Jim", "Mary", 62.47))

print("Frank started mining")

alpha.mine_pending_transaction("Frank")
alpha.create_transaction(Transaction("John", "Steve", 15))
alpha.create_transaction(Transaction("John", "Jim", 16))
alpha.create_transaction(Transaction("Frank", "John", 15))

print("Frank started mining")
alpha.mine_pending_transaction("Frank")

# Frank earned 60 Alpha Coins by mining and gave 15 Alpha Coins to John. So Frank's balance is now 45 Alpha Coins
print("Frank has " + str(alpha.get_the_balance("Frank")) + " Alpha Coins on his account")
print("Jane has " + str(alpha.get_the_balance("Jane")) + " Alpha Coins on her account")
print("Jim has " + str(alpha.get_the_balance("Jim")) + " Alpha Coins on his account")
print("Mary has " + str(alpha.get_the_balance("Mary")) + " Alpha Coins on her account")
print("John has " + str(alpha.get_the_balance("John")) + " Alpha Coins on his account")
print("Steve has " + str(alpha.get_the_balance("Steve")) + " Alpha Coins on his account")
print(alpha.is_chain_valid())
Here is the explanation for the code in alpha.py:

 I have structured the code into 3 classes:
  • Block which has all the code related to a block in the blockchain.
  • Blockchain which has all the code to chain blocks.
  • Transaction which has code related to a transaction in a blockchain.
1. To create a simple cryptocurrency, which I have named Alpha, first an instance of Blockchain class needs to be created. The code in alpha.py, starts executing from here. Here is the code for this:
alpha = Blockchain()
2. Next the execution goes to the class Blockchain, and the following code gets executed:
class Blockchain:    
    def __init__(self):
        self.chain = [self.genesis_block()]
        self.difficulty = 4
        self.pendingTransaction = []
        self.reward = 20

    def genesis_block(self):
        genesis_block = Block(str(datetime.datetime.now()), "This is the Genesis Block")
        return genesis_block
Here the Genesis Block (the first block in a Blockchain) is created and the class Block is called to do it.

3. The fundamental component of any Blockchain is a Block. I will be storing the following attributes in each Block that I create:
  • timestamp: Timestamp of when the block is created
  • previousBlock: Hash key of the previous block
  • transaction: Transaction data stored within the block
  • difficultyIncrement: A random number which is used in the calculate_block_hash_key function
  • hash: Block's own hash key
Here is the code corresponding to this:
class Block:
    def __init__(self, timestamp, transaction, previous_block=''):
        self.timestamp = timestamp
        self.previousBlock = previous_block
        self.transaction = transaction
        self.difficultyIncrement = 7777
        self.hash = self.calculate_block_hash_key(transaction, timestamp, self.difficultyIncrement)
4. Next a few transactions are created in the Blockchain that we just created using the following code:
alpha.create_transaction(Transaction("Jane", "Jim", 7.4))
alpha.create_transaction(Transaction("Jane", "Mary", 3))
5. Next the function mine_pending_transaction is called in the code below:
alpha.mine_pending_transaction("Frank")
6. In this blockchain, we will be implementing Proof of Work (PoW) consensus to create blocks and to add them to the Blockchain network. In PoW consensus, people solve hard problems to create blocks. Those people who solve these hard problems are known as miners. Usually cryptocurrency networks reward miners with cryptocurrency coins for their hard work. In this post, a block will not be created unless its hash key starts with four consecutive “3”s. This is an example of a consensus in a blockchain network and I have enforced this. After the consensus is satisfied, I am rewarding 20 Alpha Coins to a miner who solves this problem. Then the new block is appended to the blockchain.
All the logic for this is present in the code below:
def mine_pending_transaction(self, miner_reward_address):
        new_block = Block(str(datetime.datetime.now()), self.pendingTransaction)
        new_block.mine_new_block(self.difficulty)
        new_block.previousBlock = self.get_the_last_block().hash

        print("Previous Block's Hash key: " + new_block.previousBlock)
        transaction_chain = []
        for transaction in new_block.transaction:
            single_transaction = json.dumps(transaction.__dict__, indent=0, separators=(',', ': ')).replace("\n", "")
            transaction_chain.append(single_transaction)
        pprint.pprint(transaction_chain)

        self.chain.append(new_block)
        print("Block's Hash key: " + new_block.hash)
        print("New Block has been added" + "\n")

        reward_transaction = Transaction("System", miner_reward_address, self.reward)
        self.pendingTransaction.append(reward_transaction)
        self.pendingTransaction = []
As part of the code above, mine_new_block and calculate_block_hash_key are called. Here is the code corresponding to these calls:
    def mine_new_block(self, difficulty):
        difficulty_check = "3" * difficulty
        while self.hash[:difficulty] != difficulty_check:
            self.hash = self.calculate_block_hash_key(self.transaction, self.timestamp, self.difficultyIncrement)
            self.difficultyIncrement = self.difficultyIncrement + 1
    
    def calculate_block_hash_key(self, data, timestamp, difficulty_increment):
        data = str(data) + str(timestamp) + str(difficulty_increment)
        data = data.encode()
        hash_key = hashlib.sha256(data)
        return hash_key.hexdigest()
7. Then there is a function to check the balance of each person on the cryptocurrency network. Here is the code for this:
    def get_the_balance(self, wallet_address):
        balance = 0
        for block in self.chain:
            if block.previousBlock == "":
                continue
            for transaction in block.transaction:
                if transaction.fromWallet == wallet_address:
                    balance -= transaction.amount
                if transaction.toWallet == wallet_address:
                    balance += transaction.amount
        # Round Balance to 2 decimal places
        balance = round(balance, 2)
        return balance
8. Finally there is a function to check if the Blockchain is stable and valid. The previous block's hash key is used to link the blocks together. This prevents any block from being edited or a block being inserted between two existing blocks. This is checked in the code below:
    def is_chain_valid(self):
        for x in range(1, len(self.chain)):
            current_block = self.chain[x]
            previous_block = self.chain[x - 1]

            if (current_block.previousBlock != previous_block.hash):
                return "\n" + "The Blockchain is not valid!"
        return "\n" + "The Blockchain is stable and valid"

Run Application:

1. To run the application, in Anaconda Prompt, navigate to your project location and execute the command:
python alpha.py
2. To run the application in Intellij IDE, right click the file alpha.py and click Run 'alpha'

Conclusion and GitHub link:   

    In this post I have given you a comprehensive overview of Blockchain and building your own basic Cryptocurrency using Python. The code used in this post is available on GitHub.  
    Learn the most popular and trending technologies like Machine Learning, Chatbots, Internet of Things (IoT), Big Data Processing, Elastic Stack, React, Highcharts, Progressive Web Application (PWA), Angular 5, GraphQL, Akka HTTP, Play Framework, Dropwizard, Docker, Netflix Eureka, Netflix Zuul, Spring Cloud, Spring Boot, Flask and RESTful Web Service integration with MongoDB, Kafka, Redis, Aerospike, MySQL DB in simple steps by reading my most popular blog posts at Software Developer Central.  
    If you like my post, please feel free to share it using the share button just below this paragraph or next to the heading of the post. You can also tweet with #SoftwareDeveloperCentral on Twitter. To get a notification on my latest posts or to keep the conversation going, you can follow me on Twitter or Instagram. Please leave a note below if you have any questions or comments.

Comments

Popular Posts

Dropwizard MySQL Integration Tutorial

Golang gRPC Microservice

Asynchronous Processing (@Async) in Spring Boot