这个问题来自于一个好友群,大家讨论起组一周CP的事情(就是假装谈恋爱一周),聊到怎么随机分配组合,发现了现在这个问题:有10个男生,10个女生,大家都在网络上没法实际见面,怎么设计一个抽签系统,在组织者本身也不可信的情况下,保证抽签过程无法作弊,而结果尽可能随机。
最初方案
- 组织方写程序跑。这是最初的想法,组织方写个代码,将男女队列随机打乱,编号一样的为一组。组织方公开源码,跑完程序截图。但这个方案不可靠之处在于:a.源码和实际跑的代码不一定一致;b.截图可以修改;
- 改进方案是结果图采用gif动态图,保证展示的源码就是实际抽签的代码,且难以P图。但这个方案仍有空挡可钻:整个过程可以跑多次,生成数个gif,然后只给大家展示组织方想要的那个结果。
- 直播抽签,开个网络直播,从写代码到最终跑程序抽签全程被监视。这个方案我觉得的确没有空隙可钻了,但成本很高,需要直播整个过程。这就是所谓“中心化”的代价,保证中心可信需要的成本很高。
如果要去掉这个中心(组织者或裁判),改怎么办呢,去中心化有两个思路,一个是借助第三方,第二个是分散变量。
第三方方案
借助第三方其实本质上也仍然有“中心”,但这个第三方如果不涉及利益关系,就比参与者里面挑组织者略为可靠。第三方的思路有几种:
- 找一个不参与活动且有威望的人作为组织者。这是古老朴素的思路,我们班级选举的班主任,法院的法官其实都类似这种思路。但问题在于第三方的可靠性仍然会受到一些因素的影响:a.第三方和参与者的亲疏关系;b.第三方有可能被贿赂;c.第三方的喜好不同;
- 找一个第三方的程序。比如微博抽奖工具,微信红包。微博和微信属于极有公信力的产品,所以这种方案相当于选择了一个社会权威来做第三方。而问题在于:a.微博抽奖和微信红包不是专门针对这件事的,怎么去操作任然需要进一步制定方案; b.微博抽奖需要一个人去操作程序,变相又增加了一个中心。而微信红包没法一次性给出确定结果,效率很低。
分散变量方案
那我们来说今天的重点,分散变量的方案(或者叫分布式),怎么用最小的成本来保证抽签绝对可信度。下面是其中一个方案的思考过程:
- 变量分散最简单的办法:所有人在群里同时发1-10的数字,如果出现两个人数字相同,则凑一对,剩下人发1-9的数字。如果多人一样则忽略,继续一轮。这个方案的问题很明显:a.低效,很可能好几轮都没法出现一对唯一匹配的;b.有迹可循,可以根据前几轮写的数字看某个人的喜好数字;c.假如有两人要串通,仍然可以作弊。
- 变量分散到各个节点后,我们需要设计一个方案来保证任意一个变量都会影响最终结果:将两队人分别编号为0-9,每个人分别出一个1-10的数字,数字之和除以10的余数,该余数编号的人为本轮选出来的人。两组独立进行出两个人匹配为一对。这个方法杜绝了串通作弊的可能,20个数字里任何一个都将影响匹配结果。但仍然有漏洞:有人可以在看到别人出的数字后,快速计算出结果,再最后针对性出数字。即无法保证不同节点的同步。
- 解决这个问题,我们可以采用两队单独处理,结果确定后再互相通知,这样即便有人想利用时间差来出数字,也不知道另一队匹配的结果。但这样又增加了一些沟通成本和不透明度,且两队有人串通的话,还是有机会利用上面的漏洞。
- 三国演义里,周瑜和诸葛亮手心各自写了一个“火”,然后一起展开手,来说英雄所见略同。这算是一种留存机制,将答案先存到不可更改的地方再公布,可以避免某一方临时变化。如果是在线下,我们可以写在纸上再一起公布,但在线上怎么办呢?怎么确保每个人存的内容不被窥视,且不能更改,且只有一份呢?
- 哈希就是一个很好办法,大家统一一种哈希算法,每个人将自己所选数字哈希结果先公布,然后再公布数字本身。由于通过哈希结果无法得到原文,但很容易通过原文来验证哈希,这样就算最终公布不同步,由于哈希已经确定了,也没法再作弊了。
- 上面的办法其实还有漏洞,因为1-10的数字的某种哈希算法结果是固定的,有人只要提前计算并记住了这些数字的哈希值,还是可以利用不同步来作弊(这也是现在网上破解MD5的原理)。我们只需要每个人加上一个“特征字”就可以了,每个人的原文为“特征字+数字”,哈希结果就各有不同且没法推测了,最终每个人公布自己的特征字以及数字,其他规则一样,多一个用于校验的特征字。
截止到这一步,我大概构思的一种方案就成型了:AB分两组,分别编号为0-9,
其实看到“去中心化”、“分布式”这样的词时,大家肯定会想到区块链。区块链利用密码学来保证无法抵赖和破坏,同时用分布式来保证计算过程的可靠。我们的问题是去一个随机值,而非计算一个有准确答案的问题,所以没法直接用区块链模型去做。但我们可以将每次的抽签过程里,每个人出的数字和特征字作为按区块链的方式保存起来,下次活动继续在这个链上记载,可以确保将来没有人能否认自己的历史……