我尝试用Solidity写彩票合同。我在研究中发现了this方法,其中随机数是根据玩家的输入来计算的。现在,我尝试改进此算法。
到目前为止,这是我的算法:Algorithm (png)
在阶段1中,随机数的哈希值和随机数的哈希值与编号get的组合存储在合同中。
与旧方法相比,我从哈希计算中删除了公钥,因为它是随每个事务公开发送的。相反,我在阶段1中添加了nonce
。我猜这将阻止攻击者更好地创建彩虹表。
在第二阶段,玩家减轻数字和随机数。这样的计算可确保玩家无法更改数字或随机数:
function stage2 (uint256 _nonce, uint256 _number) external {
require (stage == Stage.TWO, "Stage TWO isn't active!");
require (players [msg.sender].nonceHash == keccak256 (abi.encodePacked (_nonce)), "Nonce isn't matching!");
require (players [msg.sender].noncePlusNumberHash == keccak256 (abi.encodePacked (_nonce + _number)), "Number isn't matching!");
require (players [msg.sender].number == 0, "You already submitted your number!");
players [msg.sender].number = _number;
winning_number = (winning_number ^ _number) % max;
// ...
}
我能看到的唯一问题是,最后一位玩家可以在释放其号码之前预先计算出最终结果。通过要求发送他的号码有资格赢得头奖,我们可以防止他从中受益。但是考虑以下情况:玩家A在提交n-1时获胜,而玩家B如果最后一个玩家提交其号码则获胜。然后,最后一个玩家可以选择A还是B赢。
我猜在很多用例中这不是一个大问题。但是,如果仍然需要防止这种情况,我发现了两种解决方案:
(I)仅在所有玩家提交其号码后才离开第二阶段。如果在给定的时间之后还剩下提交,请撤销整个合同(如果知道所有玩家的身份,可能会很有用。)
(II)每个玩家都必须随其提交的内容发送一笔保证金。在发送他的号码后,这笔存款会退还给玩家。
我的问题是:该算法中是否还有我到目前为止没有考虑过的其他奇怪情况?