Homestead 硬分叉变更

这篇文章详细介绍了以太坊Homestead硬分叉引入的四项关键协议变更,包括提高合约创建的Gas成本、限制交易签名的s值、合约创建失败时的处理方式,以及调整难度调整算法。文章还阐述了每项变更背后的原因和其解决的问题。

元参考

Homestead.

参数

FORK_BLKNUM 链名
1,150,000 主网
494,000 Morden
0 未来测试网

规范

如果 block.number >= HOMESTEAD_FORK_BLKNUM,执行以下操作:

  1. 通过交易创建合约的 gas 成本从 21,000 增加到 53,000,即,如果你发送一笔交易,且目标地址为空字符串,则初始扣除的 gas 为 53,000 加上交易数据的 gas 成本,而不是目前情况下的 21,000。从合约使用 CREATE 操作码创建合约不受影响。
  2. 所有 s 值大于 $\text{secp256k1n}/2$ 的交易签名现在被视为无效。ECDSA recover 预编译合约保持不变,并将继续接受高 s 值;这在例如合约恢复旧比特币签名时很有用。
  3. 如果合约创建没有足够的 gas 来支付将合约代码添加到状态的最终 gas 费用,则合约创建会失败(即 gas 耗尽),而不是留下一个空合约。
  4. 将难度调整算法从当前公式: $$ \text{block_diff} = \text{parent_diff} + \text{parent_diff} \text{ // } 2048 \times \begin{cases} 1 & \text{if } \text{block_timestamp} - \text{parent_timestamp} < 13 \ -1 & \text{else} \end{cases} + \text{int}(2^{((\text{block.number} \text{ // } 100000) - 2)}) $$ (其中 $\text{int}(2^{((\text{block.number} \text{ // } 100000) - 2)})$ 代表指数难度调整部分)更改为 $$ \text{block_diff} = \text{parent_diff} + \text{parent_diff} \text{ // } 2048 \times \max(1 - (\text{block_timestamp} - \text{parent_timestamp}) \text{ // } 10, -99) + \text{int}(2^{((\text{block.number} \text{ // } 100000) - 2)}) $$ 其中 // 是整数除法运算符,例如 $6 \text{ // } 2 = 3$, $7 \text{ // } 2 = 3$, $8 \text{ // } 2 = 4$。 minDifficulty 仍然定义了允许的最小难度,并且任何调整都不能使其低于此值。

基本原理

目前,通过交易创建合约存在过度的激励,其成本为 21,000,而不是通过合约创建,其成本为 32,000。此外,借助 suicide 退款,目前可以使用仅 11,664 gas 进行简单的以太币价值转移;执行此操作的代码如下:

from ethereum import tester as t
> from ethereum import utils
> s = t.state()
> c = s.abi_contract('def init():\n suicide(0x47e25df8822538a8596b28c637896b4d143c351e)', endowment=10**15)
> s.block.get_receipts()[-1].gas_used
11664
> s.block.get_balance(utils.normalize_address(0x47e25df8822538a8596b28c637896b4d143c351e))
1000000000000000

这并不是一个特别严重的问题,但它无疑可以算是一个错误。

目前允许任何 s 值在 $0 < s < \text{secp256k1n}$ 范围内的交易,这引发了交易可塑性(malleability)问题,因为人们可以获取任何交易,将 s 值从 $s$ 翻转为 $\text{secp256k1n} - s$,翻转 v 值(27 -> 2828 -> 27),并且生成的签名仍然有效。这不是一个严重的安全漏洞,尤其因为以太坊使用地址而不是交易哈希作为以太币价值转移或其他交易的输入,但它仍然造成了用户界面的不便,因为攻击者可能导致区块中确认的交易哈希与任何用户发送的交易哈希不同,从而干扰使用交易哈希作为跟踪 ID 的用户界面。防止高 s 值可以解决这个问题。

如果合约创建没有足够的 gas 来支付最终 gas 费用而导致 gas 耗尽,这有以下好处:

  • (i) 它在合约创建过程的结果中创建了更直观的“成功或失败”的区别,而不是当前的“成功、失败或空合约”三元划分;
  • (ii) 使失败更容易被检测,因为除非合约创建完全成功,否则根本不会创建合约账户;并且
  • (iii) 在存在捐赠(endowment)的情况下,使合约创建更安全,因为保证要么整个初始化过程发生,要么交易失败并退还捐赠。

难度调整的改变彻底解决了一个以太坊协议在两个月前遇到的问题,当时有过多的矿工挖出的区块包含的时间戳等于 $\text{parent_timestamp} + 1$;这扭曲了区块时间分布,因此当前以 13 秒为中位数的区块时间算法继续以相同的中位数为目标,但平均值开始增加。如果 51% 的矿工以这种方式开始挖矿,平均值将无限增加。提议的新公式大致基于以平均值为目标;可以证明,使用该公式,长期来看,平均区块时间超过 24 秒在数学上是不可能的。

使用 $(\text{block_timestamp} - \text{parent_timestamp}) \text{ // } 10$ 作为主要输入变量,而不是直接使用时间差,旨在保持算法的粗粒度特性,防止过度激励将时间戳差设置为正好 1,以创建难度略高的区块,从而保证击败任何可能的 fork。上限 -99 仅仅是为了确保,如果由于客户端安全漏洞或其他黑天鹅事件导致两个区块之间的时间间隔非常远,难度不会极度下降。

实现

这在 Python 中实现,链接如下:

  1. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L130
  2. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L129
  3. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L304
  4. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/blocks.py#L42
  • 原文链接: github.com/nerolation/EI...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Nerolation
Nerolation
江湖只有他的大名,没有他的介绍。