Optimism的Fault proof

1. 引言

fault proof(错误证明),又名欺诈证明,或,交互游戏,其包含3大要素:

  • 1)Fault Proof Program(客户端角色):已知对所有rollup inputs(L1数据)的承诺值,和,dispute争议,可statelessly无状态地验证该争议。
  • 2)Fault Proof VM(服务端角色):已知某stateless无状态程序及其输入,追踪任意指令步骤,并在L1证明。
  • 3)Fault Proof Interactive Dispute Game:将争议一分为二为一条指令,并使用VM解决base-case基本情况。

这3大要素可具有不同的实现,从而组合为不同的proof stacks,并为解决某争议贡献proof多样性。

程序及其单独指令的“无状态执行”是指通过使用Pre-image Oracle的authenticating输入来再现完全相同的计算。
Optimism的Fault proof_第1张图片

2. Pre-image Oracle

Program(客户端)与 VM(服务端)之间的唯一通讯方式为:

  • pre-image oracle

二者通讯使用简单的request-response wire协议。具体见后面的Pre-image communication。

Program使用pre-image oracle来查询用户可以使用的任意输入数据:

  • 用于bootstrap该program的初始输入。具体见后面的Bootstrapping章节。
  • 还不是程序代码的外部数据。具体见Pre-image hinting routes。

pre-images以bytes32 type-prefixed key来表示:

  • 第一个字节标识request类型。
  • 剩下的31个字节标识该pre-image key。

其中requestleix you :

  • Type 0:Zero key。0前缀是非法的。
  • Type 1:Local key。用于program bootstrapping,以通过索引或名称来标识初始输入参数。
  • Type 2:Global keccak256 key。用作global pre-image store contract,其是完全上下文独立和无许可的。
  • Type 3:Global generic key。保留。
  • Type 4-128:保留范围。
  • Type 129-255:应用使用。

3. Bootstrapping

初始输入是确定性的,但不一定是单一的或全局的:可能同时存在多个不同的争议,每个争议都有自己的争议主张和L1上下文。

为了bootstrap,该program使用pre-image key type 1 来从VM请求初始输入。

VM知道外部上下文,并基于它们的类型映射所请求的pre-image keys,即type 1的local lookup或 type 2的global lookup,且可选地支持其他key类型。

4. Hinting

客户端与服务端之间还有另一可选通讯方式:

  • pre-image hinting

hinting是可选的,为L1 VM实现中的no-op。

hint本身在链上的成本非常低:

  • hint可为单个write系统调用,这是即时的,因为作为hint的内存写入实际上不需要作为链上证明的一部分加载。

hinting允许程序在生成链外证明时,指示VM其所感兴趣的数据。

VM可选择在任何时候执行所请求的hint:

  • 本地执行(对于标准请求),
  • 或者通过将hint重定向到VM program附带的工具,以模块化的形式执行。

hints不必直接执行:它们可能首先被记录下来以显示program的意图,最新的hint可能会被缓冲以供延迟执行,或者在只读模式下完全删除(如onchain链上)。

当pre-image oracle服务某请求,并且不能从现有的pre-images集合(如,某local pre-image缓存)服务时,VM可以执行该hint以检索丢失的pre-image(s)。该program有责任为每个pre-image请求提供足够的hinting。某些hints可能需要重复:在处理丢失的pre-image时,VM只需要执行最后一个hint。

注意,hint可以产生多个preimage:如,具有交易列表的以太坊区块的hint可为:

  • 区块头
  • 每笔交易
  • 形成交易列表merkle-Pricia Trie的中间merkle节点

准备pre-image。

hinting是通过阻塞双向流上的request-acknowledgement协议实现的:

 :=  

 := 

 := big-endian uint32  # length of 
 := byte sequence
 := 1-byte zero value

ack通知客户端该hint已处理。服务端可能会异步回复hints和pre-image请求,因为这是分开的streams。为避免正在请求的pre-images暂未获取,客户端应在观察到该hint acknowledgement之后再请求该pre-image。

5. pre-image通信

pre-images通过通过阻塞双向流上的最小wire-protocol来通信。该协议以阻塞读写系统调用来实现:

 :=   # the type-prefixed pre-image key

 :=  

 := big-endian uint64  # length of , note: uint64

其中:

  • :可为任意高的值:若其所需的pre-image内容已读取,客户端可随时停止读取。

6. Fault proof program

Fault proof program:

  • 将,L2 rollup的状态变更,的claims,
  • 定义为,
  • 基于L1数据的纯函数。

op-program是指该program的实现,基于op-nodeop-geth来实现的。
该program主要包含:

  • Prologue:加载输入,已知最小bootstrapping,和可能的test-overrides
  • Main content:处理L2状态变更,即,根据L1输入派生该状态更改。
  • Epilogue:检查该状态更改来验证该claim。

