Skip to content

libsnark遇到的大“坑”

Agzs edited this page Dec 6, 2018 · 1 revision

1、util.h

packing_gadget实现的加法,需要调整序列为逆序,比如3 = [1 1 0 0 0 0 0 0]

sha256_gadget等需要的序列是顺序bit序列,比如3 = [0 0 0 0 0 0 1 1]

修改util.h第103行,实现序列的逆序,但是需要注意的是libsnark所使用的输入的bit序列为顺序序列,中间计算得到的为逆序序列

2、空间分配

验证proof时,输入的公共参数,在xxx_gadget构造函数中,必须为其先分配空间,并且父类的初始化仅限gadget,如果是当前类继承于其他自定义的类,则会导致验证proof失败,原因是:虽然在当前类的构造函数中先为公共参数分配了空间,但是当前类初始化时,先初始化的是父类的构造函数,所以在整个存储空间上,验证proof的公共参数并不是最先被分配的,所以验证失败。

3、、哈希值

libnsarkc++实现的sha256,最终得到的哈希值为逆序的byte序列

ethereumgo++实现的sha256,最终得到的哈希值为顺序的byte序列

比如给定下列数值

value = [14, 0, 0, 0, ...] = 0xe
sn = [18, 0, 0, 0, ...] = 0x12
r = [18, 0, 0, 0, ...] = 0x12

给定的哈希公式为cmt=sha256(value, sn, r),则

libnsark中c++实现的sha256得到的哈希值为: ccca......9175
ethereum中go++实现的sha256得到的哈希值为:7591......cacc

4、merkleTree

所用的默克尔树为zcash中的IncrementalMerkleTree,而其merkle_gadget的初始化所需的参数为

    merkle_tree_gadget(
        protoboard<FieldT>& pb,
        digest_variable<FieldT> leaf, // 叶子节点哈希值
        digest_variable<FieldT> root, // 根哈希值
        pb_variable<FieldT>& enforce
    ) : gadget<FieldT>(pb) {
        ...
    }
 
    void generate_r1cs_witness(const MerklePath& path) {}

其中,leaf为待证明的叶子节点,需要特别注意的是必须在要证明的叶子节点添加到tree后,才可以为wit赋值wit=tree.witness(),此后,继续想wittree中同时添加其他叶子节点,最终二者得到的rt是相同的,不同的是path。需要说明的一点是:treewit互为友元类,即ZCIncrementalMerkleTreeZCIncrementalWitness互为友元类,具体操作代码如下:

    ZCIncrementalMerkleTree tree;
    assert(tree.root() == ZCIncrementalMerkleTree::empty_root());
    
    ZCIncrementalWitness wit = tree.witness(); //初始化witness
    bool find_cmtS = false;
    for (size_t i = 0; i < 16; i++) {
        if (find_cmtS) {
            wit.append(commitments[i]);
        } else {
            /********************************************
             * 如果删除else分支,
             * 将tree.append(commitments[i])放到for循环体中,
             * 最终得到的rt == wit.root() == tree.root()
             *********************************************/
            tree.append(commitments[i]);
        }

        if (commitments[i] == cmtS) {
            //在要证明的叶子节点添加到tree后,才算真正初始化wit,下面的root和path才会正确。
            wit = tree.witness(); 
            find_cmtS = true;
        } 
    }

    auto path = wit.path();
    uint256 rt = wit.root();

1. 方案设计

VNT零知识设计方案

方案设计图

2. 方案实现

实现细节思考

2.1 libsnark模块实现

2.2 ethereum模块实现

2.3 cgo模块实现

3. 方案测试

部分问题

整体测试出的问题

3.1 libsnark模块测试

3.2 整体测试

4. 修改汇总

4.1 libsnark模块修改汇总

4.2 ethereum模块修改汇总

4.3 cgo模块修改汇总

5. 开发技巧

修改并编译web3.js文件

libsnark遇到的大“坑”

FZQA

CGO

MPT trie

transaction 部分修改

简易以太坊测试

Clone this wiki locally