[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4fQgcXkV-1675312908395)(https://tva1.sinaimg.cn/large/e6c9d24ely1gzmazs79m1g20tr04ojug.gif)]
Maria Cappelli在Unsplash上上传的照片
零知识证明技术,尤其是zk-SNARK技术是加密领域最令人兴奋的技术之一,因为:
Rollup是一种区块链扩展解决方案,其计算是在链下完成的,在给定数量的交易后,状态将同步回区块链,这种解决方案可以为我们提供区块链的安全性和更低的gas费,所以我们说zk-Rollup是区块链的理想扩展解决方案。
在本文中,作者会向我们展示如何在JavaScript项目中使用zk-SNARK。
众所周知,我们需要一个电路来生成零知识证明。电路是系统用来计算输出和证明的数学表达式。零知识证明本身就是我们已经成功完成计算的证明。
电路可能会非常复杂,但好在有电路编程语言和库可以让我们比较轻松的编写自己的电路。在本文中我们会使用Circom。Circom是用Rust编写的。可以使用以下命令来安装Rust环境。
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh'=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
安装完Rust后,克隆Circom存储库并构建编译器:
git clone https://github.com/iden3/circom.gitclone https://github.com/iden3/circom.git
cd circom
cargo build --release
cargo install --path circom
如果这过程中没有差池,那么我们已经安装好了Circom编译器。
现在还需要解决Circomlib,Circomlib是一个包含许多有用的预定义电路的编程库。因此,创建一个空项目,并使用以下代码安装Circomlib:
npm initinit
npm i circomlib
现在,我们已经为创建电路做好了准备,下面是它应该看起来的样子:
pragma circom 2.0.0;2.0.0;
include "node_modules/circomlib/circuits/poseidon.circom";
template PoseidonHasher() {
signal input in;
signal output out;
component poseidon = Poseidon(1);
poseidon.inputs[0] <== in;
out <== poseidon.out;
}
component main = PoseidonHasher();
这个简单的电路,有一个专用输入和一个输出信号。我们正在使用Circomlib中的poseidon哈希计算器来生成输入hash。使用此电路,可以证明我们已经知道给定的原始数据hash,但不需要透露它。
在第一步中,可以通过Circom编译器来编译电路,该编译器将生成一个wasm和rlcs文件。
circom poseidon_hasher.circom --wasm --r1cs -o ./build
生成的wasm和rlcs文件在构建文件夹中可用。要生成证明,我们需要一个证明密钥文件,而要生成这个文件,我们就需要一个ptau文件。该ptau文件可以由snarkjs生成。或者也可以下载一个预生成的文件(可以在snarkjs存储库中找到链接)。关于测试,生成的文件对我们有些好处,但在我们生产应用程序中,建议生成自己的ptau。
wget https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_12.ptau
现在可以使用电路和ptau文件生成证明密钥(zkey文件):
npx snarkjs groth16 setup build/poseidon_hasher.r1cs powersOfTau28_hez_final_12.ptau circuit_0000.zkey
不建议将此zkey文件用于生产,但对于测试,它对我们有帮助。
现在,我们已经准备好生成证明了。这其中会用到snarkjs,所以用下面的命令进行安装:
npm i snarkjs
证明生成如下所示:
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
{ in: 10 },
"build/poseidon_hasher_js/poseidon_hasher.wasm",
"circuit_0000.zkey");
console.log(publicSignals);
console.log(proof);
输入信号在函数的第一个参数中传递fullProve。第二个参数是编译电路,最后一个参数是生成的证明密钥。该函数反馈电路的输出和证明。
现在我们需要一个可以从证明密钥生成的验证密钥来验证证明。获取方法如下:
npx snarkjs zkey export verificationkey circuit_0000.zkey verification_key.jsonexport verificationkey circuit_0000.zkey verification_key.json
验证码如下:
const vKey = JSON.parse(fs.readFileSync("verification_key.json"));
const res = await snarkjs.groth16.verify(vKey, publicSignals, proof);
if (res === true) {
console.log("Verification OK");
} else {
console.log("Invalid proof");
}
验证密钥是verify函数的第一个参数,输出和证明是第二和第三个参数。该函数的结果是一个简单的布尔值。
在此例子中,我们使用电路来计算hash,但这并不总是可行的,因为hash可以使部分结果,或者我们的电路看起来像如下所示:
pragma circom 2.0.0;2.0.0;
include "node_modules/circomlib/circuits/poseidon.circom";
template PoseidonHasher() {
signal input in;
signal input hash;
component poseidon = Poseidon(1);
poseidon.inputs[0] <== in;
hash === poseidon.out;
}
component main {public [hash]} = PoseidonHasher();
这个电路没有输出,只有两个输入。第一个输入是数据,第二个输入是数据的哈希。在模板的最后一行,我们检查hash。只有给定的hash是给定数据的poseidon hash,电路才会成功运行。但是要如何在JS中计算poseidon hash呢?
Circomlib有一个可以用于此的JS实现。需要我们安装它:
npm i circomlibjs
现在我们可以用下面的代码来进行计算:
const poseidon = await circomlibjs.buildPoseidon();const poseidon = await circomlibjs.buildPoseidon();
const hash = poseidon.F.toString(poseidon([10]));
console.log(hash);
该poseidon函数结果是Buffer,我们需要将其转换为数字。在zk-SNARK中,每次计算都是在有限域中完成的,所以我们必须使用poseidon.F.toString进行转换。
Circomlibjs和snarkjs在Node.js和浏览器中运行良好,所以我们可以在客户端生成或验证证明,还可以生成用于验证的智能合约。这样我们就可以在Solidity代码中使用它来验证证明。
Circomlibjs也有智能合约生成器。
这是在JavaScript中使用zk-SNARK的简短教程,它不是一个完整教程,大家可能还存有很多问题,我们可以借助Circom和snarkjs,他们都有很好的文档记录,我们也可以从Tornado Cash等现有项目中学到很多东西。
Source:https://medium.com/better-programming/zero-knowledge-proofs-using-snarkjs-and-circom-fac6c4d63202
ChinaDeFi - ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、以最快的速度同步到中国市场提供决策辅助材料。
Layer 2道友 - 欢迎对Layer 2感兴趣的区块链技术爱好者、研究分析人与Gavin(微信: chinadefi)联系,共同探讨Layer 2带来的落地机遇。敬请关注我们的微信公众号 “去中心化金融社区”。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9gHo7Rru-1675312908398)(/Users/mac/Desktop/image-20220429123349102.png)]