L2执行引擎

目录

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

存入交易处理

引擎接口使用EIP-2718抽象出事务类型。

为了支持汇总功能,新存款的处理TransactionType 由引擎实现,请参阅存款规范

此类交易可以铸造L2 ETH,运行EVM,并在执行状态将L1信息引入到铭记的合约中。

存入交易边界

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

为了安全地处理存款交易,必须首先对存款进行身份验证:

  • 通过可信引擎 API 直接摄取
  • 部分同步到受信任的块哈希(通过之前的引擎 API 指令受信任)

存入的交易绝不能从交易池中消耗。 可以在仅存款汇总中禁用交易池

费用

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

费用金库

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

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

仓库名称预部署
定序器费用库SequencerFeeVault
基本费用金库BaseFeeVault
L1 费用金库L1FeeVault

优先费(Sequencer Fee Vault)

优先费遵循eip-1559规范,由 L2 区块的费用接收方收取。区块费用接收者(又名 coinbase 地址)设置为 Sequencer Fee Vault 地址。

基本费用(基本费用保险库)

基本费用很大程度上遵循eip-1559规范,但基本费用不会被销毁,而是会累加到基本费用 Vault ETH 账户余额中。

L1-成本费(L1 Fee Vault)

该协议通过根据估计的批量提交成本向 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 Oracleoverhead值。

  • l1FeeScalar是 Gas Price Oraclescalar值。

  • l1Basefee是在L2链上注册的最新L1源的L1基本费用。

请注意,它使用与eip-2028rollupDataGas中定义的相同的字节成本核算,但完整的 L2 事务现在计入 L1 呼叫数据中收取的字节数。此行为与 Bedrock 之前对 L2 交易的 L1 成本估计相匹配。

overhead批量交易的压缩、批量和内在 Gas 成本由具有 Gas Price Oracle和参数的协议计算scalar

Gas Price Oraclel1FeeOverheadl1FeeScalar以及l1BasefeeL1 来源的 可以通过两种可互换的方式访问:

  • 从当前 L2 块的存放的 L1 属性 ( l1FeeOverhead, l1FeeScalar, ) 中读取basefee

  • 从 L1 区块信息合约中读取 (

    0x4200000000000000000000000000000000000015
    

    )

    • 使用相应的 Solidity uint256-getter 函数 ( l1FeeOverhead, l1FeeScalar, basefee)
    • 使用直接存储读取:
      • uint256L1 基本费用作为槽中的大尾数法1
      • uint256槽中作为大端的开销5
      • uint256标量作为槽中的大尾数法6

引擎API

engine_forkchoiceUpdatedV1

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

在汇总中,forkchoice 更新的类型转换为:

  • headBlockHash:规范链头部的区块哈希。在用户 JSON-RPC 中标记"unsafe"。节点可以提前在带外应用 L2 块,然后在 L1 数据冲突时重新组织。
  • safeBlockHash:规范链的区块哈希,源自L1数据,不太可能重组。
  • finalizedBlockHash:不可逆的区块哈希,匹配争议期的下边界。

为了支持汇总功能,引入了一项向后兼容的更改engine_forkchoiceUpdatedV1:扩展PayloadAttributesV1

扩展有效负载属性V1

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 规范使用的十六进制值编码,因为该结构需要通过 JSON-RPC 发送。指的是 JSON 数组。array

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

transactions字段是可选的:

  • 如果为空或缺失:引擎行为不会发生变化。排序器(如果启用)将通过消耗交易池中的交易来构建区块。
  • 如果存在且非空:必须从这个确切的事务列表开始生成有效负载。Rollup 驱动程序根据确定性 L1 输入确定事务列表。

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

  • 如果false,执行引擎可以在任何transactions. 这是 L1 节点实现的默认行为。
  • 如果true,则执行引擎不得更改有关给定列表的任何内容transactions

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

gasLimit与 L1 的兼容性是可选的,但在用作汇总时是必需的。该字段覆盖块构建期间使用的气体限制。如果未指定为汇总,STATUS_INVALID则返回 a。

engine_newPayloadV1

没有对engine_newPayloadV1. 将 L2 块应用于发动机状态。

engine_getPayloadV1

没有对engine_getPayloadV1. 按 ID 检索有效负载,由engine_forkchoiceUpdatedV1调用时准备payloadAttributes

联网

执行引擎可以通过rollup节点获取所有数据,正如源自L1: P2P网络是严格可选的。

然而,为了不成为 L1 数据检索速度的瓶颈,应该启用 P2P 网络功能,服务于:

  • 对等发现(光盘 v5

  • eth/66

    • 交易池(由排序器节点消耗)
    • 状态同步(快速无信任数据库复制的快乐路径)
    • 历史区块头和区块体检索
    • 新区块通过共识层获取(rollup 节点)

除了配置之外,无需修改 L1 网络功能:

  • networkID:区分 L2 网络与 L1 和测试网。等于chainIDrollup 网络的 。
  • 激活合并分叉:启用引擎 API 并禁用块的传播,因为没有共识层就无法对块头进行身份验证。
  • Bootnode列表:DiscV5是共享网络, 通过先连接L2节点引导速度更快。

同步

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

  • Happy-path:rollup节点将L1确定的所需链头告知引擎,通过引擎P2P完成。
  • 最坏情况:汇总节点检测到停滞的引擎,纯粹从 L1 数据完成同步,不需要对等点。

happy-path 更适合让新节点快速上线,因为引擎实现可以通过snap-sync等方法更快地同步状态。

快乐路径同步

  1. rollup 节点无条件地通知 L2 链头的引擎(常规节点操作的一部分):
  2. 引擎向同级请求标头,反向请求直到父哈希与本地链匹配
  3. 引擎赶上:a)一种形式的状态同步被激活以实现最终或头块哈希b)一种形式的块同步将块体和进程拉向头块哈希

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

最坏情况同步

  1. 引擎不同步、未对等和/或由于其他原因而停止。
  2. 汇总节点维护来自引擎的最新头(轮询eth_getBlockByNumber和/或维护头订阅)
  3. 如果引擎不同步但未通过 P2P 同步,则汇总节点会激活同步 ( eth_syncing)
  4. Rollup 节点逐一插入从 L1 派生的块,可能适应 L1 重组,如Rollup 节点规范中所述( engine_forkchoiceUpdatedV1, engine_newPayloadV1)