【零知识证明】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文件来为相同电路的不同输入生成多个证明,而不需要重新进行可信设置。

相关推荐
OpenBuild.xyz3 小时前
我是如何从 0 到 1 找到 Web3 工作的?
人工智能·web3·去中心化·区块链·智能合约
Sui_Network3 小时前
Sui 如何支持各种类型的 Web3 游戏
大数据·数据库·人工智能·游戏·web3·区块链
区块链蓝海14 小时前
Secured Finance携手Axelar及Squid提升流动性,迎接USDFC主网
区块链
yunteng5211 天前
solidity之Foundry安装配置(一)
web3·区块链·solidity·foundry
qiquandongkh1 天前
2025年股指期货和股指期权合约交割的通知!
大数据·金融·区块链
yoona10202 天前
Rust编程语言入门教程 (七)函数与控制流
开发语言·rust·区块链·学习方法
MetaverseMan3 天前
从sumsub获取用户图片
区块链
电报号dapp1194 天前
区块链虚拟币资产去中心化私钥钱包开发
人工智能·去中心化·区块链·智能合约
漠缠4 天前
股票与比特币投资困境分析及解决方案
人工智能·区块链