工作量证明不是"浪费算力"——它是一个去中心化的时钟,谁算出了 hash,谁就获得了在这个时间点写入区块的"发言权"。
16.3.1 挖矿核心
flowchart TD
A[矿工收集待打包交易] --> B[构造区块头<br/>index + timestamp + prevHash + nonce]
B --> C[计算 hash = SHA-256(header)]
C --> D{hash 前导零 >= difficulty?}
D -->|否| E[nonce += 1]
E --> C
D -->|是| F[广播新区块到网络]
F --> G[其他节点验证后追加到本地链]
style D fill:#fff3e0
style G fill:#c8e6c9
python
# 已在 16.1 中实现核心逻辑
# 本节增加动态难度
def mine(self) -> None:
"""调整 nonce 直到 hash 前导零数 >= difficulty"""
target = '0' * self.difficulty # 如 '0000'
while not self.hash.startswith(target):
self.nonce += 1
self.hash = self.compute_hash()
# 16.1 中的测试(difficulty=4):
# 出块时间:秒级(CPU 单核)
# 难度每增加 1,预计工作量 × 16
# 因为 SHA-256 输出均匀分布,每增加一个零,概率 × 1/1616.3.2 难度调整算法
比特币每 2016 个区块(约 2 周)调整一次目标。我们简化为每 5 个区块。
python
class Blockchain:
def __init__(self, difficulty=4, target_block_time=10):
self.difficulty = difficulty
self.target_block_time = target_block_time # 目标出块秒数
self.adjustment_interval = 5
def adjust_difficulty(self) -> None:
"""每 5 个区块调整一次"""
if len(self.chain) % self.adjustment_interval != 0:
return
# 计算前 5 个块的平均出块时间
recent_blocks = self.chain[-self.adjustment_interval:]
avg_time = (recent_blocks[-1].timestamp - recent_blocks[0].timestamp) / len(recent_blocks)
print(f"\n📊 前 5 块平均出块: {avg_time:.1f}s, 目标: {self.target_block_time}s")
adjustment = self.target_block_time / avg_time
if avg_time < self.target_block_time * 0.75:
self.difficulty += 1 # 太快,增难
print(f"⬆️ 难度 +1 → {self.difficulty}")
elif avg_time > self.target_block_time * 1.5 and self.difficulty > 1:
self.difficulty -= 1 # 太慢,减难
print(f"⬇️ 难度 -1 → {self.difficulty}")
else:
print(f"⏸️ 难度不变: {self.difficulty}")难度调整的经济学
| 场景 | 原因 | 调整方向 |
|---|---|---|
| 更多算力加入 | 竞争加剧 | 增加难度 |
| 算力退出 | 竞争减弱 | 降低难度 |
| ASIC 出现 | 效率飞跃 | 大幅提升难度 |
D_{new} = D_{old} \times \frac{\text{actual_time}}{\text{target_time}}
16.3.3 难度与出块时间关系
| 难度 | 前导零 | 预计尝试次数 | 单核 CPU 出块时间 |
|---|---|---|---|
| 3 | 000 | < 1 秒 | |
| 4 | 0000 | ~1 秒 | |
| 5 | 00000 | ~20 秒 | |
| 6 | 000000 | ~5 分钟 | |
| 比特币当前 | ~72 | ~10 分钟(全网 ASIC) |
比特币的 72 位前导零需要全球算力联合尝试约 10 分钟找到。我们的测试网络保持难度 4-5,确保秒级出块。
16.3.4 完整验证
python
# 16.1 中的链验证已包含 PoW 检查
# 难度是否正确?检查每个区块的 difficulty 与根据历史计算出的期望值
def verify_difficulty(chain: List[Block]) -> bool:
"""验证难度调整是否正确(简化)"""
# 每 5 个块,检查其难度与前 5 块的平均时间匹配
for i in range(5, len(chain), 5):
# 简化验证逻辑
pass
return True, 前往 → 16.4 交易、余额与签名 |*
评论
0评论加载中…