L2 执行引擎

本文档概述了L1执行引擎对L2的修改、配置和使用,包括处理存款交易、手续费的收取方式(优先级费用、基础费用和 L1 成本费用),还介绍了Engine API 的使用,例如 forkchoiceUpdatedV1、newPayloadV1、getPayloadV1,以及L2执行引擎的网络和同步方式。

L2 执行引擎

<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> 目录

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

本文档概述了 L2 的 L1 执行引擎的修改、配置和使用。

已存入交易处理

Engine 接口使用 EIP-2718 抽象了交易类型。

为了支持 rollup 功能,通过引擎实现了对新 Deposit TransactionType 的处理,参见存款规范

这种类型的交易可以铸造 L2 ETH,运行 EVM, 并将 L1 信息引入到执行状态中的已确立的合约中。

已存入交易边界

交易不能被盲目信任,信任是通过身份验证建立的。 与其他交易类型不同,存款不由签名进行身份验证: rollup 节点在引擎外部对其进行身份验证。

为了安全地处理已存入的交易,必须首先验证存款:

  • 通过受信任的 Engine API 直接提取
  • 同步到受信任的区块哈希(通过之前的 Engine API 指令信任)

已存入的交易绝不能从交易池中使用。 可以在仅存款的 rollup 中禁用交易池

费用

排序交易(即不适用于存款)收取 3 种类型的费用: 优先费用、基础费用和 L1 成本费用。

费用金库

这三种类型的费用都收集在 3 个不同的 L2 费用金库部署中,用于记账目的: 费用支付未注册为内部 EVM 调用,因此可以通过这种方式更好地区分。

这些都是硬编码的地址,指向预先部署的代理合约。 代理由基于 FeeVault 的金库合约部署支持,以安全地将金库资金路由到 L1。

金库名称 预部署
排序器费用金库 SequencerFeeVault
基础费用金库 BaseFeeVault
L1 费用金库 L1FeeVault

优先费用(排序器费用金库)

优先费用遵循 eip-1559 规范,并由 L2 区块的费用接收者收取。 区块费用接收者(又名 coinbase 地址)设置为排序器费用金库地址。

基础费用(基础费用金库)

基础费用主要遵循 eip-1559 规范,但基础费用不会被销毁, 而是累加到基础费用金库 ETH 账户余额中。

L1 成本费用(L1 费用金库)

该协议通过根据估计的批量提交成本向 L2 用户收取额外费用来为排序的 L2 交易的批量提交提供资金。 此费用从 L2 交易发送者的 ETH 余额中扣除,并收集到 L1 费用金库中。

用于确定 L2 交易的 L1 成本费用的确切 L1 成本函数的计算方式为: (rollupDataGas + l1FeeOverhead) * l1Basefee * l1FeeScalar / 1000000 (big-int 计算,结果为 Wei 和 uint256 范围) 其中:

  • rollupDataGas完整编码的交易确定 (标准 EIP-2718 交易编码,包括签名字段):
    • 在 Regolith 分叉之前:rollupDataGas = zeroes * 4 + (ones + 68) * 16
    • 添加 68 个非零字节是 Bedrock 之前 L1 成本记账功能的残留, 与 Bedrock 不同,它考虑了最坏情况下的非零字节添加来补充未签名的交易。
    • 使用 Regolith 分叉:rollupDataGas = zeroes * 4 + ones * 16
  • l1FeeOverhead 是 Gas Price Oracle 的 overhead 值。
  • l1FeeScalar 是 Gas Price Oracle 的 scalar 值。
  • l1Basefee 是 L2 链中注册的最新 L1 来源的 L1 基础费用。

请注意,rollupDataGas 使用与 eip-2028 中定义的相同的字节成本核算, 只是现在完整的 L2 交易计入 L1 calldata 中收取的字节。 此行为与 Bedrock 之前 L2 交易的 L1 成本估算相匹配。

批量交易的压缩、批处理和内在 gas 成本由协议通过 Gas Price Oracle 的 overheadscalar 参数进行核算。

