手机版

当前位置:数字货币交易所 > 知识 >

零常识证明 - ethsnarks源码导读

时间:2021-07-20 22:24:34|浏览:

1. 源码结构

contracts - 达成了groth16的验证智能合约(Verifier.sol),椭圆曲线的计算,MerkleTree与MiMC Hash计算的智能合约。这部分智能合约可以通过truffle进行部署测试。部署有关的脚本在migrations目录下。

ethsnarks - python达成的有关功能,包括pedersen/mimc/poseidon等hash函数,groth16验证,与椭圆曲线的计算。

test - 以上两个功能的测试代码,使用python语言达成。

depends - 依靠库,包括libsnark,libfqfft等等。

src - 基于libsnark的gadget1库达成的更多的gadget。本文着重介绍这部分gadget的达成。

2. gadget达成

src目录下的源码结构如下:

2.1 ethsnarks.hpp

libsnark的gadget1库主要围绕sha256(基于bit的hash函数)达成各种gadgets。ethsnarks在alt_bn128这条椭圆曲线上达成了基于Field的hash函数(mimc,pedersen,poseidon等)。

libsnark的电路中各种概念都很长。libsnark概念一个变量数组种类:pb_variable_array<FieldT>。

ethsnarks.hpp精简了在alt_bn128这条椭圆曲线有关的种类声明:

namespace ethsnarks {

typedef libff::bigint<libff::alt_bn128_r_limbs> LimbT;
typedef libff::alt_bn128_G1 G1T;
typedef libff::alt_bn128_G2 G2T;
typedef libff::alt_bn128_pp ppT;
typedef libff::Fq<ppT> FqT;
typedef libff::Fr<ppT> FieldT;
typedef libsnark::r1cs_constraint<FieldT> ConstraintT;
typedef libsnark::protoboard<FieldT> ProtoboardT;
typedef libsnark::pb_variable<ethsnarks::FieldT> VariableT;
typedef libsnark::pb_variable_array<FieldT> VariableArrayT;
typedef libsnark::pb_linear_combination<FieldT> LinearCombinationT;
typedef libsnark::pb_linear_combination_array<FieldT> LinearCombinationArrayT;
typedef libsnark::linear_term<FieldT> LinearTermT;
typedef libsnark::gadget<ethsnarks::FieldT> GadgetT;

typedef libsnark::r1cs_gg_ppzksnark_zok_proof<ppT> ProofT;
typedef libsnark::r1cs_gg_ppzksnark_zok_proving_key<ppT> ProvingKeyT;
typedef libsnark::r1cs_gg_ppzksnark_zok_verification_key<ppT> VerificationKeyT;
typedef libsnark::r1cs_gg_ppzksnark_zok_primary_input<ppT> PrimaryInputT;
typedef libsnark::r1cs_gg_ppzksnark_zok_auxiliary_input<ppT> AuxiliaryInputT;
}
其中,FieldT特指在alt_bn128线上的点的个数。

2.2 utils.hpp/utils.cpp

utils达成了电路达成中常见的功能性函数。

inline const VariableT make_variable
{
VariableT x;
x.allocate;
return x;
}

make_variable创建一个VariableT。

const VariableArrayT flatten
{
size_t total_sz = 0;
for
total_sz += scalar.size;

VariableArrayT result;
result.resize;
size_t offset = 0;
for
{
for; i++ )
{
result[offset++].index = scalar[i].index;
}
}
return result;
}

flatten函数将多个VariableArrayT合并成一个VariableArray。其实也非常简单,就是把VariableArray中的index都合并到一个VariableArray中。

2.3 r1cs_gg_ppzksnark_zok

在libsnark的r1cs_gg_ppzksnark的基础上,稍做改动,让ETH的预编译智能合约能验证groth16的算法。r1cs_gg_ppzksnark_zok目录中的README.md非常明确的讲解了改动是什么原因。

从ETH的拜占庭硬分叉之后,ETH引入了基于ALT_BN128的配对函数计算的预编译合约,合约达成的功能如下:

给定ALT_BN128上两个基点(G1/G2)一系列的点,预编译合约能检查:

e * ... * e 是不是等于1?

Groth16原有些验证系数为:vk.alpha_beta,vk.gamma与vk.delta。Groth16的验证等式为:

vk.alpha_beta = e * e * e

其中vk.alpha_beta为e。

假如直接用之前的验证等式,ETH上的预编译合约没法达成。在不影响Groth16的安全性的状况下,将Groth16的验证系数变为:vk.alpha,vk.beta,vk.gamma与vk.delta。Groth16的验证等式也变为:

e * e * e * e = 1

r1cs_gg_ppzksnark_zok目录就是达成如上的改动。同时提供了stubs.hpp/stubs.cpp,从json文件中读取相应的验证参数进行验证。

2.4 poseidon

poseidon算法的达成在gadgets/poseidon.hpp文件中。

