零知识证明可以在不泄露具体信息的情况下向其他人证明自己掌握该信息,这听起来非常适合去中心化应用。在这个教程中,我们将利用zksnark来实现一个具体的NodeJS零知识证明应用:渔船无需透露自己的具体位置,就可以向监管机构证明自己处于划定的合法捕捞区内 —— 我们的主要武器是snarkjs和circom。
用自己熟悉的语言学习以太坊DApp开发:Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart
1、需求分析
设计零知识证明应用方案的第一步是要将具体的问题转换为一个电路。我们要证明渔船处于合法捕捞区内,这个问题中存在以下变量:
- 合法捕捞区的范围,可以用该区域的经度/维度的最大值和最小值来表示渔船的位置,用渔船的经度和维度来表示
容易得到如下的输入输出映射:
+--------------+
渔船经度/维度 ->| |
| |
捕捞区经度最大/最小值 ->| 电路 |-> 在/不在合法捕捞区
| |
捕捞区纬度最大/最小值 ->| |
+--------------+
2、circom电路实现
据此,我们可以得到如下的circom电路定义:
其中:
- latitudeRange:电路输入,表示合法捕捞区域的纬度的最小值和最大值,数组
- longitudeRange:电路输入,表示合法捕捞区域的经度的最小值和最大值,数组
- fishingLocation:电路输入,表示渔船的经度和维度,数组
- out:电路输出,1表示渔船在合法捕捞区,0表示渔船不在合法捕捞区
由于我们要隐藏渔船的具体位置,因此在上面的circom电路中,你可以看到fishingLocation被定义为private。
3、circom电路编译
如果还没有安装circom的话,使用如下命令全局安装circom:
npm install -g circom
注意:推荐使用node 12,因为内置了原生的大数计算,效率提升10倍!
使用如下命令编译电路文件InRange.circom,输出结果命名为InRange.json:
circom InRange.circom -o InRange.json
4、zksnark的可信设置
在使用zksnark之前,需要一个可信设置,而且该可信设置依赖于具体的电路,例如我们编译得到的InRange.json。
使用snarkjs来创建这个可信设置,同样,如果需要安装的话,使用如下命令:
npm install -g snarkjs
现在我们利用渔业监控电路进行可信设置:
snarkjs setup -c InRange.json
上面的命令将会在当前目录创建两个文件:proving_key.json和verification_key.json。其中proving_key.json用于证明你的输入是有效的(满足电路约束),而verification_key.json用来验证别人提供的证据。
5、计算ziksarnk电路信号的见证(witness)
在我们创建提供给其他人的证据之前,需要先计算出电路中所有信号(包括输入信号和中间信号)
的见证。为此我们需要创建一个输入文件input.json,其中包含所有输入(公开输入和私有输入)的值,然后利用这个输入文件计算得到见证文件witness.json,这两个文件都不会公开。
下面是我们的渔业监控电路的输入文件示例:
{
"latitudeRange": [ 20, 21],
"longitudeRange": [ 176, 190],
"fishingLocation": [ 20, 180]
}
使用sparkjs来计算得出见证文件witness.json:
snarkjs calculatewitness -c InRange.json
6、创建zksnark证据
有了witness.json,我们就可以创建提供给其他人的证据了:
snarkjs proof
上面的命令将在当前目录生成proof.json和公开文件public.json,publc.json实际上就是witness.json文件内容的一个子集,其中仅包含电路中可公开信号的值。
现在目录里的文件如下图所示:
7、校验zksnark证据
现在你(渔船船长)可以把verification_key.json、proof.json和public.json提供给监管机构了,监管方使用如下命令即可验证你的船的确在合法捕捞区内,但却不知道你的具体位置:
snarkjs verify
GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD!
原文链接:零知识证明实战渔业监 — 汇智网