Gas Price Oracle 的 l1FeeOverheadl1FeeScalar 以及 L1 来源的 l1Basefee 可以通过两种可互换的方式访问:

  • 从当前 L2 区块的已存入的 L1 属性(l1FeeOverheadl1FeeScalarbasefee)中读取
  • 从 L1 区块信息合约 (0x4200000000000000000000000000000000000015) 中读取
    • 使用相应的 solidity uint256 getter 函数(l1FeeOverheadl1FeeScalarbasefee
    • 使用直接存储读取:
    • L1 基础费用,以 big-endian uint256 格式存储在插槽 1
    • 开销,以 big-endian uint256 格式存储在插槽 5
    • 标量,以 big-endian uint256 格式存储在插槽 6

引擎 API

<!-- 注意:Engine API 处于 alpha 阶段,v1.0.0-alpha.5。 可能会有细微的调整,beta 版将在几周后开始 -->

engine_forkchoiceUpdatedV1

这会更新引擎认为哪些 L2 区块是规范的(forkchoiceState 参数), 并可选择启动区块生产(payloadAttributes 参数)。

在 rollup 中,分叉选择更新的类型转换为:

  • headBlockHash:规范链的头的区块哈希。在用户 JSON-RPC 中标记为 "unsafe"。 节点可能会提前异地应用 L2 区块,然后在 L1 数据冲突时进行重组。
  • safeBlockHash:规范链的区块哈希,从 L1 数据派生而来,不太可能重组。
  • finalizedBlockHash:不可逆的区块哈希,与争议期的下限相匹配。

为了支持 rollup 功能,引入了一个向后兼容的更改 到 engine_forkchoiceUpdatedV1:扩展的 PayloadAttributesV1

扩展的 PayloadAttributesV1

PayloadAttributesV1 扩展为:

PayloadAttributesV1: {
    timestamp: QUANTITY
    random: DATA (32 bytes)
    suggestedFeeRecipient: DATA (20 bytes)
    transactions: array of DATA
    noTxPool: bool
    gasLimit: QUANTITY or null
}

此处使用的类型表示法指的是 以太坊 JSON-RPC API 规范 使用的 [HEX 值编码], 因为此结构需要通过 JSON-RPC 发送。array 指的是 JSON 数组。

transactions 数组的每个项都是一个字节列表,用于编码交易:TransactionType || TransactionPayloadLegacyTransaction,如 EIP-2718 中定义。 这等同于 ExecutionPayloadV1 中的 transactions 字段

transactions 字段是可选的:

  • 如果为空或缺失:引擎行为没有变化。排序器将(如果启用)通过从交易池中使用交易来构建区块。
  • 如果存在且非空:必须使用此精确的交易列表开始生成 payload。 rollup 驱动程序 根据确定的 L1 输入来确定交易列表。

noTxPool 也是可选的,并且扩展了 transactions 的含义:

  • 如果为 false,则执行引擎可以自由地将来自外部来源(如 tx 池)的其他交易打包到 payload 中,在任何 transactions 之后。这是 L1 节点实现的默认行为。
  • 如果为 true,则执行引擎不得更改给定列表 transactions 的任何内容。

如果 transactions 字段存在,则引擎必须按顺序执行交易,并且如果在处理交易时出现错误,则返回 STATUS_INVALID。如果所有交易都可以无错误地执行,则必须返回 STATUS_VALID注意:状态转换规则已修改,以便存款永远不会失败,因此如果 engine_forkchoiceUpdatedV1 返回 STATUS_INVALID,则是因为批量交易无效。

gasLimit 对于与 L1 的兼容性是可选的,但用作 rollup 时是必需的。 此字段会覆盖区块构建期间使用的 gas 限制。 如果未指定为 rollup,则返回 STATUS_INVALID

engine_newPayloadV1

engine_newPayloadV1 没有修改。 将 L2 区块应用于引擎状态。

engine_getPayloadV1

engine_getPayloadV1 没有修改。 检索由 engine_forkchoiceUpdatedV1 在使用 payloadAttributes 调用时准备的 payload(通过 ID)。

engine_signalSuperchainV1

Engine API 的可选扩展。向 Engine 发出关于超级链的信息: V1 发出推荐和要求的协议版本。

类型:

SuperchainSignal: {
    recommended: ProtocolVersion
    required: ProtocolVersion
}

ProtocolVersion: 按照 协议版本格式规范 的定义,编码为 RPC。

参数:

  • signal: SuperchainSignal,发出的超级链信息。

返回值:

  • ProtocolVersion: 执行引擎最新支持的 OP-Stack 协议版本。

当推荐版本比执行引擎当前支持的版本更新时,执行引擎应该警告用户。

如果执行引擎不满足所需的协议版本,应该 采取安全预防措施。 这可能包括在执行引擎运营商同意的情况下停止引擎。

网络

执行引擎可以通过 rollup 节点获取所有数据,该节点从 L1 派生: P2P 网络是严格可选的。

但是,为了不限制 L1 数据检索速度,应启用 P2P 网络功能,并提供以下服务:

  • 对等点发现 (Disc v5)
  • eth/66:
    • 交易池(由排序器节点使用)
    • 状态同步(用于快速、无需信任的数据库复制的顺利通道)
    • 历史区块头和主体检索
    • 新区块通过共识层获取(rollup 节点)

除了配置之外,不需要对 L1 网络功能进行任何修改:

  • networkID:区分 L2 网络与 L1 和测试网。 等于 rollup 网络的 chainID
  • 激活 Merge 分叉:启用 Engine API 并禁用区块传播, 因为在没有共识层的情况下无法验证区块头。
  • 引导节点列表:Discv5 是一个共享网络, bootstrap 通过首先与 L2 节点连接来更快地实现。

同步

执行引擎可以通过不同的方式进行同步:

  • 顺利通道:rollup 节点将引擎告知 L1 确定的所需链头,并通过引擎 P2P 完成。
  • 最坏情况:rollup 节点检测到引擎停滞,完全从 L1 数据完成同步,无需对等点。

顺利通道更适合快速启动新节点, 因为引擎实现可以通过诸如 快照同步 之类的方法更快地同步状态。

顺利同步

  1. rollup 节点无条件地将 L2 链头告知引擎(常规节点操作的一部分):
  2. 引擎从对等点请求标头,反向直到父哈希与本地链匹配
  3. 引擎赶上进度: a) 向最终确定或头区块哈希激活一种状态同步形式 b) 一种区块同步形式拉取区块主体并处理到头区块哈希

基于 P2P 的确切同步超出了 L2 规范的范围: 引擎中的操作与 L1 完全相同(尽管具有支持存款的 EVM)。

最坏情况同步

  1. 引擎不同步、未对等和/或由于其他原因而停滞。
  2. rollup 节点维护引擎的最新头(轮询 eth_getBlockByNumber 和/或维护标头订阅)
  3. 如果引擎不同步但未通过 P2P 同步 (eth_syncing),则 rollup 节点激活同步。
  4. rollup 节点逐个插入从 L1 派生的区块,可能会适应 L1 重组, 如 [rollup 节点规范] (engine_forkchoiceUpdatedV1, engine_newPayloadV1) 中所述。
  • 原文链接: github.com/ethereum-opti...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

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