上篇文章中,我们使用 XOR 在比特币网络上进行了公平的抛硬币。今天我们来介绍另一种使用 Blum 原始协议 [^1] 来实现这个游戏的方法。
它包括以下步骤:
- Alice 选择质数 p 和 q。 他告诉 Bob 二者乘积 N = p * q。Alice 可以选择很大的 p 和 q ,这样 Bob 就无法进行从 N 进行反推;
- Bob 在 0 到 N 之间选择 x [^2],并计算 b =x² mod N。他告诉Alice 数值 b。 此步骤类似于在掷硬币之前就选择一个结果并作出承诺;
- Alice 计算 b 取模 N 的四个方根,分别是 x,y,N-x 和 N-y。 她选择 {x,N-x} 或 {y,N-y} 对中的一个并告诉 Bob。 该步骤对应于硬币的物理翻转;
- 如果 Alice 选择 {x,N-x},则 Bob 获胜,并且他可以通过告诉 Alice x 轻松证明这一点。除非 Bob 在第2步中选择了 x,否则他无法计算出这个数,因为他不知道 p 和 q;
- 如果 Alice 选择 {y,N-y},则她获胜。 因为 Bob 无法计算出 y,所以他不能通过告诉 Alice 这个数来作弊。
合约示例代码如下:
// fair coin toss using Blum's protocol
// Coin Flipping by Telephone. by Manuel Blum CRYPTO 1981
contract CoinToss {
PubKey alice;
PubKey bob;
// commitments
Sha256 aliceHash;
Sha256 bobHash;
// N = p * q
int N;
public function toss(int aliceNonce, int bobNonce, Sig sig) {
require(hash256(pack(aliceNonce)) == this.aliceHash);
require(hash256(pack(bobNonce)) == this.bobHash);
// Bob succeeds to guess Alice's toss
bool head = aliceNonce == bobNonce || aliceNonce == this.N - bobNonce;
// head -> Bob wins; tail -> Alice wins
PubKey winner = head ? this.bob : this.alice;
// winner takes all
require(checkSig(sig, winner));
}
}
[^1] Coin Flipping by Telephone: A Protocol for Solving Impossible Problems. Blum (CRYPTO 1981).
[^2] x 和 N 必须是互质的,以确保 4 个平方根