IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> zk-SNARKs实战:使用circom和snarkjs实现简单版的Tornado(含源码) -> 正文阅读

[游戏开发]zk-SNARKs实战:使用circom和snarkjs实现简单版的Tornado(含源码)

在上一篇文章中,本人讲解了如何使用circom来编写算术电路的代码,如何将该代码转换成算术电路,并使用snarkjs来转换成zkSNARKs的witness和statement,然后,基于这个来proof和认证该证明,最后,使用snarkjs工具生成solidity代码,部署到Ethereum区块链上,来认证该proof。

1. 上篇文章总结

上篇文章中使用到的命令总结如下 (https://liangyihuai.blog.csdn.net/article/details/124043881?spm=1001.2014.3001.5502):

  1. 将我们的电路编译为 .json 文件 :

$ circom testcirc.circom -o testcirc.json

  1. 执行的电路运行设置:

$ snarkjs setup -c <circuit_name.json>

  1. 计算我们运行的见证

$snarkjs calculatewitness -c testcirc.json -i input.json

  1. 生成证明

$ snarkjs proof

  1. 验证证明

$ snarkjs verify

  1. 得到一个verifier.sol文件

$ snarkjs generateverifier

  1. 获得调用构造的捷径

$ snarkjs generatecall

2.区块链交易隐私保护:Tornado原理

根据上篇文章的知识,本文先讲解Tornado的基本原理,然后讲解如何使用circom和snarkjs实现它。

在这里插入图片描述
Tornado的目的是实现数字货币转账的隐私保护。主要的idea是防止一个用户,比如alice,旧地址和新的地址被关联起来。如上图,alice通过Tornado的智能合约(部署在Ethereum上)从旧地址中转账1000DAI到该智能合约中,然后,以零知识证明的方式,从该合约中取出1000DAI到新地址中,从而达到旧地址和新地址无法被关联的目的。

在这里插入图片描述
图片来源:Stanford University CS251

上面所述的智能合约维护了上图中间的结构/智能合约的状态,其中包含一个Merkle Tree的根节点,一个 n f i nf_i nfi? 列表,其中的 i i i值和右边Merkle Tree的叶子节点的 C i C_i Ci?对应。 C i C_i Ci?表示用户存储在智能合约中的币, n f i nf_i nfi? 表示用户从智能合约中取走的币。具体的,alice秘密生成两个随机数, r i , k i r_i, k_i ri?,ki?, 计算 C i = H ( k i , r i ) ; C_i = H(k_i, r_i); Ci?=H(ki?,ri?); n f i = H ( k i ) nf_i = H(k_i) nfi?=H(ki?)

  • 当一个用户向智能合约中存入钱的时候,假设每次只能存入100DAI,她生成 C 4 C_4 C4?,根据当前的Merkle Tree(有 C 1 , C 2 , C 3 C_1, C_2, C_3 C1?,C2?,C3?三个叶子)插入 C 4 C_4 C4?到(Sparse)Merkle tree中,并生成相应的证明来证明该 C 4 C_4 C4?被正确插入。并转账100DAI。
  • 当要取钱的时候(比如取 C 3 C_3 C3?中的钱),如下图,该用户需要向智能合约证明她知道 C 3 C_3 C3?所对应的 r i , k i r_i, k_i ri?,ki? n f 3 nf_3 nf3?所对应的 k i k_i ki?。接着,她向智能合约公开 k i k_i ki?,但不公开 r i r_i ri?。智能合约检测 n f 3 nf_3 nf3?是否存在智能合约中,避免replay attack。
    需要注意的是,第二步所构造的零知识证明中,Merkle tree的根和 k i k_i ki?是公开的/非零知识的。由于除了该用户,其他人不知道 r i r_i ri?,所以,其他人没法花费 C 3 C_3 C3?所对应的钱。

在这里插入图片描述
一个问题是,上面的方案如何保护转账隐私呢?如果有很多人都使用该智能合约,转账进入该合约,然后又以零知识证明的方式无法被关联方式转账出来,那么,敌手很难将进入的和出来的转账关联起来。因此,使用的用户越多,该方案的隐私保护效果越好。一个极端情况是,只有一个用户使用该智能合约,那么敌手必定知道从该智能合约转账出来的用户必定是该给智能合约转账进入的用户。

3. 代码实现

如何实现呢?这里我们使用circom和snarkjs来实现一个简单版本的。

我们首先看最关键的代码部分:如何零知识证明一个用户知道 C i C_i Ci?所对应的 k i , r i k_i,r_i ki?,ri?。使用的是sparse Merkle Tree,也即是,叶子节点的个数事先确定好了,如果该叶子节点没有元素,就是用一个特殊的符号代替。下面是circom代码,需要注意的点是变量digest和nullifier是public的,分别表示Merkle tree的根节点和 k i k_i ki?,其它变量都是private的。最后一行约束了当前circuit的输入所对应的根节点和所给定的digest是相等的。

template Spend(depth) {
    signal input digest;
    signal input nullifier;
    signal private input nonce;
    signal private input sibling[depth];
    signal private input direction[depth];
    
    component hasherLeaf = Mimc2();
    hasherLeaf.in0 <== nullifier;
    hasherLeaf.in1 <== nonce;

    component hashers[depth];
    component selectors[depth];
    for(var i = 0; i < depth; i++){

        log(hasherLeaf.out);

        selectors[i] = SelectiveSwitch();
        selectors[i].in0 <== i == 0 ? hasherLeaf.out : hashers[i-1].out;
        selectors[i].in1 <== sibling[i];
        selectors[i].s <== direction[i];

        hashers[i] = Mimc2(); //hash function
        hashers[i].in0 <== selectors[i].out0;
        hashers[i].in1 <== selectors[i].out1;
        log(hashers[i].out);
    }

    digest === hashers[depth-1].out;
}

如果读者想执行下面给出的源码的话,可是使用test\circuits\spend10\spend10.circom的电路,使用下面作为witness/input.json。具体请看test\circuits\spend10\文件夹

{"digest": "8080087691978198117050369394765307980410920134807546634402909492739124119015","nullifier": "10137284576094","nonce": "45192935725965","sibling": ["171141047017399",
"1921104258255821504350400622926778547143386377757134762322772367658434578801",
"16973346385134691586810492335341496079657653339800419377504568909749787593353",
"6790254632552856235997996157028274815392252658513506763033770088770816748213",
"13263695242030544851800665282261527384879147831156083700346619397977212257688",
"1840967023991560259239032292502905978517614713257677771781870851685755225171",
"4027184480802781552027386339136795508535421388034532363464054617875501505940",
"11615143218180546404420789983788248771891070283082379174961217945780961556045",
"6910546519327067112999266121268451246286112395140456042979014731952547210842",
"6691476691364906793288780242577444371803878027060227645954155614755089787688"],"direction":["1",
"1",
"0",
"1",
"1",
"0",
"1",
"0",
"1",
"1"]}

下图是本人执行spend10的画面。
在这里插入图片描述

源码地址:https://download.csdn.net/download/liangyihuai/85114725
包含ppt和相关描述文件
在这里插入图片描述

以上

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:35:02  更:2022-04-15 00:38:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:09:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码