6.1 Prologue

program以2个主要输入来bootstrap:

  • l1_head:将其看成是L1链tip的L1区块哈希,证实所有之前L1的真实性。
  • dispute:标识所验证的claim。

bootstrapping,通过对program host的特殊输入请求来启动。

此外,还有隐含输入,这些输入源于上述主要输入,但可出于测试目的被覆盖:

  • l2_head:l2区块哈希,它将被视为l2链tip的之前共识,用于验证所有先前的L2历史。
  • 链配置:链配置可嵌入到程序中,也可根据L1上已标识的dispute属性来确定。
    • l1_chain_config:L1链的链配置(也称为l1_genesis.json)
    • l2_chain_config:L2链的链配置(也称为l2_generation.json)
    • rollup_config:rollup节点使用的rollup配置(也称为rollup.json)

隐含输入依赖于L1-introspection,通过争议游戏接口在L1历史(直到指定的L1_head)中加载争议的属性。争议可能是claim本身,也可能是指向L1中特定先前claimed数据的指针,这取决于争议游戏接口。

在实际的核心状态转换函数执行之前,隐含的输入被加载到“prologue”中。在测试期间,可以使用加载重写的简化prologue。

注意:目前只支持test-prologue,因争议游戏接口正在积极更改。

6.2 Main content

为验证L2 state的某claim,program首先基于之前认可的L2历史,应用L1数据,重新生成L2 state。该流程称为L2派生过程,且匹配 rollup节点 和 L2 execution engine内的处理流程。

不同于通过RPC来获取输入并对disk应用状态变更,输入通过pre-image oracle加载,并在内存中累加状态变化。

以2个数据源来派生该执行:

  • 1)对L1链只读的接口,由pre-image oracle来back:
    • l1_head:确定了可用的L1数据:后续没有可用的L1数据。
    • 链的实现从l1_head向下遍历header-chain,以按区块号查询服务。
    • l1_head:为L1 unsafe head、safe head和finalized head。
  • 2)L2 engine API接口:
    • 之前的L2链历史由pre-image oracle back,与L1链类似:
      • 初始的l2_head确定了可用的L2数据:后续没有可用的L2数据。
      • 链的实现从l2_head向下遍历header-chain,以按区块号查询服务。
      • l2_head:为L2 unsafe head、safe head和finalized head。
    • 新的L2链历史在内存中累加:
      • 若内存有限,尽管可使用pre-image oracle,按哈希来恢复数据,但program应首选在内存中保持最新创建的链数据,以最小化pre-image oracle访问。
      • L2 unsafe head、safe head和finalized head,可随着派生流程而变化。
      • L2 state包含了内存中的变化差量,可通过只读L2历史来访问任意未变化状态节点。

6.3 Epilogue

当main-content生成了disputed L2 state,epilogue会对该disputed claim下结论。

program会生成二进制输出来验证该claim,使用标准的single-byte Unix exit-code:

  • 0:成功,即该claim是正确的。
  • 非零值:表示失败,即该claim是不正确的:
    • 推荐使用1来标识不正确的claim
    • 其它非零值来表示runtime错误:如program代码中的bug所导致的panic或unexpected error。

7. Fault proof VM

fault proof VM实现:

  • 一个智能合约:来验证单个execution-trace step,如单个MIPS指令。
  • 一个CLI命令行:来为单个execution-trace step,生成proof。
  • 一个CLI命令行:来计算在第 N N N个step的VM state-root。

fault proof VM依赖于fault proof program,来基于hints提供任意丢失pre-images的接口。

VM仿真该program,为目标架构VM准备,并通过VM CLI生成state-root或指令proof。

Fault proof VM有:

  • Cannon:big-endian 32-bit MIPS proof,由OP Labs开发,当前已Public archive了。
  • Asterisc:little-endian 64-bit RISC-V proof,由protolambda开发,当前正在活跃开发中。

8. Fault proof interactive dispute game

互动纠纷游戏允许参与者通过链上挑战响应游戏解决纠纷,该游戏将不一致的区块 n → n + 1 n\rightarrow n+1 nn+1状态转换,然后基于为该状态转换建模的VM的executiont race,以证明单个VM trace步骤的基本情况为界。

游戏是多玩家的:不同的不结盟参与者可以在bond时参与。

响应时间是根据树分支中的剩余时间以及与claim的一致性来分配的。分配的响应时间受到争议游戏窗口的限制,当bond不足时,基于L1费用所需的任何额外时间都会发生变化。

注:计时、bond、一分为二争议游戏正在开发中。

参考资料

[1] Optimism的Fault proof

你可能感兴趣的:(区块链,区块链)