区块链技术自比特币诞生以来,已经走过了十多年的发展历程。这项技术不仅支撑着加密货币的运转,更在金融、供应链、数字身份等领域展现出巨大潜力。然而,对于大多数开发者来说,区块链仍然是一个神秘的黑盒子。今天,我们将通过实际代码,一步步构建一个简易但功能完整的区块链系统,揭开这项技术的神秘面纱。
区块链的核心概念
在开始编码之前,让我们先理解几个核心概念:
- 区块:区块链的基本单位,包含交易数据、时间戳和前一个区块的哈希值
- 哈希函数:将任意长度的数据转换为固定长度字符串的数学函数
- 工作量证明:确保区块链安全性的共识机制
- 去中心化:没有中央控制节点的网络结构
环境准备
我们将使用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