Alert Source Discuss
Standards Track: Core

EIP-4895: 将信标链提款作为操作推送

支持验证者通过一种新的“系统级”操作类型,从信标链向 EVM 进行提款。

Authors Alex Stokes (@ralexstokes), Danny Ryan (@djrtwo)
Created 2022-03-10

摘要

引入一个系统级的“操作”来支持从信标链“推送”到 EVM 的验证者提款。

这些操作会无条件地增加指定收款人的余额。

动机

此 EIP 提供了一种将在信标链上进行的验证者提款进入 EVM 的方法。 这种架构是基于“推送”的,而不是基于“拉取”的,即一旦从共识层出队,就需要在执行层处理提款。

提款在执行负载中表示为一种新型对象——“操作”——它将提款功能与用户级交易分离。 这种方法比之前引入新交易类型的方法更复杂,但它将这种“系统级”操作与常规交易干净地分离。 通过减少将这种系统级问题与用户数据混合产生的交互影响,这种分离简化了测试(因此有助于安全性)。

而且,相对于核心协议而言,这种方法比“拉取”式的替代方案更复杂,但确实提供了将关键特性更紧密地集成到协议本身中的途径。

规范

常量 单位
FORK_TIMESTAMP 1681338455  

从执行时间戳 FORK_TIMESTAMP 开始,执行客户端必须对负载验证和处理引入以下扩展:

系统级操作:提款

定义一个新的负载级别对象,称为 withdrawal,用于描述已经在共识层验证过的提款。 从语法上讲,Withdrawals 类似于用户级的交易,但存在于与用户级交易不同的域中。

Withdrawals 提供来自共识层的关键信息:

  1. 一个单调递增的 index,从 0 开始,作为 uint64 值,每次提款递增 1,以唯一标识每个提款
  2. 验证者的 validator_index,作为 uint64 值,对应于共识层上的提款
  3. 提取的以太币的接收者 address,作为 20 字节的值
  4. 以 Gwei (1e9 wei) 为单位的非零 amount 以太币,作为 uint64 值。

注意:每个提款的 index 是一个全局计数器,跨越整个提款序列。

Withdrawal 对象根据以下模式序列化为 RLP 列表:[index, validator_index, address, amount]

执行负载中的新字段:提款

执行负载获得了一个新字段 withdrawals,这是一个 Withdrawal 数据的 RLP 列表。

例如:

withdrawal_0 = [index_0, validator_index_0, address_0, amount_0]
withdrawal_1 = [index_1, validator_index_1, address_1, amount_1]
withdrawals = [withdrawal_0, withdrawal_1]

这个新字段在执行负载结构中现有字段之后进行编码,并被认为是执行负载主体的一部分。

execution_payload_rlp = RLP([header, transactions, [], withdrawals])

execution_payload_body_rlp = RLP([transactions, [], withdrawals])

注意:此模式中的空列表是由于 EIP-3675ommers 值设置为固定常量。

执行负载头中的新字段:提款根

执行负载头获得了一个新字段,用于提交执行负载中的 withdrawals

此提交的构造方式与现有执行负载头中的交易根完全相同,方法是将每个提款插入到 Merkle-Patricia 特里树中,该特里树的键是 withdrawals 列表中的索引。

def compute_trie_root_from_indexed_data(data):
    trie = Trie.from([(i, obj) for i, obj in enumerate(data)])
    return trie.root

execution_payload_header.withdrawals_root = compute_trie_root_from_indexed_data(execution_payload.withdrawals)

执行负载头扩展了一个新字段,其中包含特里树的 32 字节根,该特里树提交到给定执行负载中提供的提款列表。

为了说明:

execution_payload_header_rlp = RLP([
  parent_hash,
  0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
  coinbase,
  state_root,
  txs_root,
  receipts_root,
  logs_bloom,
  0, # difficulty
  number,
  gas_limit,
  gas_used,
  timestamp,
  extradata,
  prev_randao,
  0x0000000000000000, # nonce
  base_fee_per_gas,
  withdrawals_root,
])

注意:此示例中的字段名称和常量值反映了 EIP-3675EIP-4399。有关更多信息,请参阅这些 EIP。

执行负载有效性

假设执行负载格式良好,执行客户端具有额外的负载验证,以确保 withdrawals_root 与负载中给定列表的预期值匹配。

assert execution_payload_header.withdrawals_root == compute_trie_root_from_indexed_data(execution_payload.withdrawals)

状态转换

执行负载中的 withdrawals 在应用任何用户级交易之后处理。

对于 execution_payload.withdrawals 列表中的每个 withdrawal,实现都会增加由给定 amount 指定的 address 的余额。

回想一下,amount 以 Gwei 为单位给出,因此在使用执行状态中的帐户余额时必须执行转换为 wei 单位。

此余额更改是无条件的,并且必须不能失败。

此操作没有相关的 gas 成本。

理由

为什么不是一种新的交易类型?

此 EIP 建议使用一种新型对象——“提款操作”——因为它具有与其他现有类型的 EVM 交易不同的特殊语义。

操作由整个系统发起,而不是像典型交易那样源自最终用户。

一种全新的对象类型将通用 EVM 执行与这种类型的处理隔离开来,从而简化了提款的测试和安全审查。

为什么提款类型没有 (gas) 成本?

在给定时间可以到达执行层的最大提款数量是有界的(由共识层强制执行),并且选择此限制是为了使任何执行层操作成本在更广泛的负载执行上下文中可以忽略不计。

此绑定适用于计算成本(仅状态中的少量余额更新)和存储/网络成本,因为额外的负载占用空间保持较小(当前参数化将额外开销设置为当前平均负载大小的约 1%)。

为什么只有余额更新?没有通用的 EVM 执行?

更通用的处理会带来失败的风险,这会使信标链上的帐户变得复杂。

此 EIP 建议了一种提款路线,该路线以最小的(复杂性)成本提供大部分好处。

向后兼容性

没有问题。

安全注意事项

提款交易的共识层验证对于确保将适当数量的 ETH 提取回执行层至关重要。 这种共识层到执行层的 ETH 转移在 EVM 中没有当前的模拟,因此值得非常高的安全审查。

版权

CC0 下放弃版权和相关权利。

Citation

Please cite this document as:

Alex Stokes (@ralexstokes), Danny Ryan (@djrtwo), "EIP-4895: 将信标链提款作为操作推送," Ethereum Improvement Proposals, no. 4895, March 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4895.