当谈及零知识电路开发时,我们有很多可选的库。实现我发现iden3开发的circom和snarkjs 对于零知识证明的新手很友好:电路很容易编写,整个零知识证明框架 的运行也很简单,不需要复杂的环境。
建议你在学习本教程之前先阅读circom/snarkjs的官方教程。 本教程的完整代码可以从这里下载。
用自己熟悉的语言学习以太坊DApp开发: Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart
1、零知识扑克牌游戏规则简介
为了突出重点,我们简化了扑克牌游戏的规则:
每个选手发5张牌
不可以换牌
当比较牌大小时,只考虑对子(pairs),不考虑顺子(straights)、同花(flushes)、满堂红(full houses)等等情况
选手可选的动作只有:不跟(fold)、下注(see)、加注(raise)
如果一手牌里没有对子,选手就不能叫牌(bid)
还有最后一个规则 —— 不允许虚张声势(bluffing) —— 这就是我们要用零知识证据来保证的。 叫牌的选手可以避免泄露自己的牌,但同时依然可以向其他选手证明自己的确有对子,不是 虚张声势。在下面的教程中,我们将忽略游戏机制而聚焦于零知识证明电路的设计与实现。
2、零知识扑克牌游戏的电路概述
我们这个基于零知识证明的扑克牌游戏的电路,大致应该是这样的:
采集输入:牌型、选手的叫牌选择
确认牌面中至少有一个对子
评估叫牌类型,例如跟进或弃牌
设置一个约束来检查是否已经进行选择
设置一个约束来检查所选择的选项符合当前的牌型
下面就让我们分步骤学习这个电路的实现代码。
3、引入circom提供的基础电路
首先我们需要引入一些circom提供的基础电路:
include “../node_modules/circomlib/circuits/gates.circom”;include “../node_modules/circomlib/circuits/comparators.circom”;
需要指出的是,我们的文件夹结构看起来是这样:
project-root\poker
因此我们使用上面的路径来引入基础电路。这些基础电路时circomlib 提供的,因此需要进行额外的安装:
npm install --save circomlib
4、定义扑克牌游戏的零知识电路模板
template Poker() { ... circuit body ...}component main = Poker();
这个结构基本和官方教程里一样,只有一个模板并且定义了入口点。
5、定义扑克牌游戏的输入、输出和中间结果
signal private input cards[5]; // Each 2..14signal input isSee; // 1 or 0signal input isFold; // 1 or 0signal input raise; // intsignal output out; // 1 or 0// Intermediate resultssignal isBid;signal isRaise;signal hasChosen;
牌型信息定义为一个数组:cards[5],每一张牌都用其牌面值 表示,我们忽略花色。例如 Ace=14、King=13、Queen=12、Jack=11… 依次类推直至2。选手的牌型是电路的私有输入,这表示我们要求 这个输入保持隐秘。
叫牌选项当然是公开的,因为该信息需要向所有其他选手公布。 弃牌或者跟随下注选项都用布尔值表示,加注选项则是整数 类型,表示实际增加的注数。
唯一的输出是out,值为1或0。
我们还定义了其他一些中间值,稍后在进行介绍。
6、检查牌型中的对子数量
这一部分的代码用于决定牌型中是否包含对子。注意这部分代码看起来 和普通javascript非常像,不包含任何约束定义或者信号操作。
这里是关于电路工作的一个直觉。现实生活中的电路可能需要一些预处理 或者中间评估,但是注意,这样的代码不会包含于正式的证据中,只有那些 约束会嵌入零知识证明公共参数中,并在证据生成和验证节点 。一个不诚实 的证明人可能会修改中间结果来伪造见证。
预处理环节的结果是一个单独的变量numPairs,在后面部分会用到。
这里的实现逻辑就是两重循环进行配对并计算对子的总数:
// Count pairsvar numPairs = 0;for (var i=0; i<4; i++) { for (var j=i+1; j<5; j++) { if (cards[i] == cards[j]) { numPairs++; // break doesn’t work. Just force j and i to exit j = 5; i = 5; } }}
7、零知识扑克牌游戏中的电路约束
在之前的入门教程中我们介绍了电路信号的操作符号:<–, –>,<==, ==>, 和 === 。 这个教程中我们引入新的符号:组件。组件就是类的实例,注意我们调用组件的方法, 组件的输入信号(a、b、c、in等等)被赋值并使用信号操作符。组件的数据信号也可以 类似方法使用。
在这里我们使用组件进行布尔运算,circomlib提供了不少电路组件可供我们利用。
同样,我们定义了约束,其中一个约束是检查选手是否做出了选择(fold、see或raise)。 另一个要检查的约束就是看是否存在对子。最终输出信号的值为1。
// isRaise = (raise != 0)isRaise<-- (raise >0);isBid<-- (isRaise || isSee); // Constraint: Must be either bid or fold: isBid XOR isFold = 1hasChosen<-- isBid + isFold — 2*isBid*isFold;hasChosen === 1; // Constraint: numPairs must be >0 if isBid = 1var hasPairs = (numPairs >0);component not3 = NOT();not3.in<-- isBid; component or2 = OR();or2.a<-- hasPairs;or2.b<-- not3.out;or2.out === 1; out<-- or2.out;
8、零知识电路的公共参数设置、证据生成和验证
首先利用电路进行设置,生成公共参数:
circom poker.circom -o poker.jsonsnarkjs setup -o poker.json
接下来需要提供输入,例如下面这个简单的输入文件input.json:
{“cards”: [8, 7, 4, 7, 13], “isFold”: 0, “isSee”: 0, “raise”: 10 }
这手牌里包含一个对子,因此所有的叫牌选项都可用。选手选择了加注10。 我们预期这个输入是有效的。输入信息中只有cards是私有的,而其他西悉尼都是 公开的。
现在来生成证据:
snarkjs calculatewitness -c poker.jsonsnarkjs proof
证据生成的性能复杂度为O(n),其中n表示电路中约束的个数。因为 我们的电路很简单,因此约束很少,证据生成也快。如果你的电路中有 非常多的约束就需要更多的时间生成证据,你可以查看这个测试 来了解电路性能与约束数量的关系。
现在用验证器来验证证据:
PS C:\dev\snarks\poker>snarkjs verifyOK
的确和预期一样!
用户评论
这个教程太棒了!我已经开始尝试自己搭建零知识游戏平台了,虽然目前还遇到了一些小问题,但我相信通过不断学习和实践,最终就能实现理想的目标。感谢作者分享如此宝贵经验!
有10位网友表示赞同!
零知识扑克牌?真是个有趣的概念!一直在寻找一些新的区块链应用,这个教程正好给了我启发,打算花些时间深入研究一下Circom和Snarkjs,看看能不能开发出自己的游戏。
有8位网友表示赞同!
说实话,我对这种技术很迷惑,好像听起来非常复杂。但我还是很欣赏作者的创作精神,愿意用这么专业的工具去打造这样的游戏,确实很有创新性!
有12位网友表示赞同!
零知识证明一直是我比较感兴趣的方向,这篇教程很好的介绍了Circom和Snarkjs的使用方式,特别是针对游戏应用的解释非常实用,值得收藏!不过希望之后作者能分享一些更深入的案例或者实战经验。
有20位网友表示赞同!
感觉这个教程有点过于细节,刚开始看的时候完全不知道从何下手。我比较建议加入一些基础概念的讲解,方便像我这种新手更容易理解。
有10位网友表示赞同!
玩零知识游戏确实很有乐趣,因为你并不需要担心别人的作弊行为。这篇教程让我更加了解背后技术的原理,感觉以后可以尝试自己开发一些类似的游戏了!
有6位网友表示赞同!
这款游戏的安全性非常高,因为它利用零知识证明来确保玩家之间的交易公平公正。这对那些喜欢玩网络游戏并且重视数据安全的人来说是一个很好的选择。
有18位网友表示赞同!
还是比较想了解更多关于Snarkjs的具体应用场景,这篇教程主要介绍了Circom,后续能够结合一些实际案例或者开源项目讲解一下Snarkjs的使用方法会更加完善。
有18位网友表示赞同!
这个零知识扑克牌游戏听起来很有意思,但我对区块链技术和相关的编程语言还不是很了解。希望作者能提供一些更容易理解的入门教程,这样我就能更好地参与到这个有趣的项目里。
有12位网友表示赞同!
我觉得这篇文章写得非常清晰易懂,虽然我对零知识证明并不是很熟悉,但是通过阅读后已经基本明白了它的作用和原理。推荐给所有对区块链技术感兴趣的朋友!
有10位网友表示赞同!
作为一名程序员,我很欣赏作者使用Circom和Snarkjs开发这个游戏的创意,也期待以后看到更多关于零知识游戏技术的应用场景。
有9位网友表示赞同!
我对这个游戏玩法本身并不太感兴趣,但是零知识证明的概念让我感到非常新奇。我相信这种技术未来会逐渐普及,并在更多的领域发挥作用,期待更多的开发者可以加入到这个发展浪潮中!
有12位网友表示赞同!
我觉得教程的示例代码量有点少,能提供更多实际案例或者项目实战经验会更有帮助。
有14位网友表示赞同!
在开发过程中遇到了很多问题,希望作者能及时更新教程,并增加一些故障排查和常见问题的解答内容。
有16位网友表示赞同!
非常期待看到这款零知识扑克牌游戏的开源代码,希望能学习到更多关于其开发技术的细节。同时也建议作者可以加入一个社区论坛,方便大家互相交流经验和探讨项目思路。
有10位网友表示赞同!
我对教程的目标用户群的设定有些疑问,它似乎更适合对零知识证明和区块链技术有一定了解的用户,对新手来说可能比较难入门。
有11位网友表示赞同!
感觉这个视频教程讲得还不错,将复杂的理论概念用通俗易懂的方式讲解,并且举例说明了零知识游戏的发展方向。虽然我还没开始动手操作,但已经对开发这款游戏的思路有了初步了解!
有13位网友表示赞同!
希望以后作者能够进一步完善教程,提供一些更实用的案例和实战技巧,比如如何实现游戏内资产的管理以及使用不同的加密算法来保障玩家的隐私安全等
有8位网友表示赞同!