我们可以在比特币网络上基于比特承诺方法实现一个公平且不需要第三方的掷硬币游戏。
假设 Alice 和 Bob 决定掷硬币,但他们没有实物硬币,或者他们想通过互联网进行。通过遵循下面这个比特币协议,他们可以实现公平的抛硬币。
- Alice 和 Bob 各自将 x 个比特币锁定在如下所示的智能合约中(注意:此时他们并没有透露自己的秘密数字);
- 在新交易里同时提交他们各自的秘密数字,然后对这两个秘密数字进行异或操作,以确定硬币是正面还是反面。如果是正面则 Alice 赢,否则 Bob 赢。获胜者将获得所有 2x 个比特币。
contract CoinToss {
Ripemd160 alice;
Ripemd160 bob;
// commitments
Sha256 aliceHash;
Sha256 bobHash;
public function toss(bytes aliceNonce, bytes bobNonce, int amount, SigHashPreimage txPreimage) {
require(Tx.checkPreimage(txPreimage));
require(hash256(aliceNonce) == this.aliceHash);
require(hash256(bobNonce) == this.bobHash);
// last bit of XOR
bytes head = (aliceNonce ^ bobNonce) & b'0000000000000000000000000000000000000000000000000000000000000001';
// head -> Alice wins; tail -> Bob wins
Ripemd160 winner = head ? this.alice : this.bob;
// winner takes all
bytes winnerScript = Util.buildPublicKeyHashScript(winner);
bytes winnerOutput = Util.buildOutput(winnerScript, amount);
require(hash256(winnerOutput) == Util.hashOutputs(txPreimage));
}
}
实践考虑
如果当事一方在发现自己失败的情况下拒绝透露其秘密数字,可能还需要采取其他措施改进。例如,可以让失败者拿回其投入的一半比特币,而不是让获胜者全部拿走,这样也可以激励失败者提交其秘密数字。