Building a Basic Blockchain in Python. Part 2.

In Part 1, we built a basic blockchain with blocks, hashing, and chain validation. In this second part, we add Proof of Work mining and a transaction system.

Proof of Work

Proof of Work requires miners to find a hash that meets certain criteria (starts with N zeros). This computational work makes it expensive to rewrite history.

Adding Mining to the Block

import hashlib, json
from datetime import datetime

class Block:
    def __init__(self, index, transactions, previous_hash):
        self.index = index
        self.timestamp = datetime.now().isoformat()
        self.transactions = transactions
        self.previous_hash = previous_hash
        self.nonce = 0
        self.hash = self.calculate_hash()
    
    def calculate_hash(self):
        block_string = json.dumps({
            'index': self.index, 'timestamp': self.timestamp,
            'transactions': self.transactions,
            'previous_hash': self.previous_hash, 'nonce': self.nonce
        }, sort_keys=True)
        return hashlib.sha256(block_string.encode()).hexdigest()
    
    def mine_block(self, difficulty):
        target = "0" * difficulty
        while not self.hash.startswith(target):
            self.nonce += 1
            self.hash = self.calculate_hash()
        print(f"Mined! Nonce: {self.nonce}, Hash: {self.hash}")

Updated Blockchain with Transactions

class Blockchain:
    def __init__(self, difficulty=4):
        self.chain = [Block(0, [], "0")]
        self.difficulty = difficulty
        self.pending_transactions = []
        self.mining_reward = 10
    
    def add_transaction(self, sender, recipient, amount):
        self.pending_transactions.append({
            'sender': sender, 'recipient': recipient, 'amount': amount
        })
    
    def mine_pending_transactions(self, miner_address):
        block = Block(len(self.chain), self.pending_transactions, self.chain[-1].hash)
        block.mine_block(self.difficulty)
        self.chain.append(block)
        self.pending_transactions = [{'sender': 'REWARD', 'recipient': miner_address, 'amount': self.mining_reward}]
    
    def get_balance(self, address):
        balance = 0
        for block in self.chain:
            for tx in block.transactions:
                if tx['recipient'] == address: balance += tx['amount']
                if tx['sender'] == address: balance -= tx['amount']
        return balance

Usage Example

bc = Blockchain(difficulty=4)
bc.add_transaction("Alice", "Bob", 50)
bc.add_transaction("Bob", "Charlie", 25)
print("Mining...")
bc.mine_pending_transactions("Miner1")
print(f"Alice: {bc.get_balance('Alice')}")
print(f"Miner1: {bc.get_balance('Miner1')}")

Key Concepts Learned

  • Mining finds a valid nonce that produces a hash meeting the difficulty target
  • The mining reward creates an incentive for miners to secure the network
  • Balances are calculated by scanning all transactions (UTXO-style)

Real blockchains add peer-to-peer networking, Merkle trees, digital signatures, and dynamic difficulty adjustment on top of these fundamentals.

By admin

Leave a Reply

Your email address will not be published. Required fields are marked *