Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >零知识证明 circom 及 snarkjs 入门教程[译]

零知识证明 circom 及 snarkjs 入门教程[译]

作者头像
Tiny熊
发布于 2020-06-04 08:17:21
发布于 2020-06-04 08:17:21
3.3K21
代码可运行
举报
运行总次数:1
代码可运行

在本教程里将指导您创建第一个零知识 zkSnark电路。它将介绍各种编写电路的技术,并向您展示如何创建证明并在以太坊[1]上进行链外和链上验证。

1. 安装工具

1.1 先决条件

需要在电脑中安装Node.js,Node.js 的最新的稳定版本(或8.12.0)可以正常工作。不过,如果您安装了当前的最新版本的Node.js(10.12.0),将会看到显着的性能提升。这是因为最新版本本身包含大数库(Big Integer Libraries)。 snarkjs 库会利用这些特性(如果可用的话),从而将性能提高10倍(!)。

1.2 安装 circom 和 snarkjs

运行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install -g circom
npm install -g snarkjs

2. 使用 circuit

让我们创建一个电路,去证明你能够因式分解一个数字

2.1 创建一个电路目录

1.创建一个 factor 目录,教程里的所有文件都将放在这个下面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mkdir factor
cd factor

在真实的电路中,您可能需要创建一个 git 仓库,其中包含circuits目录和一个包含所有测试的test目录,以及用于构建所有电路的脚本。

1.使用下面的内容创建一个 circuit.circom 文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template Multiplier() {
   signal private input a;
   signal private input b;
   signal output c;
   c <== a*b;
}

component main = Multiplier();

这个电路有2个 private 输入信号,名为 ab ,还有一个输出 c.

电路做的事情是让强制信号 ca*b 的值。

在声明 Multiplier 模板之后, 我们使用名为main的组件实例化它。

注意:编译电路时,必须始终有一个名为main的组件。

2.2 编译电路

现在,我们准备编译电路。运行以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
circom circuit.circom -r circuit.r1cs

将电路编译为名为circuit.rlcs的文件

3. 将编译后的电路放入 snarkjs

现在电路已经编译好了,我们将继续使用snarkjs

我们随时可以通过输入snarkjs --help 来访问snarkjs的帮助

3.1 查看电路有关的信息

要显示电路的信息,可以运行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> snarkjs info -r circuit.r1cs
# Wires: 4
# Constraints: 1
# Private Inputs: 2
# Public Inputs: 0
# Outputs: 1

还可以通过运行以下命令来打印电路的约束:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
snarkjs printconstraints -r circuit.r1cs

3.2 用 snarkjs 启动配置

现在为电路运行启动配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
snarkjs setup

默认 snarkjs 将寻找和使用 circuit.r1cs. 我们也可以用 -r <circuit r1csFile> 来指定一个电路文件。

setup 将输出2 个文件: proving_key.json and verification_key.json

3.3. 计算见证(witness)

在创建任何证明之前,我们需要计算与(所有)电路约束匹配的所有电路信号。

snarkjs会帮我们计算这些。我们需要提供一个包含输入的文件,它将执行电路并计算所有中间信号和输出。这组信号就是“见证”。

零知识证明证明你知道一组与所有约束匹配的信号(见证),但不透露任何信号(公共输入和输出除外)。

例如,想像一下,你想证明自己能够因式分解33,这意味着你知道两个数 ab ,将它们相乘为 33。

因此,您想证明自己知道3和11。(当然,你可以始终使用1 和 数字本身作为 ab,我们稍后将处理此问题。)

让我们创建一个input.json 文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 {"a": 3, "b": 11}

现在计算见证:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 在执行一次见证。

生成证明

现在我们已经生成了见证信息,我们可以创建证明了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
snarkjs proof

这个命令默认会使用 prooving_key.jsonwitness.json 文件去生成 proof.jsonpublic.json

proof.json 文件包好了实际的证明。而 public.json 文件将仅包含公开的输入和输出值。

验证证明

验证证明运行命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> snarkjs verify
OK

这个命令会使用 verification_key.json, proof.jsonpublic.json 来验证有效性。

这里我们证明我们知道一个见证,见证着公共输入和输出与public.json文件中的输入和输出匹配。

如果验证通过会输出OK, 否则会显示 INVALID

生成 Solidity 验证者

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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通过输入以下命令来生成调用的参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 赞助支持。

References

