Title: Build a Simple Blockchain Pet Project with Python
zilehuda
Posted on May 2, 2023
Blockchain technology has been around for more than a decade, and its popularity has skyrocketed in recent years. A blockchain is essentially a digital ledger that records transactions in a secure and transparent manner. Each block in the chain contains a unique cryptographic hash of the previous block, creating an immutable and tamper-proof record of all transactions.
In this tutorial, we will build a simple blockchain pet project using Python. We will create a Blockchain
class that can add new transactions, create blocks, and validate the chain's integrity. The project will allow us to create a simple ledger for pet transactions, including the pet's name, breed, and owner.
Prerequisites
To follow along with this tutorial, you should have a basic understanding of Python programming and the command line interface. You will also need to have Python installed on your machine.
Setting up the Project
First, let's create a new directory for our project and navigate to it in the command line:
$ mkdir blockchain-pet-project
$ cd blockchain-pet-project
Next, let's create a new Python file called blockchain.py
in our project directory:
$ touch blockchain.py
We will use this file to define our Blockchain
class.
Defining the Blockchain Class
Open up blockchain.py
in your favorite text editor and define the Block
and Blockchain
classes:
import datetime
import hashlib
import json
class Block:
def __init__(self, index, timestamp, transactions, previous_hash):
self.index = index
self.timestamp = timestamp
self.transactions = transactions
self.previous_hash = previous_hash
self.hash = self.calculate_hash()
def calculate_hash(self):
data = str(self.index) + str(self.timestamp) + json.dumps(self.transactions) + str(self.previous_hash)
sha = hashlib.sha256()
sha.update(data.encode('utf-8'))
return sha.hexdigest()
class Blockchain:
def __init__(self):
self.chain = [self.create_genesis_block()]
def create_genesis_block(self):
return Block(0, '01/01/2022', [{'name': 'Genesis Block'}], '0')
def get_latest_block(self):
return self.chain[-1]
def add_transaction(self, transaction):
self.current_transactions.append(transaction)
def create_new_block(self):
index = len(self.chain)
timestamp = str(datetime.datetime.now())
previous_hash = self.get_latest_block().hash
new_block = Block(index, timestamp, self.current_transactions, previous_hash)
self.chain.append(new_block)
self.current_transactions = []
def is_chain_valid(self):
for i in range(1, len(self.chain)):
current_block = self.chain[i]
previous_block = self.chain[i-1]
if current_block.hash != current_block.calculate_hash():
return False
if current_block.previous_hash != previous_block.hash:
return False
return True
The Block
class represents a single block in the chain. It contains an index, timestamp, list of transactions, previous block hash, and its own hash.
The Blockchain
class represents the entire chain. It contains a list of blocks, starting with the genesis block. It also contains methods for adding new transactions, creating new blocks, and validating the chain's integrity.
Adding Transactions
Let's now add a few transactions to our blockchain. We will create a new instance of the Blockchain
class and add three pet transactions:
Adding Transactions (Continued)
blockchain = Blockchain()
transaction1 = {'name': 'Fluffy', 'breed': 'Golden Retriever', 'owner': 'Alice'}
blockchain.add_transaction(transaction1)
transaction2 = {'name': 'Buddy', 'breed': 'Labrador', 'owner': 'Bob'}
blockchain.add_transaction(transaction2)
transaction3 = {'name': 'Max', 'breed': 'German Shepherd', 'owner': 'Charlie'}
blockchain.add_transaction(transaction3)
Each transaction is represented as a Python dictionary with the pet's name, breed, and owner. We add each transaction to the blockchain using the add_transaction
method.
Creating Blocks
Once we have added a few transactions, we can create a new block using the create_new_block
method:
blockchain.create_new_block()
This method will create a new block with the current timestamp, the list of transactions we added, and the hash of the previous block in the chain.
Validating the Chain
We can check the validity of the chain at any time using the is_chain_valid
method:
print(blockchain.is_chain_valid())
This method iterates over each block in the chain and verifies that its hash matches the result of the calculate_hash
method. It also verifies that each block's previous_hash
matches the hash of the previous block in the chain.
Putting it All Together
Let's now put all the pieces of our blockchain pet project together and see how it works.
First, we create a Blockchain
object:
class Blockchain:
def __init__(self):
self.chain = [self.create_genesis_block()]
self.current_transactions = []
self.block_size = 2
def create_genesis_block(self):
return Block(0, datetime.now(), [], "0")
def add_transaction(self, transaction):
if len(self.current_transactions) < self.block_size:
self.current_transactions.append(transaction)
else:
self.create_new_block()
self.current_transactions.append(transaction)
def create_new_block(self):
previous_hash = self.chain[-1].hash
block = Block(len(self.chain), datetime.now(), self.current_transactions, previous_hash)
self.current_transactions = []
self.chain.append(block)
def is_chain_valid(self):
for i in range(1, len(self.chain)):
current_block = self.chain[i]
previous_block = self.chain[i - 1]
if current_block.hash != current_block.calculate_hash():
return False
if current_block.previous_hash != previous_block.hash:
return False
return True
blockchain = Blockchain()
transaction1 = {'name': 'Fluffy', 'breed': 'Golden Retriever', 'owner': 'Alice'}
blockchain.add_transaction(transaction1)
transaction2 = {'name': 'Buddy', 'breed': 'Labrador', 'owner': 'Bob'}
blockchain.add_transaction(transaction2)
transaction3 = {'name': 'Max', 'breed': 'German Shepherd', 'owner': 'Charlie'}
blockchain.add_transaction(transaction3)
blockchain.create_new_block()
print("Chain is valid: ", blockchain.is_chain_valid())
Each transaction is represented as a Python dictionary with the pet's name, breed, and owner. We add each transaction to the blockchain using the add_transaction
method.
Our Blockchain
class has a block_size
attribute, which determines the maximum number of transactions that can be added to a block. In this example, we set block_size
to 2, which means that a new block will be created automatically when the third transaction is added.
When we add the first two transactions, they are added to the current_transactions
list. When we try to add the third transaction, we check if the length of the current_transactions
list is less than the block_size
. If it is, we simply append the transaction to the list. If it's not, we create a new block using the create_new_block
method and add the transaction to the new block.
Finally, we create a new block by calling the create_new_block
method. This method will create a new block with the current timestamp, the list of transactions we added, and the hash of the previous block in the chain.
We can check the validity of the chain at any time using the is_chain_valid
method. This method iterates over each block in the chain and verifies that its hash matches the result of the calculate_hash
method. It also verifies that each block's previous_hash
matches the hash of the previous block in the chain.
Further Improvements
Our pet project blockchain is still very simple and lacks some key features that real-world blockchains possess. Here are a few ideas for further improvements:
Proof of Work (PoW): In a real blockchain, new blocks are only added to the chain if a certain amount of work has been done to create them. This is known as the Proof of Work (PoW) consensus algorithm. Implementing a PoW algorithm would make our blockchain more secure and resistant to attacks.
Decentralization: Currently, our blockchain runs on a single node. To make it more robust and decentralized, we could allow other nodes to join the network and validate transactions. This would require implementing a network protocol to communicate between nodes and reach consensus on the state of the blockchain.
Persistence: In our current implementation, the blockchain is stored in memory and will be lost if the program is stopped or crashes. To make it more persistent, we could save the blockchain to disk or a database.
Security: Our current implementation doesn't include any encryption or authentication mechanisms. Adding these features would make our blockchain more secure and resistant to attacks.
Conclusion
In this pet project, we created a simple blockchain to store pet ownership information. We started by defining what a blockchain is and how it works. Then, we implemented a basic Block
class to represent each block in the chain. Next, we created a Blockchain
class that handles adding transactions to the blockchain and creating new blocks. Finally, we put all the pieces together and tested our blockchain by adding some transactions and verifying the validity of the chain.
While our blockchain is still very simple and lacks many features of real-world blockchains, it provides a good starting point for further exploration and experimentation. With some additional work, we could create a more robust and secure blockchain that could be used for a variety of purposes beyond just tracking pet ownership.
Posted on May 2, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.