我用实值生成一个伪随机数。我理解区块链的确定性,以及使用先知作为种子的必要性。也就是说,我正在销售动态生成的随机项目,我使用下面的行来生成:
uint random = uint(keccak256(abi.encodePacked(msg.sender, block.number, newItemId)));在这个随机数中,我使用了调用者地址、块号和新条目id作为种子,在每一个buy()函数调用时都会增加。查看它时,它似乎很好,因为攻击者可以操纵发送方地址并通过几次尝试猜测块号,但是要获得可预测的newItemId将很困难,因为他们将不知道其他人是否同时购买,在块处理顺序中占据优先地位,并获得另一个ID。
一位矿工可以尝试挖掘有效的区块,并把它们扔出去,直到他们得到他们想要的奖励,但这方面的最高奖金将价值约300美元,这使得它不值得付出努力。
这有用吗,还是我漏掉了什么?是否有可能以一种我不知道的方式利用这一点?
发布于 2021-08-13 19:58:03
你在探索一个经典的稳健性问题:如何生成链上的随机数?
在没有熵的情况下,很难得到不可猜测的随机数。让我们检查一下您使用的随机性的来源:
msg.sender:不是随机的,是因为你提到的明显原因block.number:不是随机的:攻击者可以计算出哪个块会产生有利的结果,并在这个确切的块发送他的事务,并有足够的气体确保包含在其中。newItemId:除非每个区块的合同上都有很多交易,否则很容易猜到,因为它不会是随机的。即使每个区块有大量的交易,很难猜出哪个Id用于抽奖,矿工也可以操纵订单以获得有利的结果。任何其他值,例如block.coinbase,都会或多或少地遇到相同的问题。
请记住,对许多人来说,300美元的最高奖金可能就足够了--事实上,黑客本身往往是很有趣的。不要低估这个参数。此外,如果黑客可以很容易地重复,它可能是更多的加班。
产生随机数的更安全的方法:
blockhash(block.number + x):在本例中,您使用了两重方案:第一个事务记录未来的块号,其散列将用于创建RNG。在第二个事务中,您将显示此值并使用此RNG。这种解决方案的优点是非常直接和“便宜”,因为它不需要一个甲骨文。
它的缺点是需要一个节点来监视合同并发送一个事务来显示RNG。您可以要求用户这样做,但是要小心--它必须在接下来的256个块中完成,因为区块链只记得最后256个块散列。此外,您给这种方式的矿工有机会操纵块哈希,直到他得到一个有利的结果。
你说过你知道这个解决方案。我不会在这里刊登任何服务的广告,但如果你觉得它很贵,我可以推荐以下几点:
发布于 2021-08-13 23:42:05
除了使用无风险的随机数外,还有一种选择。以下是如何:
这样每个人都能百分之百肯定你没有作弊。这种方法唯一的问题是,随机数必须是20位或更大,所以不可能运行蛮力算法并生成哈希,以猜测您选择的随机数是多少。
稍后,您可以使用另一个函数将这个大随机数映射到您自己的问题域。我不知道这是否适用于你,但这是有多少人保护在区块链上的价值,而不透露实际价值。例如,虚名系统(ENS)使用了我所描述的相同的散列原理来注册域名(Ethereum域名),而不以英文文本显示实际名称。
https://ethereum.stackexchange.com/questions/107076
复制相似问题