Alert Source Discuss
Standards Track: Core

EIP-158: 状态清理

Authors Vitalik Buterin (@vbuterin)
Created 2016-10-16

Specification

对于所有 block.number >= FORK_BLKNUM (待定) 的区块:

  1. 在所有对账户进行状态更改的情况下,并且此状态更改导致账户状态以 nonce = 0、balance = 0、code 为空、storage 为空(以下简称 “空账户”)保存时,则改为删除该账户。
  2. 如果一个地址被 “触及” 并且该地址包含一个空账户,则将其删除。“触及” 定义为任何情况下,如果在给定地址的账户不存在,则会创建该账户的情况。
  3. 每当 EVM 检查账户是否存在时,空状态被视为等同于不存在。特别要注意的是,这意味着一旦启用此更改,从 EVM 执行的角度来看,空状态和不存在之间将不再有有意义的区别。
  4. 零值调用和零值自毁在任何情况下都不再消耗 25000 的账户创建 gas 成本

可以按如下方式枚举发生 “触及” 的情况:

  • 零值 CALL
  • CREATE(如果最终保存的代码为空,并且在保存时账户中没有剩余的以太币)
  • 零值 SUICIDE
  • 交易接收者
  • 在合约创建交易中创建的合约
  • 矿工收到交易费用(注意 gasprice 为零的情况,并且该账户尚未存在,因为它仅在处理完每笔交易_后_收到区块/叔叔/侄子的奖励)

    Specification (1b)

当 EVM 检查是否为空(为了可能应用 25000 gas 成本),空状态由 is_empty(acct): return get_balance(acct) == 0 and get_code(acct) == "" and get_nonce(acct) == 0 定义;存储的空状态无关紧要。这简化了客户端实现,因为无需添加额外的复杂性以使缓存以正确的方式可枚举,并且不会显着影响预期结果,因为 balance/code/nonce 为空但 storage 为非空的情况(其中此更改将导致支付额外的 25000 gas)是病态的,并且没有实际使用价值。

Specification (1c)

不要实现上面的第 2 点(即,不能创建新的空账户,但是除非实际_更改_了现有账户的状态,否则不会自动销毁它们)。相反,从(包括)N 开始到没有剩余的空账户为止的每个区块中,选择按照 sha3(address) 顺序从左到右的 1000 个剩余空账户,然后删除它们(按哈希排序是必要的,以便可以通过迭代树轻松找到这些账户)。

Rationale

这消除了大量由于以太坊协议早期版本的缺陷而以非常低的成本放入状态中的空账户,从而大大减小了状态大小,从而减少了完整客户端的硬盘负载并减少了快速同步的时间。此外,从长远来看,它简化了协议,因为一旦清除了所有 “空” 对象,账户为空和不存在之间不再有任何有意义的区别,并且实际上可以将不存在简单地视为为空的紧凑表示。

请注意,此提案确实引入了对现有保证的临时破坏,因为通过重复零值调用已经存在的空账户,可以以每个账户 700 gas 的成本创建状态更改,而不是通常的每 gas 至少 5000(使用 SUICIDE 退款,这将进一步降低到每个账户 350 gas)。允许每个区块进行如此大量的状态写入将导致区块处理时间增加,并在短期内增加叔块率,同时清除现有的空账户,并且最终一旦清除所有空账户,此问题将不再存在。

References

  1. EIP-158 issue and discussion: https://github.com/ethereum/EIPs/issues/158
  2. EIP-161 issue and discussion: https://github.com/ethereum/EIPs/issues/161

Citation

Please cite this document as:

Vitalik Buterin (@vbuterin), "EIP-158: 状态清理," Ethereum Improvement Proposals, no. 158, October 2016. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-158.