zkMega v0.2 报告(Megaclite v0.2 报告)
#
1.回顾0.2的设计目标#
M1: ZoPatract集成arkworks-g16以及四条曲线- 准备ark的g16算法和,算法包由xxxx封装而来
- 准备ark的bls12_381 Curve算法包,算法包由xxxx封装而来
- 准备ark的bn254 Curve算法包,算法包由xxxx封装而来
- 将以上三个算法包集成到ZoPatract_core中.
- 完成CLI flag参数对新增算法包的调整支持.
#
M2: 实现zkSNARKs协议全阶段的CLI命令(ZoPatract_cli)- 实现verifier功能的ink!智能合约模板ink_verifier.rs,并对接到ZoPatract_cli
- 实现ZoPatract_cli模块的Compile、Setup、Compute-witness、Generate-proof、Export-verifier命令在Ink!智能合约环境的移植改造
#
M3: 实现ZoPatract的Javascript工具包(ZoPatract_js)- 实现wrapper模块对接ZoPatract_cli
- 实现Javascript工具包,支持API接口compile、computeWitness、setup、generateProof、exportInkVerifier
#
M4: 集成测试- 测试CLI对Arkworks的G16和曲线bls12_381、bn254算法包的使用
- 测试CLI对Compile、Setup、Compute-witness、Generate-proof、Export-verifier命令在Ink!智能合约环境的使用
- 测试Javascript工具包在Ink!智能合约环境与CLI的集成
- 使用ZoKrates高级语言编写是示例应用,使用CLI完成证明构建,并使用Javascript工具包和链上交易完成测试验证
- 搭建ZoPatract文档和在线安装环境
#
2.实现的交付物#
2.1 ZoPatract项目ZoPatract 是一个基于zokrates改造的适配于jupiter ink环境的zksnark toolbox.
#
2.2 ZoPatract的在线安装和手动安装#
One-line installationWe provide one-line installation for Linux, MacOS and FreeBSD:
curl -LSfs get.zoprat.es | sh
#
From sourceYou can build ZoPatract from source with the following commands:
git clone https://github.com/ZoPatract/ZoPatractcd ZoPatractcargo +nightly build --releasecd target/release
#
2.3 Javascript工具包JavaScript bindings for ZoPatract.
npm install zopatract-js
#
Importing#
BundlersNote: As this library uses a model where the wasm module itself is natively an ES module, you will need a bundler of some form.
Currently the only known bundler known to be fully compatible with zopatract-js
is Webpack.
The choice of this default was done to reflect the trends of the JS ecosystem.
import { initialize } from 'zopatract-js';
#
Nodeconst { initialize } = require('zopatract-js/node');
#
Exampleinitialize().then((zopatractProvider) => { const source = "def main(private field a) -> field: return a * a";
// compilation const artifacts = zopatractProvider.compile(source);
// computation const { witness, output } = zopatractProvider.computeWitness(artifacts, ["2"]);
// run setup const keypair = zopatractProvider.setup(artifacts.program);
// generate proof const proof = zopatractProvider.generateProof(artifacts.program, witness, keypair.pk);
// export solidity verifier const verifier = zopatractProvider.exportSolidityVerifier(keypair.vk, "v1");});
ZoPatract的详细使用文档#
2.4可以获取相关命令、高级语言、工具包和示例代码的使用信息 (项目代码/工具包/文档/示例程序)
#
2.5 ZoPatract开发的简单zk示例应用#
ZoPatract use bls12_381-based arkworks-groth16 algorithm case:First, create the text-file square_root.zop and implement your program. In this example, we will prove knowledge of the square root a of a number b:
def main(private field a, field b) -> bool: return a * a == b
Some observations:
- The keyword field is the basic type we use, which is an element of a given prime field.
- The keyword private signals that we do not want to reveal this input, but still prove that we know its value.
Then run the different phases of the protocol: compile: 将zok源码压平成逻辑条件语句形式, 生成两个文件(默认 out, out.ztf), 其中 .ztf 文件是可读版.
# compile , 选择bls12_381曲线./zopatract compile -i square_root.zop -c bls12_381
setup: 执行trusted setup操作, 生成arkworks-groth16算法的CRS(Common Reference String).
输入为 compile 生成的 out, 在生成 CRS 前会会先生成 R1CS 等操作, 最终输出两个文件: proving.key 和 verification.key.
# perform the setup phase./zopatract setup -b ark -s g16
compute-witness: 命令的输入为compile生成的out, 以及计算问题的输入参数; 输出一个文件, 默认文件名为 witness.
# execute the program./zopatract compute-witness -a 12 144
generate-proof: 基于constrained system(computation problem)以及 witness 生成对应的零知识证明 proof.json.
# use arkworks groth16 algorithm to generate a proof of computation./zopatract generate-proof -b ark -s g16
verify: 验证proof.json(默认选择当前路径下的proof.json文件)
# 通过-b, -s, -c分别选择arkworks scheme, groth16 algorithm, bls12_381 curve./zopatract verify -b ark -s g16 -c bls12_381
#
3. 详细实现(展示核心代码)ZoPatract helps you use verifiable computation in your DApp, from the specification of your program in a high level language to generating proofs of computation to verifying those proofs in ink!.
#
3.1 ZoPatract的详细实现https://github.com/arkworks-rs/groth16) 到ZoPatract#
3.1.1 集成arkworks-groth16(整个设计最上层主要通过各个不同的零知识证明库去实现Backend trait来触发不同库的使用:
pub trait Backend<T: Field, S: Scheme<T>> { fn setup(program: ir::Prog<T>) -> SetupKeypair<S::VerificationKey>;
fn generate_proof( program: ir::Prog<T>, witness: ir::Witness<T>, proving_key: Vec<u8>, ) -> Proof<S::ProofPoints>;
fn verify(vk: S::VerificationKey, proof: Proof<S::ProofPoints>) -> bool;}
我们给Ark struct(对标arkworks库)实现Backend trait的三个方法: 初始化生成CRS(provingkey, verifykey)
fn setup(program: Prog<T>) -> SetupKeypair<<G16 as Scheme<T>>::VerificationKey> { let parameters = Computation::without_witness(program).groth16_setup();
let mut pk: Vec<u8> = Vec::new(); parameters.serialize_uncompressed(&mut pk).unwrap();
let vk = VerificationKey { alpha: parse_g1::<T>(¶meters.vk.alpha_g1), beta: parse_g2::<T>(¶meters.vk.beta_g2), gamma: parse_g2::<T>(¶meters.vk.gamma_g2), delta: parse_g2::<T>(¶meters.vk.delta_g2), gamma_abc: parameters .vk .gamma_abc_g1 .iter() .map(|g1| parse_g1::<T>(g1)) .collect(), }; SetupKeypair::new(vk, pk)}
主要用于将dsl产生的Prog转换成computation,然后通过groth16_prove产生proof
fn generate_proof( program: Prog<T>, witness: Witness<T>, proving_key: Vec<u8>, ) -> Proof<<G16 as Scheme<T>>::ProofPoints> { let computation = Computation::with_witness(program, witness); let params = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed( &mut proving_key.as_slice(), ).unwrap();
let proof = computation.clone().groth16_prove(¶ms); let proof_points = ProofPoints { a: parse_g1::<T>(&proof.a), b: parse_g2::<T>(&proof.b), c: parse_g1::<T>(&proof.c), };
let inputs = computation .public_inputs_values() .iter() .map(parse_fr::<T>) .collect::<Vec<_>>();
Proof::new(proof_points, inputs)}
主要做了verifykey和proof的格式转化, 封装了arkworks-groth16的verify_proof function.
fn verify( vk: <G16 as Scheme<T>>::VerificationKey, proof: Proof<<G16 as Scheme<T>>::ProofPoints>, ) -> bool { let vk = VerifyingKey { alpha_g1: serialization::to_g1::<T>(vk.alpha), beta_g2: serialization::to_g2::<T>(vk.beta), gamma_g2: serialization::to_g2::<T>(vk.gamma), delta_g2: serialization::to_g2::<T>(vk.delta), gamma_abc_g1: vk .gamma_abc .into_iter() .map(|g1| serialization::to_g1::<T>(g1)) .collect(), };
let ark_proof = ArkProof { a: serialization::to_g1::<T>(proof.proof.a), b: serialization::to_g2::<T>(proof.proof.b), c: serialization::to_g1::<T>(proof.proof.c), };
let pvk: PreparedVerifyingKey<<T as ArkFieldExtensions>::ArkEngine> = prepare_verifying_key(&vk);
let public_inputs: Vec<_> = proof .inputs .iter() .map(|s| { T::try_from_str(s.trim_start_matches("0x"), 16) .unwrap() .into_ark() }) .collect::<Vec<_>>(); verify_proof(&pvk, &ark_proof, &public_inputs).unwrap()}
通过computation_basic macro给Computation实现了封装arkworks groth16和gm17 algorithm的setup prove.
macro_rules! computation_basic { ($algorithm:tt, $name:ident) => { paste::item! { impl<T: Field + ArkFieldExtensions> Computation<T> { pub fn [<$name _prove>](self, params: &$algorithm::ProvingKey<T::ArkEngine>) -> $algorithm::Proof<T::ArkEngine> { let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let proof = $algorithm::create_random_proof(self.clone(), params, rng).unwrap();
let pvk = $algorithm::prepare_verifying_key(¶ms.vk);
// extract public inputs let public_inputs = self.public_inputs_values();
assert!($algorithm::verify_proof(&pvk, &proof, &public_inputs).unwrap());
proof }
pub fn [<$name _setup>](self) -> $algorithm::ProvingKey<T::ArkEngine> { let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
// run setup phase $algorithm::generate_random_parameters(self, rng).unwrap() } } } }}
computation_basic!(ark_gm17, gm17);computation_basic!(ark_groth16, groth16);
Bls12_377, Bls12_381, Bn254, BW6_761到ZoPatract的arkworks groth16算法:#
3.1.2 集成arkworks四条曲线通过ArkFieldExtensions trait添加arkworks curve:
pub trait ArkFieldExtensions { /// An associated type to be able to operate with ark ff traits type ArkEngine: PairingEngine;
fn from_ark(e:<Self::ArkEngine as ark_ec::PairingEngine>::Fr) -> Self; fn into_ark(self) -> <Self::ArkEngine as ark_ec::PairingEngine>::Fr;}
通过ark_extensions macro给各个曲线实现ArkFieldExtensions trait:
ark_extensions!(Bls12_377);ark_extensions!(Bls12_381);ark_extensions!(Bn254);ark_extensions!(BW6_761);
通过T: trait bound可以选择不同的arkworks curves:
impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, G16> for Ark { /*Omited*/ }
#
3.2 集成ink合约 verfify模板的实现(模板代码在哪里,改动核心点用代码展示出来,包括export_ink_verifier,包括命令行处参数部分的改动)可以通过./zopatract export-verifier -t ink
命令导出 ink_verifier.rs 合约模板.
实现通过InkCompatibleScheme trait的export_ink_verifier方法处理INK_CONTRACT_TEMPLATE常量字符串和CARGO_TOML常用字符串.
impl<T: InkCompatibleField> InkCompatibleScheme<T> for G16 { fn export_ink_verifier(vk: <G16 as Scheme<T>>::VerificationKey,abi: InkAbi) -> (String,String) { let (mut template_text,toml_text) = match abi { InkAbi::V1 => (String::from(INK_CONTRACT_TEMPLATE),String::from(CARGO_TOML)), InkAbi::V2 => (String::from(INK_CONTRACT_TEMPLATE),String::from(CARGO_TOML)) }; let vk_regex = Regex::new(r#"(<%vk_[^i%]*%>)"#).unwrap(); let vk_gamma_abc_len_regex = Regex::new(r#"(<%vk_gamma_abc_len%>)"#).unwrap(); let vk_gamma_abc_regex = Regex::new(r#"(<%vk_gamma_abc%>)"#).unwrap();
let format_g2affine = |g2:G2Affine|{ format!( "\"{}\", \"{}\", \"{}\", \"{}\"", (g2.0).0, (g2.0).1, (g2.1).0, (g2.1).1 )};
template_text = vk_regex .replace(template_text.as_str(),format!("\"{}\",\"{}\"",vk.alpha.0,vk.alpha.1).as_str()) .into_owned(); template_text = vk_regex .replace(template_text.as_str(), format_g2affine(vk.beta).as_str()) .into_owned(); template_text = vk_regex .replace(template_text.as_str(),format_g2affine(vk.gamma).as_str()) .into_owned(); template_text = vk_regex .replace(template_text.as_str(),format_g2affine(vk.delta).as_str()) .into_owned(); template_text = vk_gamma_abc_len_regex .replace(template_text.as_str(),format!("{}", vk.gamma_abc.len()*2).as_str()) .into_owned();
let mut vk_gamma_abc = String::new(); vk.gamma_abc.iter().for_each(|g1| { vk_gamma_abc.extend(format!("\"{}\",\"{}\",",g1.0,g1.1).chars()); }); template_text = vk_gamma_abc_regex .replace(template_text.as_str(),vk_gamma_abc.strip_suffix(",").unwrap()) .into_owned(); (template_text, toml_text) }}
ink_verifier.rs):#
ink contract template(#![cfg_attr(not(feature = "std"), no_std)]use ink_lang as ink;use megaclite_arkworks::{groth16, curve::<%curve%>, result::Error};
// VK = [alpha beta gamma delta]static VK:[&str;14] = [<%vk_alpha%>, <%vk_beta%>, <%vk_gamma%>, <%vk_delta%>];static VK_GAMMA_ABC:[&str;<%vk_gamma_abc_len%>] =[<%vk_gamma_abc%>];
#[ink::contract]mod zop { #[ink(storage)] pub struct Zop { // Stores the ZK result result: bool, }
impl Zop { /// Use false as initial value #[ink(constructor)] pub fn default() -> Self { Self { result: false } }
#[ink(message)] pub fn verify(&self, proof_and_input: &[u8]) -> Result<bool, Error> { groth16::preprocessed_verify_proof::<<%curve%>>(VK, VK_GAMMA_ABC, proof_and_input) } }}
Cargo.toml templa:
[package]name = "zop"version = "0.1.0"authors = ["[your_name] <[your_email]>"]edition = "2018"
[dependencies]ink_primitives = { version = "3.0.0-rc2", default-features = false }ink_metadata = { version = "3.0.0-rc2", default-features = false, features = ["derive"], optional = true }ink_env = { version = "3.0.0-rc2", default-features = false }ink_storage = { version = "3.0.0-rc2", default-features = false }ink_lang = { version = "3.0.0-rc2", default-features = false }
scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }scale-info = { version = "0.4.1", default-features = false, features = ["derive"], optional = true }
# megalicte zk librarymegaclite-arkworks = { git = "https://github.com/patractlabs/megaclite.git", default-features = false }
[lib]name = "zop"path = "lib.rs"crate-type = [ # Used for normal contract Wasm blobs. "cdylib",]
[features]default = ["std"]std = [ "ink_metadata/std", "ink_env/std", "ink_storage/std", "ink_primitives/std", "scale/std", "scale-info/std",]ink-as-dependency = []
#
4. 用ZoPatract在Jupiter上开发zk应用#
off-chain:First, create the text-file square_root.zop and implement your program. In this example, we will prove knowledge of the square root a of a number b:
def main(private field a, field b) -> bool: return a * a == b
#
Then run the different phases of the protocol:compile: 将zok源码压平成逻辑条件语句形式, 生成两个文件(默认 out, out.ztf), 其中 .ztf 文件是可读版.
# compile , 选择bls12_381曲线./zopatract compile -i square_root.zop -c bls12_381
setup: 执行trusted setup操作, 生成arkworks-groth16算法的CRS(Common Reference String). 输入为 compile 生成的 out, 在生成的CRS 前会会先生成 R1CS 等操作, 最终输出两个文件: proving.key 和 verification.key.
# perform the setup phase./zopatract setup -b ark -s g16
#
导出ink_verifier.rs合约,并部署到链上:export-verifier: select the curve at compile phase to export ink contract-type ink_verifier.rs
./zopatract export-verifier -t ink -c bls12_381
部署: //配图
#
generate proof:compute-witness: 命令的输入为compile生成的out, 以及计算问题的输入参数; 输出一个文件, 默认文件名为 witness.
# execute the program./zopatract compute-witness -a 12 144
基于constrained system(computation problem)以及 witness 生成对应的零知识证明 proof.json和proof.txt(hex encode all data).
# use arkworks groth16 algorithm to generate a proof of computation./zopatract generate-proof -b ark -s g16
cli printed:
Generating proof...Proof hex:822a26fa4c0a7fbcc725dd45f89d9a33fd69f0545702c55dfe6e5c36f987b9de3a48b53df6e9c2ce04e51dc479307f0281fbdbec9b1510435f8d3b1b6649d408e71f7e61a78d00156e42d7eef6a68f1e6b14b3a0c209e133e5d0fecbf17c2d1500647ec3b72e31d59ed2dc3d4ac84111db3d505c7d0d376e2f5b406c302d927c939e01f76a6298f3e751d7624a72c5d3196abea9d14509701344da6eb3b10d235068dd1f113d78a63b108f64da5c4a13117776a2a6cb8a765f020f569e56172c15cc94eb9d5aba92ec0ad775b14beeca44b9f6db7e6d74d9594a731c40e7cc31b13b140d12e04e0b087315f72624dd97188c9dd182e1607cf18ae48981be0a86a9fa62a696a88e57eee3dad0c5a24f6a5df938a48c77265f595a9765c0cad25c110052c05fa24dc8058811bbeeeced871472451c23370f924854e328198088e533f070f9b7e5636bcd9b4dfd1af96d6b7a0564d4660f7f0e1e75cc25f6c55cd1f1e8db29f105286fd48a5c90394b50b8b2641949f8d62b22778b0bc3b56ee12cbb050090000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000
#
发送proof到链上:通过postman将hex proof或proof.txt内容以交易形式发送到链上: // Todo 配图
#
On chain链上验证结果: // 配图
#
回顾验证信息ZoPatract_core integrates arkworks-g16、arkworks-bls12_381、arkworks-bn254Implement CLI command for the whole phase of Zksnarks agreement (Zopatract_cli)The Ink smart contract template ink_verifier.rs that implements the verifier function is connected to Zopatract_cli's export-verifier.Modify the Zopatract JavaScript toolkitTest CLI's use of Arkworks groth16 algorithm and curve Bls12_381 and Bn254 curve packageTest CLI on compile, setup, compute-witness, generate-proof, export-verifier commands in ink! smart contract environments.