通过 zk-SNARK 与 Optimistic Rollup 技术的结合,Zkopru 可实现 ETH、ERC20s 和 ERC721s 多种以太坊代币的快速、廉价和隐私的交易,并实现即时取款和隐私原子互换等功能。

撰文:殷耀平

以太坊 Layer2 隐私扩容新方案 Zkopru 问世

7 月 20 日,Ethereum 9¾ 创始人 Wanseob Lim 在太坊技术论坛 ethresear.ch 上发布了一份新的以太坊扩容方案「Zkopru」的技术实现说明。

Ethereum 9¾ 是一种概念证明系统,使用 Mimblewimble 以及零知识证明等隐私技术来隐藏以太坊代币交易。

据 Wanseob Lim 介绍,这是一个结合了 zk-SNARK 和 Optimistic Rollup 来实现隐私交易的 Layer2 扩容解决方案,该方案支持在二层网络中以低成本实现 ETH,ERC20,ERC721 之间的隐私转移和隐私原子交换,并实现了诸多其他亮点功能。

Wanseob Lim 称,该方案是由他和化名为「barry WhiteHat」的以太坊开发者共同完成,他们从 2019 年 11 月开始构建此方案,目前 Zkopru 已发布测试网(Artic Roll),代码已在 github 开源。

「barry WhiteHat」是以太坊社区最活跃的开发者和研究者之一,ZK Rollup 的扩容方案正是由 barry WhiteHat 在 2018 年下半年最先提出。

链闻查询该项目路线图发现,Zkopru 计划分为 Arctic roll (testnet)、Burrito (testnet+mainnet)、Grilled burrito (testnet+mainnet)、California roll (mainnet)、Dragon roll (mainnet)五个阶段进行迭代,github 上的开发进度显示,目前第一阶段(Artic Roll)的开发工作已完成大部分。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

Zkopru 方案一经推出,便吸引了众多以太坊开发者的关注,以太坊创始人 Vitalik Buterin 第一时间表达了对该项目问世的祝贺,认为是一项「很棒」的工作,并在推特上转发了该项目的介绍文章。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

下面我们一起了解一下 Zkopru 扩容方案的主要思路和设计亮点。

什么是 Zkopru ?

Zkopru 的全称是 zk-Optimistic-Rollup,是一个基于 zk-SNARK 和 Optimistic Rollup 的以太坊二层隐私扩容解决方案。可支持第二层网络中 ETH、ERC20、ERC721 各类代币之间的隐私转账和隐私原子交换,并且费用很低。

「Zkopru」方案使用 Optimistic Rollup 来管理区块,使用 zk-SNARK 来构建隐私交易。

了解过以太坊 Layer2 扩容现状的都知道,目前最当红的扩容主力便是基于 Rollup 技术系列扩容方案,最主流的是两个分支 ZK Rollup 和 Optimistic Rollup 。

简单理解,「ZK Rollup」方案是利用 Rollup 技术进行交易压缩,并利用 zk-SNARK (零知识证明)技术实现交易打包和验证,以实现在减少交易成本的同时确保安全性。

「Optimistic Rollup 」方案吸收了 ZK Rollup 方案对于数据可用性的优势,但去除了零知识证明部分,而是沿用了 Plasma 的欺诈证明机制。所以在该方案中,不像 ZK Rollup 方案通过 SNARK 处理后再将数据聚合到链上,而是默认「乐观(Optimistic)」相信节点会将最新且准确的数据发布到链上,否则当「验证者」发现有问题时,节点会受到相应惩罚。

了解更多关于 Rollup 的知识可以参考链闻文章「以太坊扩容最热门主力方案 Rollup 学习指南」。

而最新问世的「Zkopru」方案则是对 zk-SNARK 和 Optimistic Rollup 的结合,相当于是在 Optimistic Rollup 方案中,又加入了零知识证明的技术部分。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

Zkopru 扩容方案有何特点 ?

