Building a Blockchain in Python

in #programming7 years ago

Building a Blockchain is very easy and anyone can do this with basics of programming. In this example we're going to use Python to build own Blockchain that can be used to send and receive money.

Note: This Blockchain is not for production purpose, it is just an example to explain you the functioning of Blockchain.

Let's see what will be the features of this Blockchain

1. Mine Blocks

2. Proof-of-Work

3. Miner Rewards

4. Transaction

5. Get Balance of users

Let's start and build our Blockchain

Transactions

Let's first build how our transactions will be structured. So let's create a class called "Transaction".

class Transaction:
   def __init__(self, from_address, to_address, amount):
       self.from_address = from_address
       self.to_address = to_address
       self.amount = amount

   def serialize(self):
       return {
           "from_address": self.from_address,
           "to_address": self.to_address,
           "amount": self.amount
       }

This Transaction class will store

from_address: Address from which money is sent.

to_address: Address to which money is sent.

amount: Amount of coins that is sent.

Our transaction class will also contain a "serialize" function to serialize the transaction in to a dictionary.

Blocks

Before structuring our blocks, let's import three modules.

from datetime import datetime
from hashlib import sha256
import json

Now let's create a "Block" class.

class Block:
   def __init__(self, timestamp, transactions, previous_hash):
       self.timestamp = timestamp
       self.transactions = transactions
       self.previous_hash = previous_hash
       self.nonce = 0
       self.hash = self.calculate_hash()

   def calculate_hash(self):
       hashing_string = (self.previous_hash
                         + str(self.timestamp)
                         + json.dumps(self.transactions, separators=(',', ':'))
                         + str(self.nonce)).encode('utf-8')
       return sha256(hashing_string).hexdigest()

In our Block class we will store the following

timestamp: It will be used to record the time when the Block was created

transactions: It will be used to store which transactions are in the Block

previous_hash: It will store the hash of the previous block. Previous hash will be useful to calculate the order of blocks in our blockchain.

nonce: This is an arbitrary value which we will update when we will implement mining.

hash: This hash will be calculated using "calculate_hash" method. This method will create a string called "hash_string" which will contain all the data of the Block and run SHA256 algorithm on it to create our hash which will be unique for every block on our blockchain.

Now let's implement mining in our Block class. Add the following method in your Block class.

def mine_block(self, difficulty):
   while not self.hash[:difficulty] == ("0"*difficulty):
       self.nonce += 1
       self.hash = self.calculate_hash()

This "mine_block" method will get first few characters of our hash whose length will be equal to "difficulty". And it will create a string containing zeros which will also be equal to "difficulty". And until those two strings will not be same it will change the nonce value which will change the hash of the block. And it will keep doing it until the hash begins with certain amount of zeros.

Blockchain

Now let's finally create our Blockchain class.

class Blockchain:
   def __init__(self, difficulty, mining_reward):
       self.chain = [self.create_genesis_block()]
       self.pending_transactions = []
       self.difficulty = difficulty
       self.mining_reward = mining_reward

   def create_genesis_block(self):
       return Block(datetime.now(),
                    [Transaction(None, 'kartik', 1000).serialize()],
                    '0')

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

   def is_chain_valid(self):
       if len(self.chain) == 1:
           return True

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

           if not current_block.hash == current_block.calculate_hash():
               return False

           if not current_block.previous_hash == previous_block.hash:
               return False

           return True

   def get_balance_of(self, address):
       balance = 0

       for block in self.chain:
           for transaction in block.transactions:
               if transaction['from_address'] == address:
                   balance -= transaction['amount']
               if transaction['to_address'] == address:
                   balance += transaction['amount']

       return balance

   def create_transaction(self, transaction):
       if self.get_balance_of(transaction.from_address) < transaction.amount:
           print(transaction.from_address + ' doesn\'t have enough coins to send to ' + transaction.to_address + '.')
       else:
           self.pending_transactions.append(transaction.serialize())
           print("Transaction created, "+str(transaction.amount)+" coints will be send from "+transaction.from_address+" to "+transaction.to_address)

   def mine_pending_transactions(self, mining_reward_address):
       if not len(self.pending_transactions) == 0:
           pending_transactions = self.pending_transactions
           pending_transactions.append(Transaction(None, mining_reward_address, self.mining_reward).serialize())
           block = Block(datetime.now(), pending_transactions, self.get_latest_block().hash)
           block.mine_block(self.difficulty)

           self.chain.append(block)

           print("Block Mined, "+"Hash: "+block.hash+"; "+mining_reward_address+" is rewarded with "+str(self.mining_reward)+" coins for mining the Block.")

           self.pending_transactions = []

The blockchain class stores the following data:

chain: it contain the list of all the blocks in the blockchain.

pending_transactions: It contain the list of all the transactions that is not mined.

difficulty: It is the mining difficulty

mining_reward: It is the amount of coins that the miner will get for mining one block

The blockchain class contains the following functions

create_genesis_block: It creates the genesis block that needs to be created manually to initialize the blockchain.

get_latest_block: It returns the latest block that is in the block chain

is_chain_valid: It validates that all the blocks have correct hash and previous_hash

get_balance_of: It calculates balance of any particular address

create_transaction: It creates a transaction and put it in the pending_transaction list to be mined.

mine_pending_transaction: This method is run by the miner to mine all the pending transaction, and after mining it rewards the miner.

Let's test our blockchain

Add the following code to test our blockchain

chain = Blockchain(5, 100)
chain.create_transaction(Transaction('kartik', 'satoshi', 10))
chain.create_transaction(Transaction('kartik', 'ned', 10))
chain.mine_pending_transactions('miner')
print("Balance")
print("kartik: " + str(chain.get_balance_of('kartik')) + " coins")
print("satoshi: " + str(chain.get_balance_of('satoshi')) + " coins")
print("ned: " + str(chain.get_balance_of('ned')) + " coins")
print("miner: " + str(chain.get_balance_of('miner')) + " coins")

This code will create a blockchain with difficulty 5 and miner reward 100 and create two transactions and then mine those transaction and after that print the balance of all the addresses.

It should give an output something like this

Transaction created, 10 coints will be send from kartik to satoshi
Transaction created, 10 coints will be send from kartik to ned
Block Mined, Hash: 000002377f42855b2fcf511bb1fd308a8b6633f41c94b0e7f23baa740bad9a78; miner is rewarded with 100 coins for mining the Block.
Balance
kartik: 980 coins
satoshi: 10 coins
ned: 10 coins
miner: 100 coins

Store our Blockchain

We need a way to store and retrieve our blockchain so that all the data is preserved

To store the blockchain we need pickle, so to install it type pip install pickle in terminal and import pickle in the python file by using import pickle

To store your blockchain use the following code

with open('chain.pkl', 'wb') as f:
   pickle.dump(chain, f)

and to retrieve blockchain back use the following code

with open('chain.pkl', 'rb')  as f:
   chain = pickle.load(f)

Hope this was fun, and you enjoyed making your own blockchian

Thank You! Steemit Community

Sort:  

Just what i needed because i will soon take a programming course online to learn blockchain programming

Great, Wish you all the very best for learning blockchain programming.

Thanks so much:) I am really new to this, but i will take a chance

Congratulations @kartik2085! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes received

Click on any badge to view your own Board of Honor on SteemitBoard.

To support your work, I also upvoted your post!
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

Upvote this notification to help all Steemit users. Learn why here!

This is very good bro. I have always read about the power of Python as programming language, I consider that the power is in the programmer and in the multitudes of things that can be done with this language. It is very good for future projects. Greetings.