DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 966,155 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for How to build a simple Blockchain with Python
Pedro Aravena for Vaultree

Posted on • Updated on

How to build a simple Blockchain with Python

We have seen a lot about Bitcoin and cryptocurrencies and we can say that they are in vogue. And just like every developer, we must always be aware and learn about the new technologies out there. Ok, probably blockchain is not something new for most of us, however, do you know how it actually works? No? So, let's dive in.

Blockchain is the base concept of every cryptocurrency, but it is not limited to that scope and can be applied in several other ways. To better understand this concept, I am going to create a simple blockchain.

In order to create a Blockchain, we need to understand a few things. What do we actually need?

Blocks

A blockchain is made of blocks. In our case, a block will be composed of: a date, an index and some content (a message, for example) and the hash of the previous block.

Image description

Cryptography

To keep the information stored securely on the blockchain, we will need to encrypt the data. For our small project, we are going to use the sha256 method from the hashlib standard library (there are other hashing functions you can use). This function will create a string with 64 characters.

Ultimately, our blockchain will be a list of hashes, each 64 characters long. And as mentioned before, the hash of the previous block is contained in the next block which is why we call it block + chain.

Difficulty and Nonce

A blockchain is not built just by creating hashes of blocks. A hash must be valid. In our case, a hash is valid if it starts with four β€œ0”s (e.g. β€œ0000abc…”). We call this validation difficulty. The higher this difficulty, the longer it will take to find a valid hash.

BUT… If the hash is not valid the first time, something needs to change to get a different hash, right? If you've worked with hashes, you know that if we use the same data, it will always result in the same hash. To get around this, we use a nonce, which, in other words, is an arbitrary value. It is a simple integer that we will increment whenever a hash is not valid.

In short, we are going to hash our block (date, index, message and previous hash) and an arbitrary value of 1. If the hash is not valid, we will try with an arbitrary value of 2. And we will increment the arbitrary value of 1 by 1 until it finds a valid hash.

Genesis block

From the name you may have guessed that it is the first block of our blockchain. The problem is that this block has no previous hash, because there is no previous block. We will just use an arbitrary value to create a hash to represent the previous block and thus create the first block of our blockchain.

What methods will we need?

Image description

Now that we know what we need, let's see the functions that we are going to create to make a blockchain:

  • 1- Building the blockchain
    Of course we will have a function to build and start our blockchain. The main responsibility will be to create the genesis block.

  • 2- Encrypt our blocks
    A function responsible for generating a valid hash for our blocks.

  • 3- Check the validity of a hash
    We will also have a function that will validate if the hash starts with β€œ0000”, that is, if it is valid for our blockchain.

  • 4- Retrieve previous hash
    We will need a function that retrieves the last hash of our blockchain to include when creating a new block.

  • 5- Add a new block
    And finally, we need to provide a way to add a new block.

LET'S CODE!!!

Image description

Our little project has just two files: blockchain.py and main.py. The first contains our Blockchain class with all the necessary functions. And the second is an example of use.

Blockchain.py

from hashlib import sha256
from datetime import datetime


class Blockchain:

    def __init__(self):
        self.blocks = []
        self.set_genesis_block()

    def set_genesis_block(self):
        data = 'Hello, World!' 
        timestamp = datetime.utcnow().timestamp()
        prev_hash = 0
        index = 0
        self.hash_block(
            data, timestamp, prev_hash, index
        )

    def hash_block(self, data, timestamp, prev_hash, index):
        hash = ''
        nonce = 1
        while not self.is_hash_valid(hash):
            block = '{}:{}:{}:{}:{}'.format(
                data, timestamp, prev_hash, index, nonce
            )
            hash = sha256(block.encode()).hexdigest()
            nonce += 1
        print('[nonce]', nonce)
        self.blocks.append(hash)

    def get_last_hash(self):
        return self.blocks[-1]

    def is_hash_valid(self, hash):
        return hash.startswith('0000')

    def add_new_block(self, data):
        index = len(self.blocks)
        prev_hash = self.get_last_hash()
        timestamp = datetime.utcnow().timestamp()
        self.hash_block(
            data, timestamp, prev_hash, index
        )

    def get_all(self):
        return self.blocks[:]

