Blockchain Simulation Using Python

Table of contents

No heading

No headings in the article.

We know that blockchain is a distributed, immutable ledger, by definition. And we understand that each block in a blockchain stores some kind of information, which most of the times is related to transactions. This article will cover how to create blocks with all the required parameters and link them with hash pointers in Python.

So, the contents of our block will include:

  1. Sender's address
  2. Receiver's address
  3. Amount
  4. Hash
  5. Previous hash
  6. Block number

Firstly, we'll import a hashing library and declare a few variables:

import hashlib

block_no = 0
hash_prev = '0'*64

Next, we'll create a class Block that takes sender's address, receiver's address and amount as the parameters.

class Block:
  def __init__(self,sender_address,receiver_address,amount):

    global block_no
    global hash_prev

    self.sender_address = hashlib.sha256(sender_address.encode()).hexdigest()
    self.receiver_address = hashlib.sha256(receiver_address.encode()).hexdigest()
    self.amount = amount
    self.nonce = 1
    self.hash_prev = hash_prev
    block_no = block_no +1
    self.block_no = block_no

Here, we have simply assigned all the variables' values to the new object of the class under constructor. Next, we will be creating hash using all these vars:

hash_concat = self.sender_address + self.receiver_address + str(self.amount) + str(self.nonce) + self.hash_prev + str(self.block_no)

    self.hash = hashlib.sha256(hash_concat.encode()).hexdigest()

Since we need the first four characters of the hash to be 0s, we will run a while-loop that updates the nonce and the hash until the required hash is obtained:

while(self.hash[0:4] != "0000"):
      self.nonce = self.nonce +1

      hash_concat = self.sender_address + self.receiver_address + str(self.amount) + str(self.nonce) + 
      self.hash_prev + str(self.block_no)
      self.hash = hashlib.sha256(hash_concat.encode()).hexdigest()


    hash_prev = self.hash

After obtaining the required hash, we simply incremented the block number and stored the hash in hash_prev variable. That's all! We can add a series of print statements to view the result. The entire class Block looks like this:

class Block:
  def __init__(self,sender_address,receiver_address,amount):

    global block_no
    global hash_prev

    self.sender_address = hashlib.sha256(sender_address.encode()).hexdigest()
    self.receiver_address = hashlib.sha256(receiver_address.encode()).hexdigest()
    self.amount = amount
    self.nonce = 1


    hash_concat = self.sender_address + self.receiver_address + str(self.amount) + str(self.nonce) +   
    hash_prev

    self.hash = hashlib.sha256(hash_concat.encode()).hexdigest()

    while(self.hash[0:4] != "0000"):
      self.nonce = self.nonce +1

      hash_concat = self.sender_address + self.receiver_address + str(self.amount) + str(self.nonce)
      self.hash = hashlib.sha256(hash_concat.encode()).hexdigest()


    hash_prev = self.hash

    print("Block no. : ",block_no)
    print("Sender Address : ", self.sender_address)
    print("Receiver Address : ",self.receiver_address)
    print("Hash : ",self.hash)
    print("Previous Hash : ",hash_prev)
    print("Nonce : ", self.nonce)
    print()

Input:

Block("1","2",100)

Block("2","3",200)

Output:

Block no. :  1
Sender Address :  6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b
Receiver Address :  d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35
Hash :  0000e262a8bd9a64fde90795f0f73bd600238998ace13c7137f1147636d41378
Previous Hash :  0000000000000000000000000000000000000000000000000000000000000000
Nonce :  61487

Block no. :  2
Sender Address :  d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35
Receiver Address :  4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce
Hash :  00008d72867bb2f5a5adfedda7171f2dcff05f30ad1dea0e267b940e19ff62bc
Previous Hash :  0000e262a8bd9a64fde90795f0f73bd600238998ace13c7137f1147636d41378
Nonce :  65734

Note: In the real-world blockchain ledger, sender's and receiver's addresses will already be hashed. Since this is just a simulation and to keep things simple, I've asked for a string as input for the respective addresses and hashed them later in the code.