环境:ubuntu20.04 (VMware)。
1. 安装Truffle
安装npm。
# 安装Node.js版本16.x
# 以具有sudo特权的用户身份运行以下命令,以下载并执行NodeSource安装脚本
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
# 启用NodeSource存储库后,安装Node.js和npm
sudo apt-get install -y nodejs
# 确认安装成功
node --version
npm --version
参考:ubuntu下安装npm。
安装truffle。
npm install -g truffle
# 确认一下
truffle version
参考:TruffleDocs。
2. 安装Zokrates
curl -LSfs get.zokrat.es | sh
export PATH=$PATH:/home/[你的目录]/.zokrates/bin
#确认一下
zokrates --version
参考:ZokratesDocs。
3. 简单尝试一下Zokrates
参考:ZokratesDocs。
在test.zok
中编写以下代码。
def main(private field a, field b) {
assert(a * a == b);
return;
}
在Terminal中输入如下命令。编译生成out
、out.r1cs
、abi.json
。
zokrates compile -i test.zok
输入如下命令。生成proving.key
、verification.key
。
zokrates setup
输入命令来执行zokrates程序。生成out.wtns
、witness
。
zokrates compute-witness -a 2 4
输入命令生成proof。生成proof.json
文件。
zokrates generate-proof
或者可以本地验证一下证明是否通过。
zokrates verify
最后我们可以生成一个用来验证的智能合约。生成verifier.sol
。这个只能合约我们后面可以进行调用。
zokrates export-verifier
4. ZoKrates和Truffle实现可验证链下计算
4.1 准备一些文件
和上面一样,编写zok
文件。
def main(private field a, field b) {
assert(a * a == b);
return;
}
将zokrates添加到全局环境变量里。修改profile
文件后重启虚拟机。
gedit /etc/profile
# 添加下面一行
export PATH="$PATH:/home/[你的目录]/.zokrates/bin"
# 重启后确认添加成功
echo $PATH
参考:添加环境变量。
输入命令,编译生成out
、out.r1cs
、abi.json
、proving.key
、verification.key
。其中out
、abi.json
、proving.key
提前放在客户端文件夹中,之后使用。
zokrates compile -i test.zok
zokrates setup
输入命令,生成verifier.sol
。这个文件的生成依赖于out
、out.r1cs
、verification.key
。生成之后可以调用其中的函数,之后验证的时候需要用。将名称改为Verifier.sol
。
zokrates export-verifier
4.2 编写智能合约
新建一个Truffle模板。
mkdir truffle-test
cd truffle-test
truffle unbox webpack
将Verfier.sol
复制到contracts
文件夹中。在truffle-config.js
中更改编译器版本为0.8.0
。
compilers: {
solc: {
version: "0.8.0"
}
}
在contracts
文件夹中编写智能合约Veri.sol
。
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import "./Verifier.sol";
contract Veri {
function checkZKP(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[1] memory input
) public returns (bool) {
Verifier.Proof memory proof = Verifier.Proof(
Pairing.G1Point(a[0], a[1]),
Pairing.G2Point(b[0], b[1]),
Pairing.G1Point(c[0], c[1])
);
Verifier v = new Verifier();
return v.verifyTx(proof, input);
}
}
更改migrations\2_deploy_contracts.js
。
const Veri = artifacts.require("Veri");
const verifier = artifacts.require("Verifier");
module.exports = function(deployer) {
deployer.deploy(Veri);
deployer.link(verifier, Veri);
deployer.deploy(verifier);
};
编译,部署智能合约。
truffle develop
compile
migrate
参考:Truffle入门视频。
4.3 编写客户端
编写client.py
。
from web3 import Web3, HTTPProvider
import subprocess
import json
# Truffle后台运行接口
server = Web3(HTTPProvider('http://127.0.0.1:8545'))
# 填写Veri智能合约部署地址
CONTRACT_ADDRESS = server.toChecksumAddress("0xB47cB388D3B55D812e6A7e94FCDC1D57343A239e")
# 在编译好智能合约之后在truffle-test/build/contracts中找到Veri.json。放到客户端文件夹中。
with open('Veri.json', encoding='UTF-8') as f:
Veri_contract = json.load(f)
CONTRACT_ABI = Veri_contract['abi']
contract = server.eth.contract(address=CONTRACT_ADDRESS, abi=CONTRACT_ABI)
# 生成witness文件。依赖于abi.json
out_path = "./out"
abi_path = "./abi.json"
witness_path = "./witness"
zokrates_compute_witness = ["zokrates", "compute-witness", "-o", witness_path,'-i', out_path, '-s', abi_path, "-a", "2", "4"]
g = subprocess.run(zokrates_compute_witness, capture_output=True)
# 生成proof文件。依赖于witness文件、proving.key文件
proof_path = "proof.json"
proving_key_path = "proving.key"
zokrates_generate_proof = ["zokrates", "generate-proof",'-w',witness_path,'-p',proving_key_path,'-i',out_path,'-j',proof_path]
g = subprocess.run(zokrates_generate_proof, capture_output=True)
# 生成proof文件后读取文件中的数据。
with open(proof_path, 'r+') as f:
proof = json.load(f)
a=proof['proof']['a']
a=[Web3.toInt(hexstr=x) for x in a]
b=proof['proof']['b']
b=[[Web3.toInt(hexstr=x) for x in y] for y in b ]
c=proof['proof']['c']
c=[Web3.toInt(hexstr=x) for x in c]
inputs = proof['inputs']
inputs = [Web3.toInt(hexstr=x) for x in inputs]
# 将数据发送到智能合约中,应该得到的result为True
result = contract.functions.checkZKP(a,b,c,inputs).call()
print(result)
5. 流程总结
- Verification Smart Contract文件生成需要
out
、out.r1cs
、verification.key
。 - Witness文件生成需要
abi.json
以及公开输入和私有输入。 - Proof文件生成需要
witness
文件、proving.key
文件。
参考:Zokrates讲解。