template<unsigned nInputs, unsigned nOutputs, bool constrainOutputs=true>
using Poseidon128 = Poseidon_gadget_T<6, 1, 8, 57, nInputs, nOutputs, constrainOutputs>;

Poseidon128是Poseidon_gadget_T的一个实例。前面四个参数是poseidon算法的参数,后续会写文章详细介绍poseidon算法与这部分参数包含的意思(6,1,8,57是默认的配置)。nInputs指定算法的输入的个数,nOutputs指定输出的个数,contrainOutputs指定是不是对输出进行约束。

Poseidon_gadget_T的架构函数如下:

Poseidon_gadget_T :
GadgetT,
inputs,
constants),
first_round),
prefix_full_rounds),
partial_rounds.outputs, constants, annotation_prefix)),
suffix_full_rounds.outputs, constants, annotation_prefix)),
last_round, constants.M, suffix_full_rounds.back.outputs, FMT),
_output_vars : VariableArrayT)
{
}

poseidon算法的计算由好几轮组成:first_round(第一轮),prefix_full_rounds(预处置,完整轮),partial_rounds,suffix_full_rounds(后处置,完整轮)与last_round(最后一轮)。

_output_vars是输出的变量。这部分轮都是通过make_rounds函数达成。

template<typename T>
static const std::vector<T> make_rounds
{
std::vector<T> result;
result.reserve;

for
{
const auto& state = ? inputs : result.back.outputs;
result.emplace_back);
}

return result;
}

make_rounds就是为每一轮筹备适合的参数。每一轮的具体达成通过Poseidon_Round达成。

在Poseidon_Round的封装下,Poseidon_gadget_T的generate_r1cs_constraints与generate_r1cs_witness相对容易,小伙伴们可以自行查询源码。

3. 示例代码

在ethsnarks的基础上,达成Poseidon函数的电路就很简单了。架构一个容易的电路,给大伙参考一下。

电路的需要:达成Poseidon计算,输入为两个FieldT,输出为一个FieldT。输出作为电路的public input。

#include "ethsnarks.hpp"
#include "gadgets/poseidon.hpp"

using namespace ethsnarks;

namespace testproject {
using TestHash = Poseidon128<2, 1>;

class test_gadget : public GadgetT {
public:
VariableT output;
VariableT input0;
VariableT input1;

TestHash tHash;

test_gadget : GadgetT,
output)),
input0)),
input1)),
tHash, FMT)
{
}

void generate_r1cs_witness
{
pb.val = w_input0;
pb.val = w_input1;
pb.val = w_output;

tHash.generate_r1cs_witness;
}

void generate_r1cs_constraints
{
pb.set_input_sizes;
tHash.generate_r1cs_constraints;

pb.add_r1cs_constraint),
FMT"));
}
};
};

概要:

ethsnarks在libsnark的基础上,达成了ETH上与zkSNARK有关的智能合约和电路。ethsnarks本身也是libsnark应用非常不错的学习示例。libsnark的gadget1库主要围绕sha256(基于bit的hash函数)达成各种gadgets。ethsnarks在alt_bn128这条椭圆曲线上达成了基于Field的hash函数(mimc,pedersen,poseidon等)。

近期看知乎,发现知乎上有的文章真的醍醐灌顶。印象比较深的是,文因互联CEO 鲍捷的一篇文章:最快的成长方法就是慢慢来。创业最重要的能力,就是“不被卡住”的能力。这才是“探索力”的根本,是创业“实行力”的核心。

大多数人都熟知让其他人告知一个明确的目的,然后明确的实行。但,创业是一种探索,无人会对你说如此的明确的目的。探索,是一种反人性的活动。大部分人会对探索畏惧,恐惧,抵触,茫然。

“不被卡住”,需要学会好“任务分解,迅速迭代”的办法论,需要打造“出货”的态度(每一个时期结束都有可出货的状况),需要“勤于交流”, 需要”不固执己见“,更需要”不断复盘“。”不被卡住“,还有个应该注意的是,有多少本钱打多少仗,不要总想着打大仗,要掌握从小仗慢慢打。

以太币snarks在libsnark的基础上,达成了ETH上与zkSNARK有关的智能合约和电路。ethsnarks本身也是libsnark应用非常不错的学习示例。

ethsnarks的源码地址:

https://github.com/HarryR/ethsnarks.git

本文中用的ethsnarks源码的最后一个commit如下:

commit 9adc64355adb9154ba5042c0fadf84c438b8a08a
Author: Wan网站优化b Lim <email@wan网站优化b.com>
Date: Fri Aug 16 01:49:19 2021 +0900

Add Fr field class to the field.py

上一篇:Chia 显卡 P图仅需10秒? 下一篇:没有了

Copyright © 2002-2021 数字货币交易所 (http://www.bjfdjx.com) 网站地图 TAG标签