据 Wanseob Lim 介绍,Zkopru 方案能将每笔 zk 交易的 gas 费控制在可承受范围,并实现交易性能提升,使得:

  • 以太坊隐私交易平均成本为每笔交易 8000gas。
  • 理论上最大 TPS 为 105 (当 gas 上限为 11950000,出块时间为 13.2 秒时)

此外,Zkopru 中,交易数据消耗大约 534 字节,由于证明数据(proof data)有 256 字节,未来如果使用证明聚合( proof aggregation ),还可以将交易成本降低 50% 左右。

此外,Zkopru 方案还能实现以下功能。

1)支持 ETH、ERC20 甚至是 ERC721 资产。
2)支持隐私原子交换(private atomic swap),可以与隐私订单撮合系统一起使用。
3)运用 Subtree Rollup 将默克树(Merkle Tree)的更新挑战成本缩减至原来的 1/ 20 。
4)即时取款(Instant withdrawal)功能实现,在区块最终性(block finalization)达成前,用户可以即时取款。
5)利用批量存储和批量转移,可以构建一个内部二层网络(inter-layer-2 network)。

Zkopru 方案实现:如何证明交易真实性 ?

我们可以简单了解一下 Zkopru 方案是如何利用 zk-SNARK 技术完成交易验证的。

Zkopru 方案认为,由于每个零知识证明事务(zk-transaction)都会接受若干个 UTXOs (Unspent Transaction Outputs,未花费交易)作为其输入(inflow),并为其输出(outflow)创建新的 UTXO。因此,最重要的,就是验证输入和输出(inflow 和 outflow),从而完成对交易真实性的验证。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

首先是输入验证(Inflow Validation)

Zkopru 使用 Commitment-nullifier (Zcash 使用的隐私交易方案)来实现隐私保护。在该方案中,每个 zk 事务会使用 UTXO,但不会显示使用了哪个 note,虽然会展示从 UTXO 派生出来的 nullifier (清零器),但仅仅看到 nullifier 不可能与原始的 UTXO 建立起联系,从而可以实现隐私保护。

链闻注:在 Zcash 的隐私交易方案中。每笔转账都会用 note (有点类似支票,只有被赋予权限的人才能取款)来表示,内容包括转账的金额和一个随机数。note 有两个外在的表现形式:一个是 Commitment,一个是 Nullifier。Commitment 代表一次金额转入,Nullifier 代表一次消费。对于每个 note,Commitment 和 Nullifier 都是唯一的。因为 Commitment 和 Nullifier 是通过不同的 Hash 函数生成的结果,即使这两个数据公开,其他人也无法推断出 Commitment 和 Nullifier 之间存在联系。也就是说,提供一个 Commitment,能说明进行了一笔转账(具体信息其他人未知)。能提供对应的 Nullifier,就能消费。了解更多请参见链闻 文章

要花费 UTXOs 时,必须满足以下条件(就是完成一系列验证):

UTXO 成员证明(UTXO membership proof):交易构建器(tx Builder)提交每个 UTXO 的 Merkle 证明来证明其存在。为实现有效的 SNARK 计算,UTXO 树使用 Poseidon 作为其哈希函数。

所有权证明(Ownership proof):只有所有者才能花费 UTXO,每个 note 都会有一个公钥字段,所有者通过使用配对的私钥创建 EdDSA 签名来证明其所有权。

承诺证明(Commitment proof):整个环路(circuit)需获取有关 UTXOs 输入的详细信息,从而计算输入量的总和。因此,所有者应该提供详细信息,其 Poseidon 哈希值应该等于 Merkle 证明和所有权证明的叶节点哈希值(leaf hash)。

无效证明(Nullifier proof):给定的 nullifiers 应该从 UTXOs 输入中正确派生。

其次是输出验证(Outflow Validation)

每个 zk 事务可创建三种类型的输出:UTXO、取款(Withdrawal)和转移(Migration)。

如果 zk 事务创建 UTXO 输出,Zkopru 会追加到 UTXO 树中。如果 zk 事务创建取款(Withdrawal)输出,Zkopru 会追加到 Withdrawal 树中。最后,批量转移(mass migration)(Layer2 区块链的一部分)是由区块中的每个 zk 事务的转移输出所组成。

