Step 1: Building a Blockchain

Open up your favourite text editor or IDE, personally I ❤️ PyCharm. Create a new file, called blockchain.py . We’ll only use a single file, but if you get lost, you can always refer to the source code.

Representing a Blockchain

We’ll create a Blockchain class whose constructor creates an initial empty list (to store our blockchain), and another to store transactions. Here’s the blueprint for our class:

Blueprint of our Blockchain Class

Our Blockchain class is responsible for managing the chain. It will store transactions and have some helper methods for adding new blocks to the chain. Let’s start fleshing out some methods.

What does a Block look like?

Each Block has an index, a timestamp (in Unix time), a list of transactions, a proof (more on that later), and the hash of the previous Block.

Here’s an example of what a single Block looks like:

Example of a Block in our Blockchain

At this point, the idea of a chain should be apparent—each new block contains within itself, the hash of the previous Block. This is crucial because it’s what gives blockchains immutability: If an attacker corrupted an earlier Block in the chain then all subsequent blocks will contain incorrect hashes.

Does this make sense? If it doesn’t, take some time to let it sink in—it’s the core idea behind blockchains.

Adding Transactions to a Block

We’ll need a way of adding transactions to a Block. Our new_transaction() method is responsible for this, and it’s pretty straight-forward:

After new_transaction() adds a transaction to the list, it returns the index of the block which the transaction will be added to—the next one to be mined. This will be useful later on, to the user submitting the transaction.

Creating new Blocks

When our Blockchain is instantiated we’ll need to seed it with a genesis block—a block with no predecessors. We’ll also need to add a “proof” to our genesis block which is the result of mining (or proof of work). We’ll talk more about mining later.

In addition to creating the genesis block in our constructor, we’ll also flesh out the methods for new_block() , new_transaction() and hash() :

The above should be straight-forward—I’ve added some comments and docstrings to help keep it clear. We’re almost done with representing our blockchain. But at this point, you must be wondering how new blocks are created, forged or mined.

Understanding Proof of Work

A Proof of Work algorithm (PoW) is how new Blocks are created or mined on the blockchain. The goal of PoW is to discover a number which solves a problem. The number must be difficult to find but easy to verify—computationally speaking—by anyone on the network. This is the core idea behind Proof of Work.

We’ll look at a very simple example to help this sink in.

Let’s decide that the hash of some integer x multiplied by another y must end in 0 . So, hash(x * y) = ac23dc...0 . And for this simplified example, let’s fix x = 5 . Implementing this in Python:

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, the produced hash ends in 0 :

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

In Bitcoin, the Proof of Work algorithm is called Hashcash. And it’s not too different from our basic example above. It’s the algorithm that miners race to solve in order to create a new block. In general, the difficulty is determined by the number of characters searched for in a string. The miners are then rewarded for their solution by receiving a coin—in a transaction.

The network is able to easily verify their solution.

Implementing basic Proof of Work

Let’s implement a similar algorithm for our blockchain. Our rule will be similar to the example above:

Find a number p that when hashed with the previous block’s solution a hash with 4 leading 0 s is produced.

To adjust the difficulty of the algorithm, we could modify the number of leading zeroes. But 4 is sufficient. You’ll find out that the addition of a single leading zero makes a mammoth difference to the time required to find a solution.

Our class is almost complete and we’re ready to begin interacting with it using HTTP requests.