Polygon zkEVM是兼容EVM的zkRollup Layer 2 方案。zkEVM 证明的第一步是构建交易的执行路径 (execution trace)。trace
是一个矩阵,每一列有一个名字,对每一列进行多项式插值,将执行路径的正确性归纳为多项式之间的恒等关系,这称算术化(arithmetization)。状态机主要提供了EVM证明的算术化过程。
Fibonacci 示例
Fibonacci State Machine
对于给定初始条件Fibonacci 序列,可以用两个寄存器A 和 B 构建状态机,如下图:
状态机初始条件为 , 并且有如下的关系:
将寄存器状态表示为多项式, 定义域在子群 , 即的8次单位根上,关系如下:
状态机的关系可以转为多项式的恒等关系:
但这些等式无法完全约束,例如:
- 寄存器是非循环的,当在 计算等式关系的时候:
- 其它的初始条件也能满足恒等关系,例如 (2, 4)。
为了解决上述问题,可以添加一个辅助寄存器(C):
此时 多项式 为:
新的多项式恒等关系为:
并且可以使用其它的初始条件, 修改多项式恒等关系为:
在上一个例子中,。
状态机证明
多项式承诺需要满足Binding
和 Hiding
, 可以使用Kate 和 FRI 承诺。
Simple State Machine
首先展示一个简单状态机的算术化过程,如下图:
下列程序描述寄存器 A 和 B 接受输入的过程:
Instruction |
---|
${getInput()} => A |
3 => B |
: ADD |
0 => A, B |
上面的程序由汇编语言实现,通过executor
读入,生成执行路径。上面的代码,汇编指令分别表示为:
- ${ getInput() } => A: 寻求自由输入,并保存在寄存器 A中。
- 3 => B. 将3移入寄存器B 中;
- :ADD 将寄存器 A 和 B的值加起来,作为寄存器A 的输出;
- 0 => A, B 将0 移动到寄存器 A 和 B上。
例如,对于自由输入为7时,执行路径为:
其中 为 寄存器 的下一个状态, 其中
为了创建合适的算术化约束条件,需要添加辅助的状态和选择子(selectors)表示寄存器 和 的关系:
其中 :
- : 选择子,表示是否包含 在线性组合中;
- : 选择子,表示是否将线性组合结果赋给;
- : 包含的自由输入
- : 包含一些固定的值
在引入辅助变量之后,可以得到下面的扩展表:
寄存器状态的关系可以用如下代数关系表示:
将寄存器的状态表示为多项式 , 定义域为子群上,
这个程序可以完全由常量多项式: , , , , 描述。
多项式 可以是公开的,或根据不同的初始条件 提前承诺。
程序的最终结果为
最后的指令重置寄存器的值到初始状态,形成一个循环。
条件语言跳转
下面引入指令 ,能够跳到指定的位置。在下面的程序中,当 值为0的时候, 将跳到 5 的位置:
当引入条件跳转的时候,根据不同的输入值,执行路径长度是不一样的,如下所示:
上面的执行是6步,下面的执行是5步。
管理条件跳转
需要引入 新模型管理程序的条件跳转:
需要添加程序计数器, PC是一种特殊的寄存器,包含程序指令的执行位置。
下面使用 作为以下线性组合的简写:
若 为0, 将会跳转到指令 位置,首先需要检查操作在 中是否为0.
为了检查 中的数是否为0, 需要使用新的方法:若, 则 必然有一个乘法逆元:
下面添加 检查约束条件:
可以将两个方程变成一个约束条件:
引入下面的机制处理跳转:
添加选择子 , 通过下面的约束描述 的行为。
当输入分别为7和3的时候,执行路径分别为:
其中 用来表示 的逆。
目前,多项式是没有经过预处理的,因为表中的值不仅依赖自由输入,还需要验证正确的执行了程序。
证明正确的程序执行
为了检查执行了正确有的程序,我们提供一种指令常数值编码的方法,然后检查执行指令的编码确实在程序中指令的编码中。
假设采用4位符号整数(实际中为32位)进行编码指令中的常数值
,如下所示:
去掉(8=-8), 编码余下的值为:
然后约束:
等价于:
对示例程序指令编码后的结果为:
采用如下规则编码指令:
另外,需要检查 selectors 是二进制的, 是由4位组成, 即 .
对于, 指 , 表示没有使用常量。
为了证明程序,每个指令的编码和位置需要唯一识别,即:
可以唯一识别待验证的程序,如下所示:
采用 编码程序的路径:
那么要如何有效检查执行了正确的程序呢,可以采用Plookup 协议, 即:
若指令路径包含在ROM 程序中,则表示执行了实际的程序。
证明执行路径的恒等关系
总而言之,可以采用如下的恒等关系定义程序:
其中 定义如下:
还需要进行如下的 Plookup 检查:
相关的定义如下:
最后,还需要检查 selectors
是二进制的,即:
关于状态机中的多项式,需要承诺: , , , 和 .
是 唯一可能预处理的不变多项式。
模块化设计
分而治之
若要添加更多运算到状态机,例如乘法,可以添加列到状态机中,但这会导致设计更加复杂,且难以处理,可以采用分而治之的策略:
- zkEVM 架构 由不同的状态机相互连接组成;
- 每个状态机去证明指定的任务;
- 不同状态机相关的列可以使用包含证明 (plookup)。
下面通过一个32位算术运算的状态机和主状态机的包含证明展示这个过程。
算术状态机
算术状态机可以对32位元素执行加,减,乘,除的运算,使用如下5个寄存器:
可以用下多项式定义约束关系:
注意还需要检查 在 处的值为32 位。
我们将设计一种检查这些操作的机制:
使用 来标记需要检查 寄存器 之间的约束关系。 , , , , 和 是不变的,即它们不依赖输入。
列的值需要承诺, 依赖 , 也需要承诺。
因此算术状态机多项式恒等关系为:
下图展示了算术状态机的架构图:
扩展主状态机
对于主状态机,可以将其扩展到5 个寄存器,添加一个arith
标记,用来连接算术状态机。 当arith
为1 的时候,需要检查算术化操作。整个设计如下图所示:
下图展示如何连接主状态机和算术状态机,当arith
为1的时候,需要确何算术表中的latch
为1。
因此,需要保证如下的包含关系:
注: 使用 用来表示它包寄存器 的值。
通过使用 Plookup作为总线,可以连接主状态机和其它具体的状态机:
由此可以设计一个模块化虚拟状态机,并通过零知识证明进行验证。
参考
https://docs.hermez.io/zkEVM/Basic-Concepts/introduction/
https://polygon.technology/solutions/polygon-zkevm
https://github.com/0xPolygonHermez/
https://ethresear.ch/t/proof-of-efficiency-a-new-consensus-mechanism-for-zk-rollups/11988
网友评论