因此,UTXO 的输出应满足以下条件:

当输出是 UTXO 类型时,输出的公共哈希值必须与 SNARK 环路中计算所得值相等。
当输出是取款或转移(withdrawal 或 migration)类型时,应该显示详细信息,因为该输出需要将正确数量的资产转移至网络外部。

零和证明(Zero-sum proof)

最后,zk 事务应该保证输入等于输出,包括费用在内。

Zkopru 功能实现:原子交换 Atomic swap 功能

目前,Zkopru 在以一种很简单的方式支持原子交换(Atomic swap)。

如果 A 和 B 想交换他们的资产,他们会为彼此创建 notes,并在交易数据中公开所需的 note。然后,协调器(coordinator)应该配对相反的事务(opposite transaction),或者被惩罚。

例如,Alice 想用她的 50 个 ETH 换 Bob 的 1000 个 DAI。
Alice 花费自己的一个 60ETH 的 note,为自己创建 10ETH 的 note,同时为 Bob 创建 50ETH 的 note。
此外 Alice 计算出自己未来得到的 1000 DAI 的 note 的哈希值,并将该哈希值在她的交易事务中通过 swap 字段公开。
同样,Bob 花费自己的一个 3000 DAI 的 note,为自己创建 2000 DAI 的 note,为 Alice 创建 1000 DAI 的 note。
Bob 也计算出他未来的 50 ETH 的 note 的哈希值,并将该哈希值在他的交易事务中通过 swap 字段公开。
一旦协调器在交易池中匹配了成对事务集,就会将该对事务打包到一个新区块中。
如果一个区块中纳入了不成对的事务,协调器会被惩罚。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

Zkopru 功能实现:即时取款(Instant withdrawal)功能

Zkopru 中,取款人可以请求即时取款,取款人可以为每个取款 note 设置一定的取款费用,然后,任何人都可以提前支付这笔尚未最终完成(unfinalized)的取款并获得该取款费用。

具体而言,为请求即时取款,所有者需要为她的 note 生成一个 ECDSA 签名并进行广播。任何有足够资产支付的人都可以使用该签名提前支付这笔取款。一旦 Zkopru 成功打包了该交易,智能合约会将该取款 note 的所有权转移给预付款人。最后,预付款人可以在区块完成最终确定(finalization)后取款。

通过该功能,Zkopru 团队认为,可以为即时取款建立一个去中心化的公开市场。

Zkopru 方案的 Merkle 树结构

Zkopru 的当前版本中,UTXO 树和 withdrawal 树的最长深度将为 31,Zkopru 团队表示下个版本(即 Burrito 版本)中最长深度将变为 64,并且只有一个 UTXO 树和一个 withdrawal 树。

Zkopru 方案由 UTXO 树,nullifier 树和 withdrawal 树所组成。

UTXO 树会追加(append)包含 UTXOs 的 Merkle 树,用户可以通过提交 Merkle 证明将 UTXOs 用作事务的输入,并将事务的输出结果追加至最新的 UTXO 树中。

同样,如果 zk 事务创建了 withdrawal 输出,Zkopru 会将其追加到最新的 withdrawal tree 树中。一旦树根被标记为终结(finalized),所有者就可以来提取资产(给出所有权证明)。

最后,通过 commitment-nullifier 隐私交易方案,已使用过的 UTXO 的 nullifier 会在 nullifier 树中被标记为「已使用」。

用过的 UTXO 的清零器被标记为在 nullifier 树中使用,nullifier 树是唯一的稀疏 Merkle 树。如果有事务试图使用一个已被使用的 nullifier,该事务会自动失效,并且区块提议者会被质询系统惩罚。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

Zkopru 方案中 Merkle 树的详细规格。
以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

UTXO 树(UTXO Trees)

单个 UTXO 树是用于成员证明(membership proof)的稀疏 Merkle 树,它使用 Poseidon 哈希(SNARK 中最便宜的哈希函数之一)生成 zk SNARK 证明来隐藏花费哈希及其路径。

