从零到一:构建你自己的简易区块链

5 阅读1分钟

区块链技术自比特币诞生以来,已经走过了十多年的发展历程。这项技术不仅支撑着加密货币的运转,更在金融、供应链、数字身份等领域展现出巨大潜力。然而,对于大多数开发者来说,区块链仍然是一个神秘的黑盒子。今天,我们将通过实际代码,一步步构建一个简易但功能完整的区块链系统,揭开这项技术的神秘面纱。

区块链的核心概念

在开始编码之前,让我们先理解几个核心概念:

  1. 区块:区块链的基本单位,包含交易数据、时间戳和前一个区块的哈希值
  2. 哈希函数:将任意长度的数据转换为固定长度字符串的数学函数
  3. 工作量证明:确保区块链安全性的共识机制
  4. 去中心化:没有中央控制节点的网络结构

环境准备

我们将使用Python来构建这个简易区块链。Python简洁的语法和丰富的库使得它成为学习区块链原理的理想选择。

import hashlib
import json
import time
from typing import List, Dict, Any
from dataclasses import dataclass, asdict
from datetime import datetime

第一步:定义区块结构

区块是区块链的基本构建块。每个区块包含以下关键信息:

@dataclass
class Block:
    """区块类"""
    index: int  # 区块在链中的位置
    timestamp: str  # 区块创建时间
    transactions: List[Dict[str, Any]]  # 交易列表
    previous_hash: str  # 前一个区块的哈希值
    nonce: int = 0  # 用于工作量证明的随机数
    hash: str = None  # 当前区块的哈希值
    
    def calculate_hash(self) -> str:
        """计算区块的哈希值"""
        block_string = json.dumps({
            'index': self.index,
            'timestamp': self.timestamp,
            'transactions': self.transactions,
            'previous_hash': self.previous_hash,
            'nonce': self.nonce
        }, sort_keys=True).encode()
        
        return hashlib.sha256(block_string).hexdigest()
    
    def mine_block(self, difficulty: int) -> None:
        """挖矿:通过工作量证明找到合适的nonce值"""
        target = '0' * difficulty
        
        while self.hash is None or self.hash[:difficulty] != target:
            self.nonce += 1
            self.hash = self.calculate_hash()
        
        print(f"区块 {self.index} 挖矿成功!哈希值: {self.hash}")

第二步:创建区块链类

区块链本质上是一个按时间顺序链接的区块列表:

