Blockchain Demo in Python
About the project: This Python Blockchain project demonstrates how blocks link securely using SHA-256 hashing and Proof-of-Work mining. Here we are going to create a Blockchain Demo. Building a Blockchain demo in Python is a great way to understand the core concepts of cryptography, immutability, and proof-of-work (mining).
We shall provide a single, self-contained Python script named blockchain_demo.py. This script defines the Block and Blockchain classes and runs a demonstration of adding new blocks (mining) and validating the integrity of the chain.
🧠 How It Works
🧩 What is a Block
A block is a digital record that stores data such as transactions, timestamps, and a unique hash value. Each block also contains the hash of the previous block, creating a secure link between them.
🔗 What is a Blockchain
A blockchain is a chain of these linked blocks, forming a tamper-evident ledger. Because every block depends on the hash of the one before it, changing even a single value in one block breaks the entire chain’s integrity.
⚙️ How Proof-of-Work Prevents Tampering
Proof-of-Work (PoW) is a cryptographic process that requires computational effort (mining) to add a new block. Each block’s hash must start with a specific number of zeros — making it hard to generate. If someone tries to alter a block’s data, they must re-mine that block and every block after it, which demands enormous computing power. This is what makes blockchain data immutable and secure.
You don't need any special libraries outside of the standard Python installation (hashlib and json are built-in).
Below is the complete single python file blockchain_demo.py
import hashlib
import json
import time
from datetime import datetime
# --- Configuration ---
# Set the difficulty level for the Proof-of-Work algorithm.
# Higher number means more leading zeros required, making mining slower.
DIFFICULTY = 4
# --- 1. Block Class Definition ---
class Block:
"""
Represents a single block in the blockchain.
A block contains data, its timestamp, a cryptographic hash,
the hash of the previous block, and the Proof-of-Work nonce.
"""
def __init__(self, index, timestamp, data, previous_hash=''):
self.index = index
self.timestamp = timestamp
self.data = data
self.previous_hash = previous_hash
self.nonce = 0 # Nonce is the value adjusted during mining
self.hash = self.calculate_hash()
def calculate_hash(self):
"""
Creates a SHA-256 hash of the block's contents.
This function is called repeatedly during mining (PoW).
"""
block_string = json.dumps({
'index': self.index,
'timestamp': str(self.timestamp),
'data': self.data,
'previous_hash': self.previous_hash,
'nonce': self.nonce
}, sort_keys=True).encode()
return hashlib.sha256(block_string).hexdigest()
def mine_block(self, difficulty):
"""
Implements the Proof-of-Work (PoW) algorithm.
The block must be hashed until the hash starts with 'difficulty' leading zeros.
"""
print(f"\n⛏️ Start mining block {self.index}...")
target = "0" * difficulty
start_time = time.time()
while self.hash[:difficulty] != target:
self.nonce += 1
self.hash = self.calculate_hash()
end_time = time.time()
mining_duration = end_time - start_time
print(f"✅ Block {self.index} mined in {mining_duration:.4f} seconds!")
print(f"Hash: {self.hash}")
print(f"Nonce: {self.nonce}")
def __repr__(self):
"""Provides a clean string representation for printing."""
return (
f"--- Block #{self.index} ---\n"
f"Timestamp: {self.timestamp}\n"
f"Data: {self.data}\n"
f"Prev Hash: {self.previous_hash[:10]}...\n"
f"Hash: {self.hash[:10]}...\n"
f"Nonce: {self.nonce}\n"
)
# --- 2. Blockchain Class Definition ---
class Blockchain:
"""
Manages the chain of blocks, including creating the genesis block,
adding new blocks, and verifying the chain's integrity.
"""
def __init__(self):
self.chain = [self.create_genesis_block()]
self.difficulty = DIFFICULTY
def create_genesis_block(self):
"""
Creates the first block in the chain (index 0) manually.
It has no previous hash.
"""
return Block(0, datetime.now(), "Genesis Block", "0")
def get_latest_block(self):
"""Returns the most recently added block."""
return self.chain[-1]
def add_block(self, new_block):
"""
Prepares a new block by linking it to the previous one and mining it.
"""
new_block.previous_hash = self.get_latest_block().hash
# Mine the block using the defined difficulty
new_block.mine_block(self.difficulty)
# Add the mined block to the official chain
self.chain.append(new_block)
def is_chain_valid(self):
"""
Validates the chain integrity by checking two conditions for every block:
1. Does the block's current hash match the recalculated hash?
2. Does the block's previous hash match the actual previous block's hash?
"""
print("\n\n--- Starting Chain Validation ---")
# Loop starts from the second block (index 1)
for i in range(1, len(self.chain)):
current_block = self.chain[i]
previous_block = self.chain[i-1]
# Check 1: Does the current block's hash match the calculated hash?
if current_block.hash != current_block.calculate_hash():
print(f"❌ Chain Invalid: Block {i} Hash Mismatch.")
print(f" Stored Hash: {current_block.hash}")
print(f" Recalculated: {current_block.calculate_hash()}")
return False
# Check 2: Does the current block link back correctly?
if current_block.previous_hash != previous_block.hash:
print(f"❌ Chain Invalid: Block {i} Previous Hash Link Broken.")
print(f" Block {i} expected previous hash: {previous_block.hash}")
print(f" Block {i} actual previous hash: {current_block.previous_hash}")
return False
# Check 3 (Optional but good): Check PoW requirement
target = "0" * self.difficulty
if current_block.hash[:self.difficulty] != target:
print(f"❌ Chain Invalid: Block {i} does not meet PoW difficulty.")
return False
print("✅ Chain Valid: All blocks are correctly linked and hashed.")
return True
# --- 3. Demonstration ---
if __name__ == '__main__':
# Initialize the blockchain
titanChain = Blockchain()
print(f"Blockchain initialized with Difficulty: {DIFFICULTY}")
print(f"Genesis Block Created:\n{titanChain.chain[0]}\n")
#
# --- Add Block 1 (Transaction Data) ---
print("------------------------------------------")
block1_data = {
'transactions': [
{'sender': 'Alice', 'recipient': 'Bob', 'amount': 10},
{'sender': 'Charlie', 'recipient': 'Dave', 'amount': 50}
]
}
new_block1 = Block(1, datetime.now(), block1_data)
titanChain.add_block(new_block1)
# --- Add Block 2 (IoT Data) ---
print("------------------------------------------")
block2_data = {
'sensor_data': [
{'device': 'Thermostat', 'reading': '22.5C'},
{'device': 'Humidity', 'reading': '45%'}
]
}
new_block2 = Block(2, datetime.now(), block2_data)
titanChain.add_block(new_block2)
# --- Add Block 3 (User Data) ---
print("------------------------------------------")
block3_data = {
'user_action': 'New User Signed Up'
}
new_block3 = Block(3, datetime.now(), block3_data)
titanChain.add_block(new_block3)
# --- Final Validation ---
titanChain.is_chain_valid()
print("\n\n" + "="*50)
print("--- DEMONSTRATING TAMPERING (IMMUTABILITY) ---")
# Attempt to tamper with Block 2's data
print("Attempting to change Block 2's data...")
original_data = titanChain.chain[2].data
# The hacker changes the data (e.g., changes a transaction amount)
titanChain.chain[2].data = {'sensor_data': 'Hacked Data Injection'}
print(f"Block 2 Data Tampered! (Original: {original_data})")
# Re-validate the chain
print("\n--- Re-running Chain Validation after tampering ---")
titanChain.is_chain_valid()
print("\n**Observation:** The chain is now invalid! The stored hash of Block 2 no longer matches the recalculated hash after the data change.")
print("To make the chain valid again, the attacker would have to re-mine Block 2 AND all subsequent blocks (3, 4, etc.).")
print("="*50)
How to Run the Project
- Save: Save the code above as a single file named blockchain_demo.py.
- Run: Open your terminal and run the command:
python blockchain_demo.py
This above single file, blockchain_demo.py, includes all the necessary logic to demonstrate the core principles of how a blockchain works.
The validation check at the end highlights the immutability that makes blockchains secure.
👉 Download this code and experiment by modifying the difficulty or adding transactions.
← Back to Projects
