3 min read

Simple Blockchain Implementation

This guide demonstrates how to build a basic Blockchain from scratch. It covers the fundamental concepts of chaining blocks together using cryptographic hashes and implementing a simple "Proof of Work" system to simulate mining.

Modules Used:

  • hashlib: To create SHA-256 hashes for the blocks.
  • json: To serialize block data before hashing.
  • time: To timestamp each block.

The Code

Save this as blockchain.py.

import hashlib
import json
import time

class Block:
    def __init__(self, index, transactions, timestamp, previous_hash):
        self.index = index
        self.transactions = transactions
        self.timestamp = timestamp
        self.previous_hash = previous_hash
        self.nonce = 0
        self.hash = self.compute_hash()

    def compute_hash(self):
        """
        A function that return the hash of the block contents.
        """
        block_string = json.dumps({
            "index": self.index,
            "transactions": self.transactions,
            "timestamp": self.timestamp,
            "previous_hash": self.previous_hash,
            "nonce": self.nonce
        }, sort_keys=True)

        return hashlib.sha256(block_string.encode()).hexdigest()

class Blockchain:
    def __init__(self):
        self.unconfirmed_transactions = []
        self.chain = []
        self.create_genesis_block()
        self.difficulty = 2 # Number of leading zeros required for hash

    def create_genesis_block(self):
        """
        A function to generate genesis block and appends it to
        the chain. The block has index 0, previous_hash as 0, and
        a valid hash.
        """
        genesis_block = Block(0, [], time.time(), "0")
        genesis_block.hash = genesis_block.compute_hash()
        self.chain.append(genesis_block)

    @property
    def last_block(self):
        return self.chain[-1]

    def proof_of_work(self, block):
        """
        Function that tries different values of nonce to get a hash
        that satisfies our difficulty criteria.
        """
        block.nonce = 0
        computed_hash = block.compute_hash()
        while not computed_hash.startswith('0' * self.difficulty):
            block.nonce += 1
            computed_hash = block.compute_hash()
        return computed_hash

    def add_block(self, block, proof):
        """
        A function that adds the block to the chain after verification.
        """
        previous_hash = self.last_block.hash
        if previous_hash != block.previous_hash:
            return False
        if not self.is_valid_proof(block, proof):
            return False
        block.hash = proof
        self.chain.append(block)
        return True

    def is_valid_proof(self, block, block_hash):
        return (block_hash.startswith('0' * self.difficulty) and
                block_hash == block.compute_hash())

    def add_new_transaction(self, transaction):
        self.unconfirmed_transactions.append(transaction)

    def mine(self):
        if not self.unconfirmed_transactions:
            return False

        last_block = self.last_block
        new_block = Block(index=last_block.index + 1,
                          transactions=self.unconfirmed_transactions,
                          timestamp=time.time(),
                          previous_hash=last_block.hash)

        proof = self.proof_of_work(new_block)
        self.add_block(new_block, proof)
        self.unconfirmed_transactions = []
        return new_block.index

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

    # 1. Add transactions
    print("Adding transactions...")
    blockchain.add_new_transaction({"sender": "Alice", "receiver": "Bob", "amount": 10})
    blockchain.add_new_transaction({"sender": "Bob", "receiver": "Charlie", "amount": 5})

    # 2. Mine the block
    print("Mining block 1...")
    blockchain.mine()

    # 3. Add more transactions
    blockchain.add_new_transaction({"sender": "Charlie", "receiver": "Alice", "amount": 2})

    # 4. Mine again
    print("Mining block 2...")
    blockchain.mine()

    # 5. Display the chain
    print("\n--- Blockchain Content ---")
    for block in blockchain.chain:
        print(f"Index: {block.index}")
        print(f"Timestamp: {block.timestamp}")
        print(f"Transactions: {block.transactions}")
        print(f"Hash: {block.hash}")
        print(f"Prev Hash: {block.previous_hash}")
        print(f"Nonce: {block.nonce}")
        print("-" * 30)

Usage

python blockchain.py

programming/python/python