-
Notifications
You must be signed in to change notification settings - Fork 14
libsnark遇到的大“坑”
Agzs edited this page Dec 6, 2018
·
1 revision
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
序列为顺序序列,中间计算得到的为逆序序列
验证proof
时,输入的公共参数,在xxx_gadget
构造函数中,必须为其先分配空间,并且父类的初始化仅限gadget
,如果是当前类继承于其他自定义的类,则会导致验证proof
失败,原因是:虽然在当前类的构造函数中先为公共参数分配了空间,但是当前类初始化时,先初始化的是父类的构造函数,所以在整个存储空间上,验证proof
的公共参数并不是最先被分配的,所以验证失败。
libnsark
中c++
实现的sha256
,最终得到的哈希值为逆序的byte
序列
ethereum
中go++
实现的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
所用的默克尔树为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()
,此后,继续想wit
和tree
中同时添加其他叶子节点,最终二者得到的rt
是相同的,不同的是path
。需要说明的一点是:tree
和wit
互为友元类,即ZCIncrementalMerkleTree
与ZCIncrementalWitness
互为友元类,具体操作代码如下:
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();