7月20日,Ethereum 9? 创始人 Wanseob Lim在太坊技术论坛 ethresear.ch上正式发布了Zkopru,这是一种二层(Layer 2)私人交易扩容解决方案,同时使用了zk-SNARK和Optimistic rollup技术。 它能够以很低的成本支持ETH,ERC20,ERC721代币在二层网络内进行私人转移和原子交换。 此外,借助预付款功能,用户可以在交易确认之前从二层提取资产。 非常高兴分享以太坊二层隐私技术Zkopru的实现。 从去年11月开始,我和@barryWhiteHat开始构建此项目,如今结果如下。 Zkopru是什么? 它是一种二层(layer 2)私人交易解决方案。它使用了Optimistic rollup技术来管理区块。它使用了zk SNARK技术来创建私人交易 性能 在以太坊网络上实现每笔私人交易成本仅8000gas。当gas限制为1195万且区块时间为13.2秒时,最大TPS为105 亮点功能 支持ETH、ERC20、甚至ERC721支持私人原子互换。可以与私人订单匹配系统一起使用。Subtree rollup将成本削减为merkle树形的20分之1在区块最终确认之前进行快速提款使用大量存款和大量迁移,我们可以构建一个第2层间网络。 而且,最重要的是,它现在已经开始生产区块! 欢迎在我们的测试网上试用:https://zkopru.network 介绍 Zkopru是一种二层(Layer 2)私人交易扩容解决方案,同时使用了zk-SNARK和Optimistic rollup技术。 它能够以很低的成本支持ETH,ERC20,ERC721代币在二层网络内进行私人转移和原子交换。 此外,借助预付款功能,用户可以在交易确认之前从二层提取资产。 交易 zk交易可以接受多个UTXO作为其流入(inflow),并为其流出(outflow)创建新的UTXO。 因此,最重要的是验证流入和流出。 流入验证 Zkopru使用承诺消除器方案实现隐私。 这意味着zk交易花费了UTXO,而没有透露已使用了哪个票据。 取而代之的是,我们揭示了源自UTXO的无效符,但无法与其原始UTXO链接。 要使用UTXO,必须满足以下条件: UTXO证明 tx构建器会提交每个UTXO的Merkle证明以证明其存在。 为了进行有效的SNARK计算,UTXO树使用Poseidon作为其哈希函数。 所有权证明 只有所有者才可以使用UTXO。 在这种情况下,每个note都有一个公钥字段,即一个Babyjubjub点。 使用配对的私钥,所有者可以创建EdDSA签名以证明其所有权。 commitment证明 该回路应具有有关输入UTXO的详细信息,以计算流入的总和。 因此,所有者应提供详细信息,其Poseidon哈希值应等于Merkle证明和所有权证明的leef哈希值。 Nullifier证明 给定的Nullifier可以从输入的UTXO正确得出。 流出验证 zk交易可以创建三种类型的输出:UTXO,取款(Withdrawal)和迁移(Migration)。 如果zk事务创建了UTXO,则Zkopru将它们附加到UTXO树中。 创建提款输出时,Zkopru会将它们附加到提款树中。 最后,作为二层区块一部分的大规模迁移(mass migration),包括该区块每个zk交易的迁移输出。 因此,流出(outflow)应满足以下条件: 当输出为UTXO类型时,输出的公共哈希值等于在SNARK回路中计算出的值。如果输出的类型是提款或迁移,则应显示详细信息,因为它将正确数量的资产移至网络外部。 零和证明(zero-sum proof) 最后,zk交易应保证流入等于流出,包括手续费。 区块结构 区块头(header) 数据的前372个字节应为区块头(header)。 区块头包含以下数据: 区块体(block body) 区块主体由交易,大量存款和大规模迁移组成。 此外,区块头应包含来自区块体的正确信息。 如果区块头的值不正确,提出者将通过质询系统被削减。 交易 大量存款 大规模迁移(mass migration) 账户 Zkopru将提出了一种新的公共密钥结构。 注意此规范未来将进行更新。 Zkopru帐户管理着1层和2层密钥对。 首先,该帐户具有一个以随机方式生成的私钥的以太坊帐户。 这用于1层上的交互。 其次,Zkopru钱包从以太坊帐户的私钥中创建一个Babyjubjub私钥和公钥集。 此Babyjubjub密钥集用于二层的EdDSA和加密的备注字段。 UTXO 很快会提出一种新的UTXO规范 Zkopru使用Poseidon哈希计算leaf哈希: var intermediate_hash = poseidon(ether, pub_key.x, pub_key.y, salt) var result_hash = poseidon(intemediate_hash, token_address, erc20, nft) 接收者如何知道? zk交易可以为接收者包括81个字节的加密备注字段。 由于具有零知识特性,如果没有交互过程,接收者也无法知道怎么接收。 因此,为了保持非交互方式,我们可以在接受者的备注字段中放入一些加密的数据。
加密(encryption)
使用Diffie-Hellman密钥交换协议生成共享密钥。 为发送者生成共享密钥的详细步骤为: 1. 创建一个临时密钥及其同态隐藏值: ephemeral=epublic_ephemeral=ge 2. 将其临时密钥乘以接收者的公共密钥: recipient_pubkey=gashared_key=(ga)e 3. 准备对压缩数据进行加密: data = { salt // 16 byte tokenId, // 1 byte value, // 32 byte } 4.使用chacha20算法对数据进行加密,并使用临时公共密钥创建备忘录数据: ephemeral = random.new() public_ephemeral = generator.multiply(ephemeral) shared_key = recipient_jubjub.multiply(ephemeral) ciphertext = chacha20.encrypt(data, shared_key) memo = public_ephemeral + ciphertext
解密(decryption)
使用Diffie-Hellman密钥交换协议,接收者还使用公共临时密钥和私有密钥创建共享密钥。 1. 解析备注(memo)并获取共享密钥: public_ephemeral, ciphertext = parse(memo) shared_key = public_ephemeral.multiply(private_key) 2. 使用共享密钥解密ciphertext: decrypted = ciphertext.decrypt(shared_key) 3. 接收者使用解密结果尝试生成各种可能的UTXO。 这是因为加密的数据只有49个字节以最小化调用数据(calldata)的大小。 因此,接收者应尝试各种组合以检查交易是否包括被恢复的UTXO哈希。 如果未能在TX中找到已恢复的UTXO,则认为TX没有接收方的输出。 压缩数据 为了最大程度地减少调用数据(calldata),Zkopru将原始数据压缩为49字节数据。 首先,它摆脱了加密候选者的公钥,因为接收者将使用自己的公钥来推断出。 并且,它使用Token ID,该Token ID将支持的token地址和索引从0映射到255。然后,由于value可以是ether,erc20Amount或nftId,因此接收者针对这3种情况创建了三种类型的UTXO。 最后,如果在交易的输出列表中存在任何推断出的UTXO,则接收者成功接收了UTXO。 局限性 Zkopru不会强制回路(circuit)检查加密协议。因此,如果发送者未使用适当的共享密钥或数据,则接受者将不会收到备注。 原子交换 Zkopru以直接方式支持原子交换。如果A和B想要交换其资产,则它们会彼此创建备注(note)并将所需的备注公开在交易数据上。然后,协调者应对相反的交易进行配对或被削减。 例如,爱丽丝(Alice)想用天的50ETH交换鲍勃(Bob)的1000 DAI。 爱丽丝支出她的60 ETH note,并为自己创建了10 ETH note,并为鲍勃创建了50 ETH note。爱丽丝还计算她未来的1000 DAI note的哈希值,并将该哈希值暴露给她交易的swap字段。鲍勃则支出他的3000 DAI note,并为自己创建了2000 DAI note,为爱丽丝创建了1000 DAI note。鲍勃还计算他未来的50 ETH note的哈希值,并将该哈希值暴露给他的交易的swap字段。一旦协调者匹配了交易池中成对的交易集,它将把交易对包括在一个新区块中。如果一个区块仅包含其中一个,则协调者将被削减。 Zkopru正在使用一种简单版本的原子互换。然而如果你想要检验一种基于MPC的zk原子互换模型,你可以在这里看到详细信息。 Merkle树结构 UTXO树和withdrawal树中的备注(note)在下一个版本将有64深度。将只有一个单一的UTXO树和一个提取树。 Zkopru的树林由UTXO树,nullifier树和withdrawal树组成。 UTXO树是仅追加用法,包含UTXO的Merkle树。 通过提交包含Merkle证明,用户可以将UTXO用作交易的流入。 并将交易的输出结果附加回最新的UTXO树中。 另外,如果zk-transaction创建withdrawal输出,则Zkopru会将它们附加到最新的withdrawal树中。 将树的根被标记为已完成后,所有者可以通过证明所有权来提取资产。 然后,通过 commitment-nullifier方案,将用过的UTXO的nullifier标记为在nullifier树(唯一的稀疏Merkle树)中使用。 如果交易试图使用已经无效的叶子(leaf),它将变为无效(nullified),并且挑战者系统会大幅削减区块提议者。 Merkle树规范 {% hint style=“warning” %} UTXO树&withdrawal树在Burrito版本上有64深度 https://github.com/zkopru-network/zkopru/issues/35 {% endhint %} 如何管理UTXO树 单个UTXO树是用于成员资格证明的稀疏Merkle树。 它使用Poseidon哈希(SNARK中最便宜的哈希函数之一)生成zk SNARK证明以隐藏支出哈希及其路径。 要将新树叶(leaf)追加到UTXO树,协调者将执行以下步骤。 1.准备一个阵列。 2.协调者选择要包括的MassDeposits,并将MassDeposits中的每笔存款附加到阵列中。 3.二层交易生成新的UTXO。 将新生成的UTXO附加到阵列。 4.以区块大小为32对准备好的数组进行分割。5. 构造子树(sub-tree)并执行子树rollup。 假设UTXO树已被(2 ^ 31)个事项完全填充,系统将被填充的树进行存档并启动一个新树。 也允许使用归档树来引用交易的包含证明。 Nullifier树
每次转账,提款和迁移交易都支出带有包含证明的UTXO,并标记在nullifier树上使用的派生nullifier。因此,nullifier树是一个很大的稀疏Merkle树,它记录了深度为254的稀疏Merkle树中每一个用过的UTXO。因此,Zkopru使用最便宜的哈希函数keccak256作为nullifier树的哈希函数。 要更新nullifier树,协调者执行以下步骤: 选择交易(转移,取款,迁移)并从交易中收集所有nullifier。检查是否存在任何已使用的nullifier。将每个nullifier标记为已使用。在更新过程中,如果所有nullifier都没有更改nullifier树的根,请丢弃该交易,因为它会尝试进行双花。 就像UTXO树一样,Zkopru乐观地更新了nullifier树的根。如果有任何问题,我们可以通过生成防欺诈链上证明一个nullifier被使用了不止一次。要查看工作原理,请参阅RollUpChallenge.sol和SMT.sol。
提款树(withdrawal树)
与withdrawal树和UTXO树的唯一区别在于,withdrawal树使用keccak256作为哈希函数。 之所以使用keccak256,是因为Zkopru在智能合约上需要提取树的Merkle证明,而在SNARK回路中则需要UTXO树的Merkle证明。 在树的根定型后,withdrawal树中的叶子(leaves)在1层智能合约中便是可以提取的。 要更新提款树,协调者执行以下步骤: 收集已选择交易的所有withdrawal叶子。拆分出区块大小为32的withdrawal数组。构造子树(subtree)并执行子树rollup。 大量存款(mass deposit)
当用户将资产存入Zkropu时会发生什么: Zkopru合约将给定数量的资产从用户帐户转移到自身。验证note是否带有给定信息的一个有效哈希。将note合并到MassDeposit []列表的最后一项。 什么是MassDeposit? MassDeposit是用于rollup证明的单个mergedLeaves bytes32值。 可在此处检查什么是rollup证明mergedLeaves。 如果协调员提出一个包含MassDeposits的区块,则该区块会将MassDeposit中的所有note追加到其UTXO Merkle树。 协调员如何处理MassDeposits? 协调员只能包括不再更改的“已承诺(commited)” MassDeposit。 为了包含MassDeposit,协调员将监视Zkopru合约中的存款事件。 MassDeposit什么时候变成“已承诺”? 尽快将存款推到二层网络。 因此,当协调员提出每个新区块时,它将冻结最新的MassDeposit。 协调员可以包含多个MassDeposit吗? 是的,可以在最大挑战成本范围内一次包含多个MassDeposit。
大规模迁移(mass migration)
大规模迁移的基本思想非常简单。 虽然1层合约上的存款交易创建了MassDeposit对象,但是交易的“迁移”类型输出可以创建MassMigration,该MassMigration为其目的地网络构造MassDeposit。 交易可以具有UTXO,迁移(migration)或取款(withdrawal)类型的输出。 在Zkopru中,要进行迁移,就会涉及到源网络和目标网络。 一旦完成源网络上的大规模迁移(相关代码请查看),就可以执行源网络上的migrationTo函数。 该函数可以移动资产(包括Ether,ERC20和ERC721),同时为目标网络创建MassDeposit对象。 因此,目标网络应实现acceptMigration函数。 更多信息在这里 rollup之间的迁移标准将通过EIP进行标准化。
即时取款(instant withdrawal)
在Zkopru中,提取者可以通过设置每个提取note的即时提取费用来请求即时提取。 然后,任何人都可以提前为未完成的提款付款并收取费用。 为了请求即时提款,所有者为她的note生成ECDSA签名并进行广播。 拥有足够资产且可支付的任何人都可以使用签名提前支付取款。 一旦Zkopru成功包含该交易,智能合约便将提款note的所有权转移给付款人。 最后,预付款人在完成交易后将其提取。 我们可以有一个分散的公开市场来收取即时取款费。 要跟进最新进展,请订阅此github:?https://github.com/zkopru-network/zkopru/issues/333 结论 根据此规范,我们已成功使用Circom,Solidity,Typescript等构建了测试网。 使用zk-SNARK和Optimistic rollup的以太坊二层私人交易扩展解决方案。 -zkopru-network / zkopru 首先,我们可以实现了一种每笔zk交易可承受的gas成本。 平均值约为8800gas,当gas限制为1,150,000且区块时间为13.2秒时,理论上最大的TPS为105。 在Zkopru中,交易数据消耗约534个字节。 由于证明数据为256字节,因此如果将来应用证明聚合,我们可以减少大约两倍的交易成本。 否则,每个区块提出和最终确定的存储成本分别约为168k gas和55k gas。 当我们包括350笔交易时,此成本约为区块生成成本的6.7%。 此外,我们可以利用Optimistic Rollup的灵活性来实现许多功能。 首先,Zkopru通过多个SNARK验证密钥支持各种类型的交易。 您甚至可以使用1个输入和4个输出,或4个输入和1个输出完成一笔交易。 通过Optimistic Rollup的灵活性,使其支持多种类型的交易非常简单。 其次,Zkopru实现了精确类型的挑战案例。 这意味着,如果区块的第n个交易有问题,则质询仅检查该特定交易。 另外,Zkopru需要您在计算机上运行节点,这一点也很重要。 因此,SNARK高效率性和轻节点是软件实现要考虑的重要因素。 因此,我们将使用Typescript和NodeJS构建该项目,以供将来在基于本机的移动应用程序中使用。 预计轻型节点将仅消耗约50?100 MB的存储空间用于树管理。 总结一下工作,我们希望Zkopru可以用于以太坊的隐私交易层。 它既快速,便宜,又可移植到升级版本。 欢迎感兴趣的人为该项目进行捐款。 您可以通过Zkopru的文档页面(https://docs.zkopru.network)查看一个已经组织过的版本。 感谢你阅读本文。 参考文献: Ethereum 9 3/4: Optimistic rollup for zk-Mimblewimble1BarryWhitehat’s zk-rollup1John Adler’s Minimal Viable Merged Consensus1Plasma-group’s Optimistic RollupBatch Deposits for [op/zk] rollup / mixers / MACIMass migration to prevent user lockin in rollup —- 编译者/作者:Kyle 玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。 |
一文读懂以太坊最新二层隐私技术Zkopru,实现ETH、ERC20和ERC721代币标准互通
2020-07-20 Kyle 来源:区块链网络
LOADING...