在本教程里将指导您创建第一个零知识 zkSnark电路。它将介绍各种编写电路的技术,并向您展示如何创建证明并在以太坊[1]上进行链外和链上验证。
需要在电脑中安装Node.js
,Node.js 的最新的稳定版本(或8.12.0)可以正常工作。不过,如果您安装了当前的最新版本的Node.js(10.12.0),将会看到显着的性能提升。这是因为最新版本本身包含大数库(Big Integer Libraries)。 snarkjs
库会利用这些特性(如果可用的话),从而将性能提高10倍(!)。
运行:
npm install -g circom
npm install -g snarkjs
让我们创建一个电路,去证明你能够因式分解一个数字!
1.创建一个 factor
目录,教程里的所有文件都将放在这个下面
mkdir factor
cd factor
在真实的电路中,您可能需要创建一个 git
仓库,其中包含circuits
目录和一个包含所有测试的test
目录,以及用于构建所有电路的脚本。
1.使用下面的内容创建一个 circuit.circom
文件:
template Multiplier() {
signal private input a;
signal private input b;
signal output c;
c <== a*b;
}
component main = Multiplier();
这个电路有2个 private 输入信号,名为 a
和 b
,还有一个输出 c
.
电路做的事情是让强制信号 c
为 a*b
的值。
在声明 Multiplier
模板之后, 我们使用名为main
的组件实例化它。
注意:编译电路时,必须始终有一个名为main
的组件。
现在,我们准备编译电路。运行以下命令:
circom circuit.circom -r circuit.r1cs
将电路编译为名为circuit.rlcs
的文件
现在电路已经编译好了,我们将继续使用snarkjs
。
我们随时可以通过输入
snarkjs --help
来访问snarkjs
的帮助
要显示电路的信息,可以运行:
> snarkjs info -r circuit.r1cs
# Wires: 4
# Constraints: 1
# Private Inputs: 2
# Public Inputs: 0
# Outputs: 1
还可以通过运行以下命令来打印电路的约束:
snarkjs printconstraints -r circuit.r1cs
现在为电路运行启动配置:
snarkjs setup
默认 snarkjs
将寻找和使用 circuit.r1cs
. 我们也可以用 -r <circuit r1csFile>
来指定一个电路文件。
setup 将输出2 个文件: proving_key.json
and verification_key.json
在创建任何证明之前,我们需要计算与(所有)电路约束匹配的所有电路信号。
snarkjs
会帮我们计算这些。我们需要提供一个包含输入的文件,它将执行电路并计算所有中间信号和输出。这组信号就是“见证”。
零知识证明证明你知道一组与所有约束匹配的信号(见证),但不透露任何信号(公共输入和输出除外)。
例如,想像一下,你想证明自己能够因式分解33,这意味着你知道两个数 a
和 b
,将它们相乘为 33。
因此,您想证明自己知道3和11。(当然,你可以始终使用1 和 数字本身作为 a
和 b
,我们稍后将处理此问题。)
让我们创建一个input.json
文件:
{"a": 3, "b": 11}
现在计算见证:
snarkjs calculatewitness
这时会生成包含所有信号的见证文件witness.json
, 可以打开看一看。
译者注,如果遇到提示 :Error: ENOENT: no such file or directory, open 'circuit.wasm' ERROR: Error: ENOENT: no such file or directory, open 'circuit.wasm' 就用
circom circuit.circom -w circuit.wasm
生成一个 circuit.wasm 在执行一次见证。
现在我们已经生成了见证信息,我们可以创建证明了。
snarkjs proof
这个命令默认会使用 prooving_key.json
和 witness.json
文件去生成 proof.json
和 public.json
proof.json
文件包好了实际的证明。而 public.json
文件将仅包含公开的输入和输出值。
验证证明运行命令:
> snarkjs verify
OK
这个命令会使用 verification_key.json
, proof.json
和 public.json
来验证有效性。
这里我们证明我们知道一个见证,见证着公共输入和输出与public.json
文件中的输入和输出匹配。
如果验证通过会输出OK
, 否则会显示 INVALID
。
snarkjs generateverifier
这个命令将使用到 verification_key.json
并生成一个 solidity[2] 代码文件: verifier.sol
。
可以复制verifier.sol
代码到 remix[3] 进行部署。
verifier.sol
包含两个合约:Pairings 和 Verifier, 你只需要部署Verifier 合约。
可以使用Rinkeby,Kovan或Ropsten等测试网,也可以使用Javascript VM
,也许在某些浏览器中,验证会花很长时间,并且可能会挂起页面,请知晓。
上面生成的 Verifier 合约有一个 view 视图函数[4] verifyProof
, 如果证明和输入正确,这个函数会返回 true .
The verifier contract deployed in the last step has a view
function called verifyProof
.
为了方便调用,可以使用snarkjs通过输入以下命令来生成调用的参数:
snarkjs generatecall
这命令的输出复制到 Remix 中的 verifyProof
方法的 parameters 字段中,调用 verifyProof
,
如果一切正常,方法应该返回 true
。
如果仅更改参数中的任何位,则可以检查结果返回 false 。
签名提到了一个漏洞,现在来通过添加一些额外的约束修复电路。
我们约束不接受 1 作为任何一个值,这里使用 0 不可逆的特性,即(a-1)
不可逆。
如果 a 是 1 则 (a-1)*inv = 1
是不可能成立的, 通过 1/(a-1)
来计算 inv 。
修改电路:template Multiplier() { signal private input a; signal private input b; signal output c; signal inva; signal invb; inva <-- 1/(a-1); (a-1)*inva === 1; invb <-- 1/(b-1); (b-1)*invb === 1; c <== a*b; } component main = Multiplier();
circom 语言的一个好处是可以把<==
分为两个动作 : <--
和 ===
。
<--
和 -->
操作符运算符只为信号分配一个值,而不创建任何约束。
===
操作符添加约束而不分配值。
该电路还有另一个问题,那就是该运算可以在 Zr 中工作,因此我们还必须保证乘法不会溢出。这可以通过二进制化输入并检查范围来修复,让我们留着在之后的教程里介绍。
阅读我们的 代码库[5] 了解更多 circom 的特性。
我们写好了一些基本的电路,如:binaritzations、comparators, eddsa, hashes, merkle trees 等等,可以在circomlib[6] 找到,还有更多电路在开发中。
对于开发人员而言,没有什么比使用buggy 编译器更糟糕的了。现在依旧是编译器的早期阶段,因此存在许多错误,并且需要完成许多工作。
如有任何问题,请与我们联系。哪怕是一小段修复 bug 的代码。
最后,享受零知识证明[7]!
原文链接:https://iden3.io/blog/circom-and-snarkjs-tutorial2.html
本译文得到 登链社区 及 Cell Network 赞助支持。
[1]
以太坊: https://learnblockchain.cn/categories/ethereum/
[2]
solidity: https://learnblockchain.cn/docs/solidity/
[3]
remix: https://learnblockchain.cn/tags/Remix
[4]
view 视图函数: https://learnblockchain.cn/docs/solidity/contracts/functions.html?#view
[5]
代码库: https://github.com/iden3/circom
[6]
circomlib: https://github.com/iden3/circomlib
[7]
零知识证明: https://learnblockchain.cn/categories/zero
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有