Learn Blockchain by creating one
Tags: blockchain, beginners, python, flask
Published: 2020-07-25 10:26:44

# The best way to learn how Blockchain works is to create one 
You are here because like me you have heard about Bitcoin and cryptocurrency, and want to learn how they work. After spending hours reading articles and watching YouTube videos, I thought of making a simple project so that people could understand Blockchain.
 
# Before getting started...
Remember that a blockchain is an immutable, sequential chain of records called Blocks. They can contain transactions, files, or any data you like, really. But the important thing is that they are chained together using *hashes*.

If you aren't sure what a hash is, [here's an explanation](https://en.wikipedia.org/wiki/Cryptographic_hash_function).

_**Who is this guide is for?**_ You should be comfortable at reading and writing basic Python syntax, as well as have some understanding of how HTTP requests work, as we'll be talking to Blockchain over HTTP.

_**What do I need?**_ We are going to use Flask here, so it would be good if you have knowledge about it. Even if you don't have working knowledge, it is fine as I would be going through the code step by step. Let's install our requirements:
```bash
pip install Flask==1.1.2 requests==2.24.0
```
Oh, you'll also need an HTTP Client, like [Postman](https://www.postman.com/downloads/) or cURL. But anything would do.

_**Where's the final code?**_ The source code is [available here](https://github.com/Phantsure/silver-fiesta).

# Step 1: Building a Blockchain
Open up any text editor, I prefer [VS Code](https://code.visualstudio.com/). Let's create a file names `blockchain.py`. It will contain our Blockchain structure/class.

### Representing a Blockchain
Here is how our `Blockchain` class will look like:
```python
class Blockchain(object):
    def __init__(self):
        self.chain = []
        self.current_transactions = []
        
    def new_block(self):
        # Creates a new Block and adds it to the chain
        pass
    
    def new_transaction(self):
        # Adds a new transaction to the list of transactions
        pass
    
    @staticmethod
    def hash(block):
        # Hashes a Block
        pass

    @property
    def last_block(self):
        # Returns the last Block in the chain
        pass
```
Okay, now let us go function to function.
**init**: 
- _chain_ Contains actual chain/sequence of blocks
- *current_transactions* Contains the list of transactions.

Rest functions have appropriate comments to make you understand their functionality.

Our `Blockchain` class is responsible for managing the chain. It will store transactions and have few helper methods for adding new blocks to the chain.

### What does a Block look like?
Each Block has an _index_, a _timestamp_(in Unix time), a _list of transactions_, a _proof_ (later in article), and the _hash of the previous Block_.

```python
block = {
    "index": 2,
    "timestamp": 1595318883.8897538,
    "transactions": [
        {
            "sender": "0",
            "recipient": "d48099450667467e97a6033ddde69e8a",
            "amount": 70
        }
    ],
    "proof": 35293,
    "previous_hash": "65679099343e4a8f9c8c30438b053db6558546d8cef9378ed8d3dd3c7e317af5"
}
```
_(Example of a Block in our Blockchain)_

Till this point, the idea of a _chain_ should be apparent--each new block contains the hash of the previous block. Thus providing immutability to blockchains. If an attacker corrupts an earlier _Block_ in the _chain_ then **all** the subsequent blocks will contain incorrect hashes, basically will not match with the hashes stored at other nodes. P.S. for blockchain to work, there should be multiple nodes to store data and those nodes should be decentralised, i.e. not on same server/ip.

_Does it make sense? If it doesn't, take some time to let it sink in, read it once more--it's the core idea behind blockchains._

### Adding transaction to a Block
_Transaction_ is record of transfer of data, or in our case fake money. We'll need a way to add transactions to a Block. Our `new_transaction()` method is responsible for this. Let's see how it works:
```python
class Blockchain(object):
    ...
    
    def new_transaction(self, sender, recipient, amount):
        """
        Creates a new transaction to go into the next mined Block
        :param sender: <str> Address of the Sender
        :param recipient: <str> Address of the Recipient
        :param amount: <int> Amount
        :return: <int> The index of the Block that will hold this transaction
        """

        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1
```
This function adds a _dict_ to *current_transactions* with _sender_, _recipient_ and _amount_ of the transaction. 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 out constructor(_init_), we'll also write out few other methods.

```python
import hashlib
import json
from time import time


class Blockchain(object):
    def __init__(self):
        self.current_transactions = []
        self.chain = []

        # Create the genesis block
        self.new_block(previous_hash=1, proof=100)
    def new_block(self, proof, previous_hash=None):
        """
        Create a new Block in the Blockchain
        :param proof: <int> The proof given by the Proof of Work algorithm
        :param previous_hash: (Optional) <str> Hash of previous Block
        :return: <dict> New Block
        """

        block = {
            'index': len(self.chain) + 1,
            'timestamp': time(),
            'transactions': self.current_transactions,
            'proof': proof,
            'previous_hash': previous_hash or self.hash(self.chain[-1]),
        }

        # Reset the current list of transactions
        self.current_transactions = []

        self.chain.append(block)
        return block

    def new_transaction(self, sender, recipient, amount):
        """
        Creates a new transaction to go into the next mined Block
        :param sender: <str> Address of the Sender
        :param recipient: <str> Address of the Recipient
        :param amount: <int> Amount
        :return: <int> The index of the Block that will hold this transaction
        """
        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):
        """
        Creates a SHA-256 hash of a Block
        :param block: <dict> Block
        :return: <str>
        """

        # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
        block_string = json.dumps(block, sort_keys=True).encode()
        return hashlib.sha256(block_string).hexdigest()

    @property
    def last_block(self):
        # Returns the last block in the chain
        return self.chain[-1]
```
Okay, now let us look at the code. 
- `new_block`: Adds a Block to the chain
- `new_transaction`: Stores a transfer of amount from sender to recipient.
- `hash`: Returns a hex formatted hash of the block passed to it in SHA256.
- `last_block`: Returns the last block of chain.
I've also added some comments and _docstrings_ to help make 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 number x multiplied by another number y must end in 0. So, `hash(x * y) = ad534...0`. And for this example, let's fix `x = 9`. Implementing this in Python:

```python
from hashlib import sha256
x = 9
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 = 16`. Since, the produced hash ends in 0.

```python
hash(9 * 16) = 5ec1a0c99d4............2cf5563d97ff0
```
In Bitcoin, the Proof of Work algorithm is called [Hashcash](https://en.wikipedia.org/wiki/Hashcash?ref=hackernoon.com). And it's not too different from our 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: Find a number that when hashed with the previous block's solution a hash with **4 leading zeros(0000)** is produced.

```python
import hashlib
import json

from time import time
from uuid import uuid4


class Blockchain(object):
    ...
        
    def proof_of_work(self, last_proof):
        """
        Simple Proof of Work Algorithm:
         - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
         - p is the previous proof, and p' is the new proof
        :param last_proof: <int>
        :return: <int>
        """

        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        return proof

    @staticmethod
    def valid_proof(last_proof, proof):
        """
        Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes?
        :param last_proof: <int> Previous Proof
        :param proof: <int> Current Proof
        :return: <bool> True if correct, False if not.
        """

        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()
        return guess_hash[:4] == "0000"
```

To make it difficult to find the proof we could increase the number of leading zeros. But 4 is sufficient. You'll find out that the addition of a single leading zero makes a huge difference to time required. To better understand I would suggest to add zeros and check how much time does it take, you could use the simple example we used earlier.

Our class is almost complete. The whole class is in `blockchain.py`. In the next post I would start using HTTP requests to interact with our network. 
I will post the link in the update section to subsequent posts. To get the source code go [here](https://github.com/Phantsure/silver-fiesta).

## Updates
The link to the following blog is [here](https://dev.to/phantsure/learn-blockchain-by-creating-one-part-2-46me).

# Credits
I can't take the credit for this article. This article is just an upgraded version of [dvf's article](https://hackernoon.com/learn-blockchains-by-building-one-117428612f46).
<span>Photo by <a href="https://unsplash.com/@jjying?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">JJ Ying</a> on <a href="https://unsplash.com/s/photos/chain?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>