为了更新 UTXO 树,协调器(coordinator)需执行以下步骤。

1、准备好数组(array)。
2、协调器选择需要并入的 MassDeposits,并将 MassDeposits 中每笔存款都追加到数组中。
3、Layer2 事务生成新的 UTXOs,将新生成的 UTXOs 追加到数组中。
4、将准备好的数组拆分成大小为 32 的块。
5、构造子树(Subtree)并执行子树汇总(Subtree Rollup)。

假设 UTXO 树完被全填满了(包含了 2^31 项),系统会将填满的树归档并开始一个新树,已存档的树也可以作为交易的包含证明被引用。

Zkopru 会乐观地更新树根,且只在发现挑战(问题)时进行验证。Zkopru 会使用 Subtree rollup (子树汇总)的方法生成链上欺诈证明。Subtree rollup 会追加固定大小的 subtree,而非逐个追加交易项。与单纯的 Rollup 相比,Subtree Rollup 显著降低了大约 20 倍的 gas 成本。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

Nullifier 树

每个转账(transfer)、取款(withdrawal)和转移(migration)事务都通过包含证明(inclusion proofs)来花费 UTXOs,并标记在 nullifiers 树上。所以 nullifiers 树是一个非常大的稀疏 Merkle 树,要记录稀疏 Merkle 树(254 深度)中每个已花费的 UTXO。因此,Zkopru 使用 keccak256 (最便宜的哈希函数)作为 nullifier 树的哈希函数。

为了更新 nulleizer 树,协调器(coordinator)需执行以下步骤。

1、选择事务(转账、取款、转移),并从事务中收集所有 nullifiers 项。
2、检查是否存在任何已经使用的 nullifiers 项。
3、将每个 nullifier 项标记为已使用。更新过程中,如果有 nullifier 不更改 nullizer 树根,立刻丢弃该事务,因为它尝试进行双花(double-spending)。

就像 UTXO 树一样,Zkopru 会乐观地更新 nullifier 树的根。若有任何问题,可以通过在链上生成欺诈证明来证明一个 nullifier 使用了不止一次。

Withdrawal 树

Withdrawal 树和 UTXO 树的唯一区别是,提取树使用 keccak256 作为哈希函数。原因是 Zkopru 在智能合约中需要 withdrawal 树的 Merkle 证明,但在 SNARK 环路中又需要 UTXO 树的 Merkle 证明。

要更新 Withdrawal 树,协调器需执行以下步骤。

1、收集所选交易的每个取款项(every withdrawal leaf)。
2、将所搜集的取款数组拆分成大小为 32 的块。
3、构造子树并执行子树汇总 (Subtree rollup)。

Zkopru 方案实现:Zkopru 中的区块结构(Block structure)

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

区块头(Header)

前 372 个字节的数据是区块头(block header),区块头包含以下数据:

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

区块主体(Body)

区块主体包括交易( transactions)、批量存款(mass deposits)和批量转移(mass migrations)。此外,区块头应该包含来自区块主体的正确信息。如果区块头没有包含正确的值,提案人会被质询系统(the challenge system)所惩罚。

交易(Transactions)

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

批量存款(Mass deposits)

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

批量转移(Mass migrations)

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

Account (帐户)

Zkopru 计划创建一种新的公钥结构(public key structure)。

每个 Zkopru 帐户将同时管理 Layer1 和 Layer2 的密钥对(key pairs)。

首先,该帐户会有一个随机生成私钥的以太坊帐户,用于与 Layer1 交互。其次,Zkopru 钱包会根据该以太坊账户的私钥创建一个 Babyjubjub 私钥和公钥集,用于 Layer2 的 EdDSA 签名和加密 memo 字段。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

UTXO

Zkopru 还将提出一种新的 UTXO 标准。

以太坊扩容赛道又出新方案 Zkopru:zk-SNARK 与 Optimistic Rollup 的结合将如何实现隐私扩容?

然后 Zkopru 再用 Poseidon 哈希计算叶节点哈希(leaf hash)。