Myths BlogNever forget to improve yourself

EIP-4895 withdrawal

2023-03-31

EIP-4895 规定了一种系统级取款withdrawal操作,可以将 validator 的 ETH 从共识层提取到执行层。

FORK_TIMESTAMP1681338455,也就是 2023-04-12T22:27:35.000Z,此时间后各个执行客户端必须包含下列payload校验及功能。

withdrawal对象

定义一个称为withdrawalpayload级对象,它描述已在共识层验证的取款。

包含4个字段:

  • index, uint64, 每次提款增加1
  • validator_index, uint64, validator的序号
  • recipient, address, 取款接收地址
  • amount, uint64, 取款金额, 单位是Gwei

注意:每次取款的index是一个跨越整个取款序列的全局计数器。 RLP列表:[index, validator_index, address, amount]

执行时有一个withdrawals字段,表示取款对象列表,类似于交易列表,包含多个取款:

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]

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

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

withdrawals root

通过将每次withdrawal插入到以取款列表withdrawals中的索引为键的 Merkle-Patricia trie 中,此承诺的构造与现有执行负载标头中的transactions root相同。

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)

修改之后的payload:

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,
])

执行层的校验

假设执行有效payload格式正确,执行客户端有一个额外的有效payload验证,以确保 withdrawals_root 与给定有效payload列表的预期值相匹配。

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

状态转换

取款操作在普通用户交易之后被触发。 对于每个取款,增加对应address的余额,此操作必须成功。

一些解释

  1. 为什么不作为一种新的交易类型?

    因为取款操作不同于其他的交易。取款是由系统发起的,不是由普通用户交易。将通用 EVM 执行从此类处理中分离出来,以简化提款的测试和安全审查。

  2. withdrawal为什么没有gas cost?

    在给定时间内的取款操作次数是由共识层所限制的,在这种限制下所产生的取款消耗可以忽略不计。 这个界限适用于计算成本(状态中只有少数余额更新)和存储/网络成本,因为额外的有效负载占用空间很小(当前参数化将额外开销设置为当前平均有效负载大小的约 1%)。

  3. 为什么只是更新余额,而没有EVM的执行?

    EVM的执行会使得共识层的计算更加复杂。 此EIP所建议的只更新余额消耗最小。

  4. 安全注意

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

现状

此EIP所表述的所有内容均合并至capella共识升级其中使用python进行了更具体的描述。升级完成,已合并至主网。

操作

  1. 提取区块奖励:只需要将 0x00 提取凭证更改为 eth1 0x01 地址;
  2. 全部提款:需要在更改为“0x01”地址后,需要连接到信标节点,运行客户端相关命令退出信标链。

具体参见以下文档

https://docs.prylabs.network/docs/wallet/exiting-a-validator

https://docs.prylabs.network/docs/wallet/withdraw-validator

Reference

https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md

https://github.com/ethereum/consensus-specs/tree/dev/specs/capella

https://ethereum.org/en/staking/withdrawals/

https://notes.ethereum.org/@launchpad/withdrawals-faq

Copyright © 2023 Powered by myt0.com