[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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
2 条评论
热度
最新
看这个更好 https://github.com/iden3/snarkjs/blob/master/README.md
看这个更好 https://github.com/iden3/snarkjs/blob/master/README.md
回复回复1举报
3.2节开始误导人,根本没有snarkjs setup这个指令,差评!
3.2节开始误导人,根本没有snarkjs setup这个指令,差评!
回复回复1举报
推荐阅读
编辑精选文章
换一批
构建你的第一个零知识 snark 电路(Circom2)
https://blog.iden3.io/first-zk-proof.html
Tiny熊
2022/11/07
1.5K0
构建你的第一个零知识 snark 电路(Circom2)
密码学[4]:电路 R1CS QAP
设 \sum 是任意集合,\sum^* 是所有的长度有限的字符串 <x_1, .., x_n> ,其中 x_j 取自 \sum ,空字符串 <> ∈ \sum^* 。语言 L 是 \sum^* 的子集。在这种情况下,\sum 是语言 L 的子母表,\sum 中的元素是字母,L 中的元素是单词。如果有规则指定 \sum^* 中的字符串是否属于语言,该规则就被称为语法。如果 L_1 和 L_2 是基于同一个字母表的两个形式语言,且包含了相同的单词集,则称 L_1 和 L_2 是等价的。
谛听
2023/10/28
8410
用零知识证明解决投票安全
我们经常会遇到需要给别人投票的情况,比如有些公司会组织员工给领导做反向打分,但是往往员工都不敢“真心实意”的打分,为什么呢?归根结底是害怕所谓的匿名不是真匿名,万一领导拿到了投票数据给你穿个小鞋你就别混了。
qudamahcui
2018/12/15
2.1K0
一文弄懂 零知识证明中的 Ciruit、Witness、 Proof、 Commitment
在区块链和密码学领域,特别是在零知识证明(Zero-Knowledge Proofs, ZKP)的上下文中,Circuit(电路)、Witness(见证)、Proof(证明)和 Commitment(承诺)都是关键的概念。零知识证明(Zero-Knowledge Proofs, ZKP)技术是一个允许一方(证明者)向另一方(验证者)证明其知道某个信息,而无需透露任何关于该信息的具体内容的强大工具。这种技术不仅增强了隐私保护,还为区块链交易的安全性和透明性提供了支持。
天地一小儒
2024/04/20
1.1K1
区块链隐私保护技术解析——零知识证明
区块链技术最初给我们第一印象是其拥有匿名性,不可篡改性,一致性,分布式等特点。其中匿名性随着对区块链的进一步分析和一些信息情报的收集,一般区块链公链的匿名性都是较弱的。我们熟悉的比特币,以太坊等区块链的匿名性都是较弱的,可以实现交易追踪和地址的聚类,我们在区块链追踪这边也做了一些基础的工作,实现区块链的威胁情报与监管。但是可以通过密码学技术进一步增强区块链的匿名性,其中主流的方法有两种,一种是采用混币的方式其中最具代表性的公链技术是门罗币,这个技术我们在上一篇《区块链隐私保护技术解析——之门罗币(monero)》中进行了详细的分析;另一种技术是采用零知识证明的方式实现强匿名性具有代表性的公链技术是大零币ZEC(Zerocash)。
绿盟科技研究通讯
2022/03/11
2.8K0
区块链隐私保护技术解析——零知识证明
零知识证明学习资源汇总
Github 地址:https://github.com/sec-bit/learning-zkp/blob/master/zkp-resource-list.md
爬虫
2019/11/15
1.5K0
零知识证明;Halo2原理;举例说明算术电路、转换为约束系统、多项式承诺举例形式和数值;PLANK算术化;
零知识证明(Zero-Knowledge Proof,简称ZKP)是一种密码学工具,允许互不信任的通信双方之间证明某个命题的有效性,同时不泄露任何额外信息。这种技术最初由莎菲·戈德瓦塞尔、S.Micali及C.Rackoff在20世纪80年代初提出,其核心在于证明者能够在不向验证者提供任何有用信息的情况下,使验证者相信某个论断是正确的。
zhangjiqun
2024/08/14
3380
零知识证明是零信任吗
如果只是为了回答标题问题,两个字就可以:不是。但还是想顺便说说,零知识证明(ZKP)究竟是什么。
网络安全观
2021/02/24
1.1K0
详解零知识证明的四大基础技术,如何与以太坊发生反应
雷锋网按:原文标题为《zkSNARKs in a nutshell》,作者是以太坊智能合约语言Solidity的发明人Christian Reitwiessner。译者杨文涛,授权转载自作者知乎专栏。 摘要: zkSNARKs(zero-knowledge succint non-interactive arguments of knowledge)的成功实现让我们印象深刻,因为你可以在不执行,甚至在不知道执行具体内容的情况下确定某个计算的结果是否正确——而你唯一知道的信息就是它正确地完成了。但是不幸的是,
企鹅号小编
2018/01/22
1.6K0
详解零知识证明的四大基础技术,如何与以太坊发生反应
去中心化数字身份DID简介——四、用户属性的零知识证明
在上一篇文章中,我们介绍了用户具有多个身份属性时,选择性的把其中的一个属性暴露出来,而不会造成其他信息的暴露。更进一步的情况,某些时候我们只需要验证用户的年龄达到多少岁,或者小于多少岁,但是并不关心用户的具体年龄和出生日期,比如在购买烟酒时,商家需要验证用户的年龄大于18岁。除了年龄,住址、民族等都可能会有对某个断言进行验证的情况。比如某旅游景点,对本市所有居民免费,所以居民只需要证明自己身份证上的住址在某市,而不需要暴露具体的居住地址。这些只给出证明的答案,而不暴露其他任何身份信息的情况,都是零知识证明的范畴。
深蓝studyzy
2022/09/19
1.5K0
去中心化数字身份DID简介——四、用户属性的零知识证明
蚂蚁区块链第7课 零知识证明隐私保护原理和蚂蚁BAAS接口调用实现
本文试图普及隐私保护和零知识证明的相关技术知识,尝试使用更简单的描述来理解复杂的数学算法和技术原理。同时,也提供了蚂蚁区块链已经实现的隐私保护的接口函数说明。 本文涉及的专业知识有零知识证明,zk-SNARKs和 BulletProofs(防弹证明),佩德森承诺等。
辉哥
2019/04/01
1.9K0
蚂蚁区块链第7课 零知识证明隐私保护原理和蚂蚁BAAS接口调用实现
理解Groth16,一些细节上的说明
V 神曾经写过一篇非常好的介绍 R1CS 与 QAP 问题的文章[2]。但是,对于不熟悉密码学[3]的,或者说如何使用密码学的思想来解决问题的票友们来说,文章中的一些逻辑上的跨度还是大了一些。尤其是在 R1CS 转换成多项式的地方,初次接触的人可能会一脸懵逼,不明白为什么要这么做。下面我就从我的理解来谈一谈,从 R1CS 到 QAP 这一过程。
Tiny熊
2022/05/25
1.2K0
理解Groth16,一些细节上的说明
Hyperledger Fabric中的零知识证明
Fabric 1.3中的新增的idemixer(Identity Mixer)以前不大懂zero-knowledge proof(零知识证明),原本觉得PKI基础的MSP是比较常用和稳健的方式,新加个验证方式是不是有点增加复杂性。
Zeal
2020/11/11
1.7K0
Hyperledger Fabric中的零知识证明
Remix IDE 发布了 VSCode 插件
Remix 项目--包括 Remix IDE 及其相关库,发布了 VSCode 的 Remix 插件的测试版本。现在可以在 VSCode 的插件市场上搜索:Remix
Tiny熊
2021/05/11
2.7K0
Remix IDE 发布了 VSCode 插件
每周以太坊进展2022/6/18
(编者注:本翻译不代表登链社区的立场,也不代表我们(有能力并且已经)核实所有的事实并把他的观点分离开来。)
Tiny熊
2022/11/07
3210
以太坊主网部署终极指南
我们都喜欢以太坊,所以你已经创建了一些出色的智能合约。它们通过单元测试和测试网进行了密集的测试。现在终于到了上主网的时候了。但这是一个棘手的事情...
Tiny熊
2021/05/11
2K0
以太坊主网部署终极指南
在区块链浏览器上验证Solidity源码(standard-input-json)
Convert/Escapes an object to a JSON string 将solidity[2]源码转换为JSON字符串
Tiny熊
2022/02/18
1.3K0
在区块链浏览器上验证Solidity源码(standard-input-json)
密码学[5]:Groth16
zero-knowledge protocol:是一组数学规则,根据这些规则,在给定 instance 后,prover 可以向 verifier 证明自己知道该 instance 的 witness 而不揭露 witness 任何信息。
谛听
2023/10/30
6611
二层网络上的以太坊智能合约: Optimistic Rollup
这篇文章概述了optimistic rollup:一种使用OVM[4]在二层网网络上启用智能合约的结构。该构造大量借鉴了plasma和zkRollup设计,并以Vitalik所描述的 shadow chains[5] 为基础 。此结构类似于Plasma[6],但放弃了一些扩展性,以便在二层网络中运行完全通用的智能合约(例如Solidity),同时还享有和一层网络相同的安全性。optimistic rollup的可扩展性与一层网络数据可用带宽成正比,一层网络可以包括Eth1,Eth2, 甚至Bitcoin现金或以太坊经典[7],optimistic rollup都可以在二层网络上提供类EVM的链。
Tiny熊
2020/08/04
1.4K0
二层网络上的以太坊智能合约: Optimistic Rollup
[译] 用 Truffle 插件自动在Etherscan上验证合约代码
Etherscan是以太坊上最受欢迎的浏览器。它的一大功能是验证智能合约的源代码[5]。使用户可以在使用合约之前通过源码了解合约的功能。从而增加用户对合约的信任,也因此使开发者受益。
Tiny熊
2020/08/04
2K0
[译] 用 Truffle 插件自动在Etherscan上验证合约代码
推荐阅读
相关推荐
构建你的第一个零知识 snark 电路(Circom2)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验