【零知识证明】Groth16

一 相关介绍

1 Groth16

Groth16是一种用于零知识证明系统中的简洁非交互式知识论证(SNARK)协议,是一种表示计算的方式,在算术电路上操作,使用加法和乘法门。使用配对友好的椭圆曲线来实现高效的证明生成和验证。

Groth16的主要特点包括:

--1. 简洁性:生成的证明非常小,通常只有几百字节。

--2. 高效验证:验证过程计算量小,速度快。

--3. 非交互式:证明者只需发送一个证明,无需与验证者进行多轮交互。

--4. 通用性:可以用于各种计算问题的零知识证明。

--5. 安全性:基于一些标准的密码学假设。

2 Powers of Tau

Powers of Tau是零知识证明系统中的一个重要概念,特别是在zk-SNARKs(零知识简洁非交互式知识论证)中。它是一个多方计算(MPC)仪式,用于生成zk-SNARK系统的初始可信设置。旨在创建一个通用的加密"材料",可以用于后续的零知识证明。这个名字来源于希腊字母τ(tau),在这个过程中,计算τ的不同幂次(powers)。主要特点包括:

--1.安全性:只要参与仪式的至少一方是诚实的,整个系统就是安全的。

--2.可累积:多个参与者可以依次贡献自己的随机性。

--3.通用性:生成的结构可以用于多个不同的电路和证明。

二 Groth16设置

Phase 1

1 启动一个新的Powers of Tau仪式

使用snarkjs工具创建Powers of Tau仪式的初始文件

snarkjs powersoftau new bn128 12 ceremoy_0000.ptau -v
  • snarkjs: 用于生成和验证零知识证明的JavaScript库。
  • powersoftau: snarkjs中的一个子命令,用于执行Powers of Tau仪式。
  • new: 表示我们要创建一个新的Powers of Tau仪式。
  • bn128: 指定使用的椭圆曲线类型。BN128(也称为BN254)是一种常用于零知识证明的配对友好曲线。
  • 12: 多项式的最大幂次,决定了电路的最大大小。2^12 = 4096,意味着这个设置最多可以支持4096个约束。
  • ceremoy_0000.ptau: 输出文件的名称,将数字附加到仪式词的末尾是传统做法,这样就可以跟踪哪些参与者为这个仪式文件贡献了随机性。。
  • -v: 表示"verbose"模式,会输出更详细的信息。

2 贡献阶段

多个参与者依次对ceremony文件进行贡献,其步骤为:

--1 下载当前的ceremony文件

--2 添加自己的随机性

--3 上传修改后的文件

snarkjs powersoftau contribute ceremoy_0000.ptau ceremoy_0001.ptau -v

输入随机数或者文字完成后,删除 ceremoy_0000.ptau ,继续提供随机性。

snarkjs powersoftau contribute ceremoy_0001.ptau ceremoy_0002.ptau -v

......

3 验证贡献

为确保该文件贡献随机性之前,仪式文件没有以任何方式被破坏,获取到仪式文件时可以验证完整性。

snarkjs powersoftau verify ceremoy_0001.ptau

打印出[INFO] snarkJS: Powers of Tau Ok!,则意味着仪式文件正确。

4 最终文件

文件随机性贡献完成后,生成最终文件:

snarkjs powersoftau prepare phase2 ceremoy_0002.ptau ceremoy_final.ptau -v

验证最后的生成文件:

snarkjs powersoftau verify ceremoy_final.ptau  

Phase 2

针对特定电路的设置过程

1 准备电路

首先,准备好想要证明的具体电路,MIMC5哈希电路为例。

pragma circom 2.0.0;

// y = (x + k + c) ^ 5
// 输入信号x, k ,常量c
// base = x + k + c
// base2 = base * base
// base4 = base2 * base2
// base5 = base *base4
// 输出 y

template MIMC5(){
    signal input x;
    signal input k;
    signal output y;

    var nRounds = 10;
    
    signal lastOutput[nRounds + 1];
    signal base[nRounds];
    signal base2[nRounds];
    signal base4[nRounds];

    var c[nRounds] = [
        0,
        108628498564530119400845211344465696619893215909509348621394122327540108068425,
        97918840674612490766260259917122040983322146107578572117133348745818718934238,
        37080288021783359382631708635481166595643657187023815953993753410034258263757,
        73837458841121413400840196415753404416336899430626860296277530990112251638375,
        14175455430092778326653438909353750763438980656611040223157546655455727686661,
        85678297215287832106125129972569780982362546197552607669873965012182303538395,
        37616746480726794097353991145016865625300747892258420087145463257639176364046,
        96407012155233017139473625567546330731938257866046827176139377315631058571917,
        35426948207998228380140847549475429358133108689610886291038432834368020538887
    ];

    lastOutput[0] <== x;
    
    for(var i = 0; i < nRounds; i++){
        base[i] <== lastOutput[i] + k + c[i];
        base2[i] <== base[i] * base[i];
        base4[i] <== base2[i] * base2[i];
        lastOutput[i+1] <== base[i] + base4[i]; 
    }
}

