Building a Blockchain from Scratch using Python – Part 1

It’s one thing to understand the concept of a blockchain, but it’s an entirely new level of understanding to be able to implement one. In the following series of tutorials, you will learn how to develop a very simple blockchain using Python 3.

This tutorial is for people who are fairly familiar with blockchains. If you need assistance with some of the technical aspects of a blockchain, I suggest this coursera course.

A good portion of the blockchain outline came from this article by Lauri Hartikka. If you’re JavaScript literate, I suggest checking it out.

The Genesis Block

Before we build the first block, we need to create a class for all of blocks to abide by. It should have the attributes:

  • Index – it’s position in the blockchain
  • Previous Hash – the hash of the block that came before the current block
  • Timestamp – the time the block was created
  • Data – the information (e.g. transactions) that the block carries
  • Hash – the hash of the block itself.

We implement it like this:

class Block:
    def __init__(self, index, previousHash, timestamp, data, currentHash):
        self.index = index
        self.previousHash = previousHash
        self.timestamp = timestamp
        self.data = data
        self.currentHash = currentHash

Now we can create our first block! This is commonly referred to as the genesis block:

def getGenesisBlock():
    return Block(0, '0', '1496518102.896031', "My very first block :)", '0q23nfa0se8fhPH234hnjldapjfasdfansdf23')

blockchain = [getGenesisBlock()]

Your genesis block doesn’t have to be exactly like this. The only requirements are that the genesis has index of 0 and the timestamp is less than the current time. The previous has doesn’t matter, data can be anything you want, and we’ll learn about hashing next!

Hashing Blocks

Now that we have our first block, how do we get a hash for it? Python has a library which includes SHA256 – the hashing algorithm that Bitcoin and others use. To install this package, go to the command line and enter:

pip install hashlib

We will create two functions for ease of use, but only the first is actually necessary – calculateHash and calculateHashForBlock. The second function depends on the first, but sometimes it’s easier to enter a block and get the hash.

def calculateHash(index, previousHash, timestamp, data):
    value = str(index) + str(previousHash) + str(timestamp) + str(data)
    sha = hashlib.sha256(value.encode('utf-8'))
    return str(sha.hexdigest())

def calculateHashForBlock(block):
    return calculateHash(block.index, block.previousHash, block.timestamp, block.data)

We essentially convert all of the block information into one large string. Then we encode it, and finally hash it with hashlib.sha256(). 

Creating New Blocks

Now that we have our first block and can hash blocks, we need a function to add blocks to the blockchain. This will incorporate a function that can retrieve our latest block.

import time

def getLatestBlock():
    return blockchain[len(blockchain)-1]

def generateNextBlock(blockData):
    previousBlock = getLatestBlock()
    nextIndex = previousBlock.index + 1
    nextTimestamp = time.time()
    nextHash = calculateHash(nextIndex, previousBlock.currentHash, nextTimestamp, blockData)
    return Block(nextIndex, previousBlock.currentHash, nextTimestamp, nextHash)

Validation

So far we can:

  1. Create a genesis block
  2. Hash blocks
  3. Create additional blocks

But how can we be sure these blocks are legitimate? And what about checking the entire chain? Let’s start with a function that checks if two blocks are the same (to make sure no one alters the genesis block):

def isSameBlock(block1, block2):
    if block1.index != block2.index:
        return False
    elif block1.previousHash != block2.previousHash:
        return False
    elif block1.timestamp != block2.timestamp:
        return False
    elif block1.data != block2.data:
        return False
    elif block1.currentHash != block2.currentHash:
        return False
    return True

Now we can write a function that takes the previous block and the new block as inputs. It determines if the block is valid based on hashes and indices matching up:

def isValidNewBlock(newBlock, previousBlock):
    if previousBlock.index + 1 != newBlock.index:
        print('Indices Do Not Match Up')
        return False
    elif previousBlock.currentHash != newBlock.previousHash:
        print("Previous hash does not match")
        return False
    elif calculateHashForBlock(newBlock) != newBlock.hash:
        print("Hash is invalid")
        return False
    return True

