隨機(jī)數(shù)
Solidity 中最好的隨機(jī)數(shù)生成器是 keccak256
哈希函數(shù).
// 生成一個(gè)0到100的隨機(jī)數(shù):
uint randNonce = 0;
uint random = uint(keccak256(now, msg.sender, randNonce)) % 100;
randNonce++;
uint random2 = uint(keccak256(now, msg.sender, randNonce)) % 100;
這個(gè)方法很容易被不誠(chéng)實(shí)的節(jié)點(diǎn)攻擊
在以太坊上, 當(dāng)你在和一個(gè)合約上調(diào)用函數(shù)的時(shí)候, 你會(huì)把它廣播給一個(gè)節(jié)點(diǎn)或者在網(wǎng)絡(luò)上的 transaction
節(jié)點(diǎn)們。 網(wǎng)絡(luò)上的節(jié)點(diǎn)將收集很多事務(wù), 試著成為第一個(gè)解決計(jì)算密集型數(shù)學(xué)問(wèn)題的人,作為“工作證明”咽袜,然后將“工作證明”(Proof of Work, PoW)
和事務(wù)
一起作為一個(gè) block
發(fā)布在網(wǎng)絡(luò)上。
一旦一個(gè)節(jié)點(diǎn)解決了一個(gè)PoW
, 其他節(jié)點(diǎn)就會(huì)停止嘗試解決這個(gè) PoW
, 并驗(yàn)證其他節(jié)點(diǎn)的事務(wù)列表是有效的挺举,然后接受這個(gè)節(jié)點(diǎn)轉(zhuǎn)而嘗試解決下一個(gè)節(jié)點(diǎn)。
這就讓我們的隨機(jī)數(shù)函數(shù)變得可利用了
我們假設(shè)我們有一個(gè)硬幣翻轉(zhuǎn)合約——正面你贏雙倍錢(qián)烘跺,反面你輸?shù)羲械腻X(qián)湘纵。假如它使用上面的方法來(lái)決定是正面還是反面 (random >= 50 算正面, random < 50 算反面)。
如果我正運(yùn)行一個(gè)節(jié)點(diǎn)滤淳,我可以 只對(duì)我自己的節(jié)點(diǎn) 發(fā)布一個(gè)事務(wù)梧喷,且不分享它。 我可以運(yùn)行硬幣翻轉(zhuǎn)方法來(lái)偷窺我的輸贏 — 如果我輸了脖咐,我就不把這個(gè)事務(wù)包含進(jìn)我要解決的下一個(gè)區(qū)塊中去铺敌。我可以一直運(yùn)行這個(gè)方法,直到我贏得了硬幣翻轉(zhuǎn)并解決了下一個(gè)區(qū)塊屁擅,然后獲利偿凭。
所以我們?cè)撊绾卧谝蕴簧习踩厣呻S機(jī)數(shù)呢?
因?yàn)閰^(qū)塊鏈的全部?jī)?nèi)容對(duì)所有參與者來(lái)說(shuō)是透明的, 這就讓這個(gè)問(wèn)題變得很難派歌,目前沒(méi)有標(biāo)準(zhǔn)答案弯囊。
盡管這個(gè)方法在以太坊上不安全,在實(shí)際中胶果,除非我們的隨機(jī)函數(shù)有一大筆錢(qián)在上面匾嘱,你游戲的用戶一般是沒(méi)有足夠的資源去攻擊的。