本文是 zkMove 系列的第二篇文章,我们以 zkMove 最典型的使用场景 zk-rollup 为例来说明其工作原理。
在介绍 zkMove 如何工作之前,我们先来回顾一下 zk-rollup 的工作原理。zk-rollup 是一种 layer2 扩展方案。所谓 layer2,就是将资金存储到主链上的智能合约里作为抵押,把交易放到主链之外执行,好像主链上面又生出了一层。二层方案里提出较早的是状态通道和 Plasma 侧链,但是这两种方案都存在“数据可用性”问题,就是交易记录只保存在链下,出现争端时如果参与者没有及时提供正确的交易数据,交易的安全性就无法保证。
zk-rollup 不用于状态通道和 Plasma,它可以批量“打包”交易,并将“打包”后的交易数据连同一个 SNARK 零知识证明发布到链上。交易的合法性由链上智能合约通过零知识证明来验证,负责“打包”的操作者不可能发布恶意或无效的交易。这样就能做到一次性执行一批链下交易,但是在链上只执行一个交易,从而实现“计算”从链上到链下的转移。
zk-rollup 目前最大的问题是通用性或者说“可编程性”较差。大多数 zk-rollup 扩容方案每部署一个合约都需要单独编写电路(circuit),而且只支持单个应用场景。为了提升 zk-rollup 的可编程性,零知识证明虚拟机被提了出来。
zkMove (www.zkmove.net)的核心就是一个零知识证明虚拟机,它将 Move 编程语言和零知识证明技术结合在一起,使得部署 Move 智能合约时可以自动生成电路,执行合约时生成零知识证明。下面我们就来看一下它的工作原理。
从分布式计算的角度,区块链是一个复制状态机(replicated state machine),其中 S 表示当前的账户状态,当交易 txn 被执行后账户状态变更为 S':
为了将计算从链上转移到链下,需要将账户状态 S 搬到链下,用默克尔树来维护,用户交易的签名校验、执行都在链下进行。只有当用户需要时才将其账户状态同步到链上,否则仅将状态的默克尔树根 R 上链,状态的正确性通过参与交易的账户的 merkle_proof 来保证。这一过程用复制状态机可以表示为:
为了将计算从链上 “Move” 到链下,还需要将用户交易按提交顺序在链下执行,并生成零知识证明 zk proof 和压缩编码后的操作记录,然后将运行结果和 zk proof 提交到链上。链上的智能合约对 zk proof 进行验证,验证通过则说明用户的交易确实被正确执行了,然后记录最新的默克尔树根 R'。压缩后的操作记录作为智能合约的参数上链,作为用户交易记录。下面这幅图描述了zkMove 典型的工作流程:
如图所示,zkMove 的核心是一个字节码虚拟机,bytecode 满足 Move 字节码规范。 witness 是交易的输入,它通常包含参与交易的 accounts、merkle_proof 和执行交易前的状态树树根 R;public data 是交易的输出,它通常包含执行交易后新生成的状态树树根 R' 和压缩后的用户操作记录。zkMove 采用了只需要一次可信初始设置的PLONK 零知识证明算法,智能合约在发布的时候生成 proving key 和 verification key。
以上我们以 zk-rollup 作为使用场景简单描述了 zkMove 的工作原理。后面我会进一步介绍 zkMove 虚拟机的具体实现,有兴趣的朋友欢迎关注我的同名公众号“宇宙流拾荒者”。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!