One of the best ways to understand how blockchain technology works is to build one yourself. In this first part of a two-part series, we’ll build a simple blockchain from scratch in Python. By the end, you’ll have a solid understanding of the core concepts that make blockchain technology work.
What We’ll Build
Our simple blockchain will include:
- A Block class to represent each block
- A Blockchain class to manage the chain
- Cryptographic hashing using SHA-256
- A proof-of-work mechanism
- Chain validation
Understanding the Basics
A blockchain is, at its core, a linked list of blocks where each block contains data and a cryptographic hash that includes the hash of the previous block. This creates an unbreakable chain — modifying any block invalidates all subsequent blocks.
Setting Up the Environment
You’ll need Python 3.x and the hashlib module (included in Python’s standard library).
The Block Class
import hashlib
import json
from datetime import datetime
class Block:
def __init__(self, index, data, previous_hash):
self.index = index
self.timestamp = datetime.now().isoformat()
self.data = data
self.previous_hash = previous_hash
self.hash = self.calculate_hash()
def calculate_hash(self):
block_string = json.dumps({
'index': self.index,
'timestamp': self.timestamp,
'data': self.data,
'previous_hash': self.previous_hash
}, sort_keys=True)
return hashlib.sha256(block_string.encode()).hexdigest()
def __repr__(self):
return f"Block(index={self.index}, hash={self.hash[:10]}...)"
Let’s break down what each part does:
index: Position of the block in the chaintimestamp: When the block was createddata: The actual content of the block (transactions, etc.)previous_hash: Hash of the previous block — this is what creates the “chain”hash: The block’s own hash, calculated from all other fields
The Blockchain Class
class Blockchain:
def __init__(self):
self.chain = [self.create_genesis_block()]
def create_genesis_block(self):
return Block(0, "Genesis Block", "0")
@property
def last_block(self):
return self.chain[-1]
def add_block(self, data):
new_block = Block(
index=len(self.chain),
data=data,
previous_hash=self.last_block.hash
)
self.chain.append(new_block)
return new_block
def is_valid(self):
for i in range(1, len(self.chain)):
current = self.chain[i]
previous = self.chain[i-1]
# Check if hash is correct
if current.hash != current.calculate_hash():
return False
# Check if chain is properly linked
if current.previous_hash != previous.hash:
return False
return True
Testing Our Blockchain
# Create a blockchain
blockchain = Blockchain()
# Add some blocks
blockchain.add_block({"from": "Alice", "to": "Bob", "amount": 50})
blockchain.add_block({"from": "Bob", "to": "Charlie", "amount": 25})
blockchain.add_block({"from": "Charlie", "to": "Alice", "amount": 10})
# Print the chain
for block in blockchain.chain:
print(f"Block {block.index}: {block.hash[:20]}...")
# Validate
print(f"Is valid: {blockchain.is_valid()}")
# Try to tamper with the chain
blockchain.chain[1].data = {"from": "Alice", "to": "Bob", "amount": 9999}
print(f"After tampering - Is valid: {blockchain.is_valid()}")
What This Demonstrates
When you run this code, you’ll see that:
- Each block has a unique hash based on its contents
- Changing any block’s data changes its hash
- This breaks the chain because the next block’s
previous_hashno longer matches - The
is_valid()method detects this tampering
This is the fundamental security property of blockchain: you can’t change historical data without detection.
Next Steps
In Part 2, we’ll add a proof-of-work mechanism (mining), making our blockchain resistant to easy modification. We’ll also look at how multiple nodes can maintain consensus on the same chain.
Stay tuned, and feel free to experiment with the code above!