component main = MIMC5();

2 生成zkey文件

编译电路,生成circuit.r1cs文件并导入Phase 1(即之前运行的Powers of Tau命令)的输出

circom circuit.circom --r1cs

启动Phase 2设置,使用编译后的电路和Phase 1输出的ptau文件生成一个初始的zkey文件。

snarkjs groth16 setup circuit.r1cs ceremoy_final.ptau setup_0000.zkey

zkey文件包含了特定于circuit.circom电路的证明和验证密钥

3 贡献随机性

与Phase 1类似,多方可以为zkey文件贡献随机性,以增加安全性。(可以重复多次)

snarkjs zkey contribute setup_0000.zkey setup_final.zkey

4 验证设置

完成贡献后,和Phase 1类似,需要验证最终的zkey文件以确保其正确性。

snarkjs zkey verify circuit.r1cs ceremoy_final.ptau setup_final.zkey

Phase 3

1 生成证明

先为电路添加输入x和k的值:

# 新建一个input.json文件
{
    "x" : "156345341",
    "k" : "28965346"
}

再编译电路为WebAssembly形式,用于生成证明。

circom circuit.circom --wasm

使用编译后的电路、输入数据和最终的zkey文件来生成证明。

snarkjs groth16 fullprove input.json circuit_js/circuit.wasm setup_final.zkey proof.json public.json

2 导出Solidity验证器合约

创建一个Solidity合约,可以在以太坊上验证证明

snarkjs zkey export solidityverifier setup_final.zkey Verifier.sol

3 生成验证调用数据

生成可以用来调用验证器合约的数据。

snarkjs zkey export soliditycalldata public.json proof.json

["0x05fe0d95b181b07d383313d4b458ff17ac2ab3e7ae8433fa4e3c5869875d653c", "0x28e17a78038c2cd2685f9c536c2be7423dd6e23f7e2061b6e27c5071b3f58c36"],[["0x0e5e1552b27bbd45dbf8bbfbcaee1bdc71fa6a9c016654dff27a1beea7b2f57d", "0x03160fb7373a40993cbc74d121ccd75f4910c543c75c65934f93fdde1a16cb6a"],["0x221e506d697c36f9d1bf5b2f12dd1b83986a3f479360f31faf17e215f982681f", "0x227a10c7abfa2c835fe9a3c42e63dc2a67dadb8556942f42e913c943d3e96e75"]],["0x095e86f10679e5f4d96220678e98dbb8cbbd6ec613568ae372e955d088304dce", "0x03c00703bd4dc41af417765c411c84d0a61f9d76b82e22a3215f9889f5edab42"],["0x0000000000000000000000000000000000000000000000000000000000000000"]

4 在合约中验证:

最后,可以将生成的验证器合约部署到以太坊,并使用生成的调用数据来验证证明。

这个过程的美妙之处在于,一旦Phase 1和Phase 2完成,就可以重复使用setup_final.zkey文件来为相同电路的不同输入生成多个证明,而不需要重新进行可信设置。

相关推荐
Roun311 小时前
去中心化存储:Web3中的数据安全新标准
web3·去中心化·区块链
请不要叫我菜鸡15 小时前
分布式——一致性模型与共识算法
分布式·后端·区块链·raft·共识算法·zab
BlockOne1116 小时前
Meme 币生态全景图分析:如何获得超额收益?
大数据·人工智能·区块链
霸都小魔女16 小时前
MT4交易的平仓与强制平仓有哪几种情况
大数据·人工智能·区块链
dingzd951 天前
Web3对社交媒体的影响:重新定义用户互动方式
web3·去中心化·区块链·媒体
复业思维202401081 天前
2024年10月第4个交易周收盘总结(10月收盘)
区块链
倾城璧1 天前
solidity中的Error和Modifier详解
区块链
搬砖的小码农_Sky1 天前
什么是区块链中的不可能三角?
区块链
web3探路者1 天前
加密货币行业与2024年美国大选
java·大数据·web3·区块链·团队开发·开源软件
yoona10202 天前
《女巫攻击:潜伏在网络背后的隐秘威胁与防御策略》
网络·web安全·区块链·学习方法·女巫攻击