我们想研究这种加密数字货币的“掷硬币”系统的真正原因是,如果我们可以据此设计一个安全协议的话,也可以用这个技术来设计其他有趣和有用的协议。密码学专家研究“多方参与的安全计算”,也就是说多个互相不信任的参与者,每个主体都有各自的数据,然后综合各主体的数据来共同计算一个结果,但同时每个主体都不想让其他参与者知道自己的数据是什么。想象一个类似的场景,一次竞价拍卖,但没有一个可靠的拍卖行。通常这些计算需要被随机化,来打破互相之间的关联,最后,这个计算的结果是有金融属性的,并且是不可逆转的。比如,我们想要保证中标者最后会付款给拍卖物品的卖方,更进一步,让卖方的(智能)资产自动转移到中标者的名下,甚至更进一步,我们还想要惩罚那些不守规矩的人。
第一回合:
每个参与者选择一个大的任意字符串。爱丽丝选x,鲍勃选y,卡罗尔选z。
每个参与者发布对应的哈希函数值H(x)、H(y)、H(z)。
每个参与者验证H(x)、H(y)、H(z)具有明显的差异性(否则放弃这个协议)。
第二回合:
三个参与者分别披露他们所选的字符串x、y和z。
每个参与者查证这些字符串是否与第一回合里发布的函数值相吻合。
最后的输出是(x+y+z)%3。
接下来,爱丽丝和鲍勃会同时签下一个交易,把这个保证金支付给鲍勃(两种情形之一)。但为什么爱丽丝会同意这样做呢?这个交易带有一个nLockTime值来保障鲍勃不能在时间点t之前来赎取保证金。因为,在此时间之前,爱丽丝只要愿意披露她的约定随机值,她就可以赎回这个保证金,所以她的这个签名交易是安全的。见图9.5。
可以在比特币系统上实施这个博彩系统。但这个系统有些复杂,而且有时限的函数约定还要求多个非标准的交易。当系统里有n个玩家的时候,由于每个玩家都要设置一笔保证金,我们需要n2个约定,此外玩家们还不得不投入比全部赌注更多的资金用来托管保证金。但对于参与者较少的游戏来说,这是合理的,并且有更好的效率。最重要的是,这个游戏验证了本来认为不可能的数据交换协议,比如在线掷虚拟硬币,并对不遵守规则的玩家进行惩罚,在比特币的世界里是可以做到的。
图9.5 在有时限的哈希函数约定中使用输出脚本和输入脚本的交易输出
我们所要做的是立下一个规矩:参与者若是做出承诺,则必须在一定的时间内披露所选的随机数。在密码学里,这个特性叫作公平性。比特币提供了一个非常好的解决方法。
如果他们都是完全独立地选择随机数的话,这个方法是可行的。但请记住,这是在互联网上,没有办法可以限制他们绝对地“同时”送出数据。爱丽丝可能会等到鲍勃和卡罗尔送出随机数之后再发布她的数据。这样一来,她可以轻易地操纵这个计算的结果。我们没有办法设计出一个数据交换协议,它可以让大家都相信没有人会作弊。
要是有人不披露约定怎么办?在这个协议的第二回合里,假设卡罗尔一直等到爱丽丝和鲍勃披露他们的秘密随机数,然后,在披露之前,意识到她会输掉这一局,她就有可能拒绝公布她的随机数——她可以说她忘记了或是假装下线。爱丽丝和鲍勃可能会怀疑,但他们也没有什么好的办法去追查。
这种数据协议之所以能成功是因为以下因素:第一,因为函数的输入x,y,z是大的任意数,没有人可以在第一回合之后预测其他人的输入;第二,如果爱丽丝按照规则任意地选择她的输入,她可以相信,不管鲍勃和卡罗尔是否选择了随机数,最后的输出结果也是随机的。
为了解决这个问题,我们还是要回到函数约定。首先,每一个人选一个大的随机数,并发布它的哈希函数值;然后,每个人披露各自所选的数字;接着,其他两个人查证这个被披露的函数值和在第一步发表的数据是否正确;最后,计算这个三个随机数的结果,如下:
初看起来,这个应用有些古怪,并且有局限性,并不值得深入研究。非常有意思的是,一个基于比特币的在线博彩系统中本聪之骰,已经被证明非常受欢迎,但它并未采用上述设计模式,而是依赖于某一方的信用,但它时不时地囊括了大部分比特币网络上的交易量。
爱丽丝和鲍勃想要下一个5美元的赌注。他们在下注之前商量好了游戏规则。鲍勃往空中扔一个硬币,爱丽丝在硬币落地之前叫出“正”或“反”面。当硬币落地的时候,可以立即判断谁是赢家。双方都知道这个结果有足够的随机性,他们之中任何一人都没有办法影响结果。
比如爱丽丝想要做出一个有时限的约定承诺,但鲍勃是唯一对此有顾虑的。第一,爱丽丝先设置一定的保证金,比特币支出交易的脚本可以用来规定,这笔保证金只能用以下两种支付情形:第一种支付情形是必须同时有爱丽丝和鲍勃两人的共同签名;第二种支付情形是只要爱丽丝披露了她的随机数,以后消费这笔交易,就只需要有爱丽丝的签名。如果爱丽丝所选择的随机字符串是x,那么输出脚本(ScriptPubkey)会包括哈希函数H(x)的值。
为了使双方相信这个游戏是公平的,游戏的步骤顺序以及硬币的特性至关重要。但上述设计有一个缺陷,就是他们二人都必须同时在场,而且相信对方会愿赌服输。在线上,我们也想设计一个同样“公平”的博彩系统,同时确保输家也会愿赌服输。
第一个挑战是找到与“掷硬币”相对应的线上的相关方法。假设我们有三个参与者:爱丽丝、鲍勃和卡罗尔,大家都想以相同的概率来选择一个号码1、2、3。我们尝试以下协议:每个人选择一个大的随机数,比如爱丽丝选x、鲍勃选y、卡罗尔选z,然后互相告知各自的随机数,并共同计算结果(x+y+z)%3。
总而言之,一个安全的多方博彩系统虽然看起来简单,但其实可以用来研究一个非常强大的系统模式:各自都有敏感数据的互不信任的一群参与者,共同来执行一个程序,不仅仅是为了控制数据,还可以控制与之关联的资金。
如果爱丽丝在弃局之前没有披露她的约定随机数值,那么鲍勃就可以在时间点t之后赎取该保证金。没有人逼迫爱丽丝披露她的随机数,但如果她不披露,她会因此失去预设的保证金。
我们如何用这个有时限的函数约定来实现安全的博彩系统?其实,架构和之前几乎一样,差别在于,我们不再采用简单的函数约定,而是采用有时限的函数约定。任何一方,要赎回这笔保证金就必须把正确的随机数值x披露出来;如果在最后期限到来时还不披露出他的随机数值,就会放弃他的保证金,以用来补偿其他两个玩家。
我们现在来讨论一下如何在比特币里举行一个“掷硬币”的游戏。首先看一下,在线下是如何建立这个系统的。