Alert Source Discuss
Standards Track: Core

EIP-161: 状态树清理 (保持不变性的替代方案)

Authors Gavin Wood (@gavofyork)
Created 2016-10-24

硬分叉

Spurious Dragon

参数

  • FORK_BLKNUM: 2,675,000
  • CHAIN_ID: 1 (Mainnet)

规范

a. 账户创建交易和 CREATE 操作应在执行初始化代码之前,将 nonce 在其正常起始值的基础上 递增 (对于普通网络,这将仅仅是 1,但具有非零默认起始 nonce 的测试网络将会不同)。

b. 当目标不存在时,CALLSUICIDE 会收取 25,000 gas,现在,只有当操作转移 超过零的值 且目标账户是 dead 时,才应收取费用。

c. 任何账户都不能从不存在的 改变状态 为存在但 empty。 如果操作会这样做,则帐户应保持为不存在。

d. 在交易结束时,任何被该交易执行 触及 且现在是 empty 的账户应变为不存在(即 删除)。

其中:

当一个账户参与到任何潜在的 状态改变 操作中时,它被认为是 touch 的。 这包括但不限于作为 零值转移 的接收者。

当一个账户 没有代码nonce 为零余额为零 时,它被认为是 empty 的。

当一个账户不存在或 empty 时,它被认为是 dead 的。

在交易结束时 是指紧随 suicide 列表执行之后,在确定用于收据填充的状态树根之前。

一个账户 改变状态 当:

  • 它是 SUICIDE 操作的 零或更多 值的目标或退款;
  • 它是 CALL 操作或消息调用交易的源或目标,转移 零或更多 值;
  • 它是 CREATE 操作或合约创建交易的源或创建,赋予 零或更多 值;
  • 作为区块作者(“矿工”),它是区块奖励或交易费的 零或更多 值的接收者。

注释

在当前的以太坊协议中,应该注意的是,很少有状态更改最终会导致在交易执行后账户为空。 事实上,当前实现只需要跟踪四种情况:

  • 一个 empty 账户通过 CALL 收到零值转移;
  • 一个 empty 账户通过 SUICIDE 收到零值转移;
  • 一个 empty 账户通过消息调用交易收到零值转移;
  • 一个 empty 账户通过零 gas 价格的费用转移收到零值转移。

理由

与 #158 相同,只是避免了几个边缘情况,因为我们没有打破不变性:

  • 一个账户可以在交易执行过程中从中途从具有代码和存储变为不具有代码或存储; [已更正]
  • 一个新创建的账户在部署之前不能被删除。

CREATE 避免了 nonce 中的零,以避免任何关于 CREATE 的账户在其创建过程中被中途收割的奇怪之处。

附录 (2017-08-15)

在 2016-11-24,由于两个实现在状态回滚的情况下具有不同的行为,因此发生了一个共识错误。[3] 该规范已进行修订,以澄清当状态回滚时,empty 账户删除也会回滚。

参考文献

  1. EIP-158 问题和讨论: https://github.com/ethereum/EIPs/issues/158
  2. EIP-161 问题和讨论: https://github.com/ethereum/EIPs/issues/161
  3. https://blog.ethereum.org/2016/11/25/security-alert-11242016-consensus-bug-geth-v1-4-19-v1-5-2/

    详情: Geth 未能回滚 empty 账户删除,当导致 empty 账户删除的交易以 out-of-gas 异常结束时。 在 Parity 中发现了另一个问题,其中 Parity 客户端错误地未能回滚 empty 账户删除,在涉及 out-of-gas 调用预编译合约的更有限的上下文中; 新的 Geth 行为与 Parity 的行为相匹配,并且一旦状态清除过程完成,empty 账户将不再是通常关注的来源,大约在一周后。

Citation

Please cite this document as:

Gavin Wood (@gavofyork), "EIP-161: 状态树清理 (保持不变性的替代方案)," Ethereum Improvement Proposals, no. 161, October 2016. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-161.