强烈建议先快速回顾 区块链分叉的基础概念,再深入源码细节,你会对为啥代码里突然出现“dao-hard-fork”四个字节更有体感。
回顾 2016:价值 5 000 万美元的一次智能合约事故
2016 年 4 月 30 日,The DAO—一个用智能合约运作的链上风险投资基金—向全世界开放“众筹”。28 天吸金 1.5 亿美元的 ETH,成为当时最风光的 去中心化自治组织。谁也想不到,一份小小的递归调用漏洞,让黑客在 6 月 17 日转走了 3 600 000 ETH,按市价约 5 000 万美元。
市场震动、社区分裂,“是否直接回滚这笔交易”成为考验 去中心化精神 的社会级难题。
软硬分叉纷争与最终裁决
- 软分叉:只会让黑客资金继续“冻结”,但代码改动小,兼容老节点。
- 硬分叉:在区块高度 1920000 直接“回滚”,把 DAO 余额整体搬去退款合约。
投票、争论、算力站队,最终 “ETH 派” 胜出,执行硬分叉;拒绝回滚的矿工继续维护旧链,自此 Ethereum Classic(ETC) 诞生。
区块 1920000:ETH 与 ETC 的楚河汉界
关键信息 | 实际值 |
---|---|
分叉高度 | 1 920 000(0x1d4c00) |
extraData 标志 | dao-hard-fork (十六进制 0x64616f2d686172642d666f726b ) |
退款合约地址 | 0xbf4ed7b27f1d666546e30d74d50d173d20bca754 |
当天转账总额 | 12,001,961.845205763407115004 ETH 由 58 个 DAO 合约转出 |
这笔转账并没有出现在任何一笔 交易 里,而是被写进了 C++ 客户端源码,永不磨灭的 “链上补丁”。
C++ 源码剖析:补丁是怎么植入的?
1. 参数下发:哪儿记录了 1920000?
文件位置
libethashseal/genesis/mainNetwork.cpp
"daoHardforkBlock": "0x1d4c00"
同样目录里的 ropsten.cpp
将该值设为 0,意味着 Ropsten 测试网不做 DAO 分叉,方便开发者做无重放保护的测试。
关键词 “daoHardforkBlock” 既是硬分叉开关,也是未来所有 DAO challenge 的基准。
2. 一次性搬运余额:performIrregularModifications()
文件位置
libethereum/Block.cpp
void Block::performIrregularModifications()
{
u256 const& daoHardfork = m_sealEngine->chainParams().daoHardforkBlock;
if (daoHardfork != 0 && info().number() == daoHardfork)
{
Address recipient("0xbf4ed7b27f1d666546e30d74d50d173d20bca754");
Addresses allDAOs = childDaos();
for (Address const& dao : allDAOs)
m_state.transferBalance(dao, recipient, m_state.balance(dao));
m_state.commit(State::CommitBehaviour::KeepEmptyAccounts);
}
}
核心动作:
- 判断是否到达分叉高度;
- 遍历所有 DAO 子合约;
- 把余额 整包移动 给退款合约且不产生 交易回执;
- 提交状态,空账户保留,避免破坏后续 以太坊状态树。
3. 共识检测:DAO-Challenge 机制
当节点第一次与陌生 peer 建立连接,必须确认彼此在同一分叉上,于是出现了 DAO-Challenge——一次额外的协议握手。
发起挑战
BlockChainSync::onPeerStatus()
→ requestDaoForkBlockHeader()
if (!requestDaoForkBlockHeader(_peer)) {
syncPeer(_peer, false);
}
验证回应
BlockChainSync::verifyDaoChallengeResponse()
return header.number() == daoHardforkBlock
&& header.extraData() == fromHex("0x64616f2d686172642d666f726b");
如果对方回应的区块不含 dao-hard-fork
四字标记,节点会立刻 ban 掉该 peer,避免未来陷入 重放攻击 或 链错乱。
为什么这事对开发者仍值得关心?
- 做 以太坊节点 或 二层网络 如果忽略了 DAO challenge,会连不上大部分的 ETH Mainnet;
- 分叉实现技巧:以太坊过去 9 年只用过一次“代码级回滚”,源码就是 经典模板;
- 审计智能合约:DAO 事件催生了如今一整套 形式化验证、测试网复读、奖金众测 的全链路安全体系。
极速 FAQ:5 个常被问到的疑问
Q1:退款合约里的 ETH 后来都去哪了?
A:所有 DAO 代币持有者根据持币比例,在 2017 年初提现完毕,合约余额跌至 0,从此停止运行——完整追踪可以👉 通过链上数据工具查到每一步。
Q2:现在还能挖出 ETC 吗?
A:可以,但 ETC 采用与 ETH 不同的 Thanos
与 ECIP-1100
调整算法,需用支持该算法的矿机,并留意 算力波动 与 51% 攻击历史。
Q3:为什么测试网不一起做 DAO 分叉?
A:Ropsten、Goerli 等测试网就是为了复现主网“之前”的环境;如果强制带 daoHardforkBlock > 0
,开发者难以调试早期历史数据。
Q4:有没有官方文档解释 performIrregularModifications()
?
A:社区文档散见于 Ethereum Classic & Ethereum.org 的许多旧帖,可被视为 非正式的 EIP 0xdead,但它确实存在于 核心源码 里,自行阅读源码反而最权威。
Q5:未来还会出现类似的人为硬分叉吗?
A:理论上有,只要社区共识足够强大;但 2016→2024 的实践 表明概率极低,如今的治理更依循 EIP、Rollup、Layer2 模块化 的软升级路径。
扩展阅读与避坑提示
- 链上浏览器练习:到区块 1920000 观察
extraData
的十六进制原始字符串,把它抄下来再对照文中0x64616f2d686172642d666f726b
,体会 “四个字节定乾坤” 的玄学。