Module 02 · 练习
练习 01:PoW 挖矿模拟器
用 30 行 Python 理解比特币工作量证明:难度调整与算力的指数关系
🔒
登录后查看练习
登录以查看练习内容,并跟踪你的学习进度。
目标
完成本练习后,你应该能回答:
- “挖矿”的本质操作是什么?
- 难度每提升 1,计算量大约增加多少倍?
- 比特币为什么每 2016 个块调整一次难度?
环境
Python 3.8+,无需额外安装。
代码
将以下代码保存为 01_pow_simulator.py 并运行:
"""
Exercise 01: PoW 挖矿模拟器
================================
目标:用 30 行代码理解比特币的工作量证明
运行:python 01_pow_simulator.py
你会看到:
- 难度越高,找到合法 nonce 需要的计算次数指数级增长
- 这就是"挖矿"的本质——暴力搜索满足条件的 hash
"""
import hashlib
import time
def mine_block(block_data: str, difficulty: int) -> tuple[int, str, float]:
"""
模拟挖矿:找到一个 nonce,使得 sha256(block_data + nonce) 的前 difficulty 位为 0
Args:
block_data: 区块内容(交易数据等)
difficulty: 难度,即 hash 前缀需要多少个 '0'
Returns:
(nonce, hash, elapsed_seconds)
"""
target = "0" * difficulty
nonce = 0
start = time.time()
while True:
text = f"{block_data}{nonce}"
h = hashlib.sha256(text.encode()).hexdigest()
if h.startswith(target):
elapsed = time.time() - start
return nonce, h, elapsed
nonce += 1
# ============================================================
# 体验不同难度
# ============================================================
block = "Alice->Bob:1BTC|Bob->Charlie:0.5BTC|prev_hash:0000abc..."
for diff in range(1, 7):
nonce, h, t = mine_block(block, diff)
print(f"难度 {diff} (前缀 {'0'*diff}xxx...)")
print(f" Nonce: {nonce:>10,}")
print(f" Hash: {h}")
print(f" 耗时: {t:.3f}s")
print()
# 难度 6 以上可能要跑很久,可以 Ctrl+C 中断
if t > 30:
print(" ⚠️ 后续难度耗时太长,跳过。你已经能看到指数增长的趋势。")
break
# ============================================================
# TODO: 扩展练习
# ============================================================
#
# 1. 修改 block 内容(哪怕改一个字符),观察 nonce 是否完全不同
# → 理解:为什么不能"预计算" nonce
#
# 2. 模拟难度调整:如果上一个块 5 秒内挖出来,难度+1;超过 30 秒,难度-1
# → 理解:比特币每 2016 个块调整一次难度,目标是平均 10 分钟出块
#
# 3. 模拟最长链规则:两个矿工同时出块(分叉),后续的块会延伸哪条链?
# → 理解:为什么 6 个确认后交易被认为不可逆
运行方式
python 01_pow_simulator.py
思考问题
- 运行结果中,难度从 1 增到 2 时,nonce 大约增加了多少倍?这和理论上的 16 倍(每多一个前导零,搜索空间 ×16)吻合吗?
- 如果比特币全网算力翻倍,难度会如何调整?调整后每个块的出块时间会变成多少?
- 为什么修改区块内容(哪怕一个字符)就必须重新挖矿?这和区块链的不可篡改性有什么关系?
参考答案
Q1: 难度增加与 nonce 的关系 每增加一个前导零要求(十六进制),有效搜索空间扩大约 16 倍。实际运行中因为随机性会有波动,但多次取平均后会趋近 16 倍。这就是为什么比特币难度调整的精细度用 256 位 target 而不是简单的前导零个数——需要更平滑的控制。
Q2: 算力翻倍后的难度调整 比特币每 2016 个区块(约两周)调整一次难度。如果算力翻倍,这 2016 个块大约一周就挖完了,系统会将难度提高约 2 倍,使出块时间回到 10 分钟。难度调整是比特币维持固定出块速率的核心机制。
Q3: 修改内容为什么必须重新挖矿? 区块的 hash 是对整个区块头(包含交易数据的 Merkle Root)的 SHA-256 结果。改动任何内容都会改变 Merkle Root,从而使当前 hash 不再满足难度要求。攻击者不仅要重新挖当前块,还要重新挖之后所有区块(因为每个块的 header 包含前一块的 hash),算力成本随深度指数增长——这就是不可篡改性的来源。