Enter fullscreen mode Exit fullscreen mode

In this module, we have a class with some methods that we are going to analyse. First of all, I import the functions that we will need:

sha256 to encrypt our blocks
datetime to have the creation date (timestamp) of the blocks

Now let's take a look at what's happening in the methods:

set_genesis_block: this method is called in the construction of the blockchain to create the first block of the chain, i.e. the genesis block. We take the timestamp of the current date, a message, the block index on the blockchain (0) and an arbitrary value as the previous hash since we don't have any blocks in the chain (self.blocks) yet. With this data, we add the block to the chain by calling the hash_block method.

hash_block: this method takes the entire contents of the block, creates a valid hash and adds it to the chain. As you can see, the first time we try to encrypt a block, we set the value of the nonce to 0. Then we wrap the entire contents of the block into a string and encrypt it with the sha256 function from the hashlib standard library. If the hash is not valid, we increment the nonce and try again. When we find a valid hash, we add it to the end of the string.

get_last_hash: in this method, returning the last block of the chair.

is_hash_valid: this method receives a hash and determines if it is valid.

add_new_block: this method is responsible for adding a new block. We only need the information (in our case, its messages) as an argument, because the rest of the block's content is calculated through the blockchain itself. Once the block content is ready, we call hash_block to add the block to the chain.

Good, now let's see how we use this Blockchain class in our main.py

Main.py

from blockchain import Blockchain


if __name__ == '__main__':
    blockchain = Blockchain()

    blockchain.add_new_block('First block!')
    blockchain.add_new_block('Blockchain is awesome!')
    blockchain.add_new_block('Once again!')

    print(blockchain.get_all())
Enter fullscreen mode Exit fullscreen mode

What is happening here is that we import our Blockchain class and:

We create a new β€œblockchain” instance
We added 3 blocks with the respective messages: β€œFirst block!”, β€œBlockchain is awesome!” and "once again!".

Finally, we take a look at how our blockchain is doing. The output should look like this:

[nonce] 3455
[nonce] 4003
[nonce] 40238
[nonce] 4161
[β€˜0000d5e8a1a6e6c0e033c0e9c8e1f6a1ff7426083fee5343274c230599670fed’, β€˜000015422c0380102a781d44f116efc605a9487cab8aa40397f32d9012a4ecc8’, β€˜00004d05054645cfe0b3dff068151b8502db93b9b9a49143a4b7aec7bbbdbfbb’, β€˜0000d78b4059d51651fdac4159b5cabc30ecd59e377c841a434510fbde773fa8’]
Enter fullscreen mode Exit fullscreen mode

The array represents our 4 blocks (genesis block and the 3 added ones). As you can see, each of them starts with β€œ0000”, so each of them is valid. If any of them didn't start with four zeros, we would know that it is an invalid hash and therefore the corresponding content of that block is unreliable.

We can also see 4 nonce values. They are the values ​​that were used in each block. If you go back to blockchain.py you will see that we have a print in the hash_block method. These values ​​also represent how many times we hashed the block until we find a valid one.

The message β€œBlockchain is awesome!” (our second block that was added to main.py) took 40238 tries before finding a valid hash!

Conclusion

Image description

This is a very simple example of how a blockchain works. Probably some things were left out, others were simplified. In this little project we learned that:

Each new block connects to all the blocks before it in a cryptographic chain in such a way that it's nearly impossible to tamper with. All transactions within the blocks are validated and agreed upon by a consensus mechanism, ensuring that each transaction is true and correct.

That's all for today. I hope this helps you to better understand the concepts of how to create a blockchain and how it works. Feel free to add anything or correct me in the comments below. :)

Vaultree Community

Right now at Vaultree we are building a community that is all about Privacy-Enhancing Technologies (PETs), an emerging field of future-oriented tech to solve real world problems, for everyone interested in cybersecurity and cryptography, to also ask questions, trade tips, get answers, network and share ideas with like-minded tech enthusiasts - all welcome to join. You can join here.

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.