Using the two functions above, we can check the validity of an entire chain by iterating over the entire list in a for loop:

def isValidChain(bcToValidate):
    if not isSameBlock(bcToValidate[0], getGenesisBlock()):
        print('Genesis Block Incorrect')
        return False
    
    tempBlocks = [bcToValidate[0]]
    for i in range(1, len(bcToValidate)):
        if isValidNewBlock(bcToValidate[i], tempBlocks[i-1]):
            tempBlocks.append(bcToValidate[i])
        else:
            return False
    return True

Now we can check our chain!

Putting it together

All the code together looks like:

 
import hashlib
import time

class Block:
    def __init__(self, index, previousHash, timestamp, data, currentHash):
        self.index = index
        self.previousHash = previousHash
        self.timestamp = timestamp
        self.data = data
        self.currentHash = currentHash

def getGenesisBlock():
    return Block(0, '0', '1496518102.896031', "My very first block :)", '0q23nfa0se8fhPH234hnjldapjfasdfansdf23')

blockchain = [getGenesisBlock()]

def calculateHash(index, previousHash, timestamp, data):
    value = str(index) + str(previousHash) + str(timestamp) + str(data)
    sha = hashlib.sha256(value.encode('utf-8'))
    return str(sha.hexdigest())

def calculateHashForBlock(block):
    return calculateHash(block.index, block.previousHash, block.timestamp, block.data)

def getLatestBlock():
    return blockchain[len(blockchain)-1]

def generateNextBlock(blockData):
    previousBlock = getLatestBlock()
    nextIndex = previousBlock.index + 1
    nextTimestamp = time.time()
    nextHash = calculateHash(nextIndex, previousBlock.currentHash, nextTimestamp, blockData)
    return Block(nextIndex, previousBlock.currentHash, nextTimestamp, nextHash)

def isSameBlock(block1, block2):
    if block1.index != block2.index:
        return False
    elif block1.previousHash != block2.previousHash:
        return False
    elif block1.timestamp != block2.timestamp:
        return False
    elif block1.data != block2.data:
        return False
    elif block1.currentHash != block2.currentHash:
        return False
    return True

def isValidNewBlock(newBlock, previousBlock):
    if previousBlock.index + 1 != newBlock.index:
        print('Indices Do Not Match Up')
        return False
    elif previousBlock.currentHash != newBlock.previousHash:
        print("Previous hash does not match")
        return False
    elif calculateHashForBlock(newBlock) != newBlock.hash:
        print("Hash is invalid")
        return False
    return True

def isValidChain(bcToValidate):
    if not isSameBlock(bcToValidate[0], getGenesisBlock()):
        print('Genesis Block Incorrect')
        return False
    
    tempBlocks = [bcToValidate[0]]
    for i in range(1, len(bcToValidate)):
        if isValidNewBlock(bcToValidate[i], tempBlocks[i-1]):
            tempBlocks.append(bcToValidate[i])
        else:
            return False
    return True

Now you have to ability to independently manage a blockchain. Stay tuned for the next tutorial on how to incorporate the blockchain into a consensus seeking network.

3 comments:

  1. I love this tutorial. Is part 2 up yet?

    I’m a final year software development student, for my final year project, I’m developing an online e-voting system. I’m exploring the possibility of using block chain technology, to provide transparency and accountability of the votes.

    Any thoughts on this? Would it be possible?

    1. Hi Mark – sorry, I haven’t had the time to put together a part 2 yet!

      Great to hear about your project! Awesome idea. It’s definitely possible to do in ethereum’s solidity. Would love to talk more if you email blockxchain@gmail.com 🙂

  2. This is awesome, I am a newbie software dev currently doing a rigorous research on blockchain implementations in different fields. I am not strongly based in any other prog-lang except python, it would be wonderful if the part two of this tutorial comes out soon enough. I am eagerly waiting to complete this. Anyways, thanks alot!

Leave a Reply

Your email address will not be published. Required fields are marked *