class Blockchain:
    """区块链类"""
    
    def __init__(self, difficulty: int = 4):
        self.chain: List[Block] = []
        self.pending_transactions: List[Dict[str, Any]] = []
        self.difficulty = difficulty  # 挖矿难度
        self.mining_reward = 10  # 挖矿奖励
        
        # 创建创世区块
        self.create_genesis_block()
    
    def create_genesis_block(self) -> None:
        """创建创世区块(第一个区块)"""
        genesis_block = Block(
            index=0,
            timestamp=str(datetime.now()),
            transactions=[],
            previous_hash="0" * 64  # 创世区块没有前一个区块
        )
        genesis_block.hash = genesis_block.calculate_hash()
        self.chain.append(genesis_block)
    
    def get_latest_block(self) -> Block:
        """获取最新的区块"""
        return self.chain[-1]
    
    def create_transaction(self, sender: str, recipient: str, amount: float) -> int:
        """创建新的交易"""
        transaction = {
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
            'timestamp': str(datetime.now())
        }
        
        self.pending_transactions.append(transaction)
        return self.get_latest_block().index + 1
    
    def mine_pending_transactions(self, miner_address: str) -> None:
        """挖矿:将待处理交易打包成新区块"""
        if not self.pending_transactions:
            print("没有待处理的交易")
            return
        
        # 添加挖矿奖励交易
        reward_transaction = {
            'sender': "系统",
            'recipient': miner_address,
            'amount': self.mining_reward,
            'timestamp': str(datetime.now())
        }
        
        block = Block(
            index=len(self.chain),
            timestamp=str(datetime.now()),
            transactions=self.pending_transactions.copy() + [reward_transaction],
            previous_hash=self.get_latest_block().hash
        )
        
        # 执行工作量证明
        block.mine_block(self.difficulty)
        
        # 将新区块添加到链上
        self.chain.append(block)
        
        # 清空待处理交易
        self.pending_transactions = []
    
    def get_balance(self, address: str) -> float:
        """获取地址的余额"""
        balance = 0.0
        
        for block in self.chain:
            for transaction in block.transactions:
                if transaction['sender'] == address:
                    balance -= transaction['amount']
                if transaction['recipient'] == address:
                    balance += transaction['amount']
        
        return balance
    
    def is_chain_valid(self) -> bool:
        """验证区块链的完整性"""
        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():
                print(f"区块 {current_block.index} 的哈希值无效")
                return False
            
            # 验证区块是否链接正确
            if current_block.previous_hash != previous_block.hash:
                print(f"区块 {current_block.index} 的前一个哈希值无效")
                return False
            
            # 验证工作量证明
            if current_block.hash[:self.difficulty] != '0' * self.difficulty:
                print(f"区块 {current_block.index} 的工作量证明无效")
                return False
        
        return True
    
    def display_chain(self) -> None:
        """显示整个区块链"""
        print("\n" + "="*50)
        print("区块链信息")
        print("="*50)
        
        for block in self.chain:
            print(f"\n区块 #{block.index}")
            print(f"时间戳: {block.timestamp}")
            print(f"前一个哈希: {block.previous_hash[:16]}...")
            print(f"当前哈希: {block.hash[:16]}...")
            print(f"Nonce: {block.nonce}")
            print(f"交易数量: {len(block.transactions)}")
            
            if block.transactions:
                print("交易详情:")
                for tx in block.transactions:
                    print(f"  {tx['sender']} -> {tx['recipient']}: {tx['amount']}")

第三步:测试我们的区块链

现在让我们创建一个简单的测试来验证我们的区块链是否正常工作:

def test_blockchain():
    """测试区块链功能"""
    
    # 创建区块链
    print("创建新的区块链...")
    my_blockchain = Blockchain(difficulty=3)
    
    # 创建一些交易
    print("\n创建交易...")
    my_blockchain.create_transaction("Alice", "Bob", 50)
    my_blockchain.create_transaction("Bob", "Charlie", 25)
    
    # 挖矿
    print("\n开始挖矿...")
    my_blockchain.mine_pending_transactions("Miner1")
    
    # 创建更多交易
    print("\n创建更多交易...")
    my_blockchain.create_transaction("Charlie", "Alice", 10)
    my_blockchain.create_transaction("Alice", "David", 5)
    
    # 再次挖矿
    print("\n开始第二次挖矿...")
    my_blockchain.mine_pending_transactions("Miner2")
    
    # 显示区块链
    my_blockchain.display_chain()
    
    # 验证区块链
    print(f"\n区块链是否有效: {my_blockchain.is_chain_valid()}")
    
    # 查询余额
    print("\n账户余额:")
    print(f"Alice: {my_blockchain.get_balance('Alice')}")
    print(f"Bob: {my_blockchain.get_balance('Bob')}")
    print(f"Charlie: {my_blockchain.get_balance('Charlie')}")
    print(f"David: {my_blockchain.get_balance('David')}")
    print(f"Miner1: {my_blockchain.get_balance('Miner1')}")
    print(f"Miner2: {my_blockchain.get_balance('Miner2')}")
    
    # 测试篡改检测
    print("\n测试篡改检测...")
    if len(my_blockchain.chain) > 1:
        # 尝试篡改交易
        my_blockchain.chain[1].transactions[0]['amount'] = 100
        
        print(f"篡改后区块链是否有效: {my_blockchain