區(qū)塊鏈的隨機數(shù)之傷

你好,我是不羈烘挫,一名程序員诀艰,帶你玩轉EOS智能合約開發(fā)。如果你對EOS智能合約感興趣饮六,歡迎關注我的專欄其垄。

簡介:昨天我在為什么EOSBet不敢開源?一文中卤橄,和大家探討了EOS上隨機數(shù)的生成問題绿满。隨機數(shù)的生成問題的確是很多區(qū)塊鏈項目的硬傷,也是不少項目不愿意開源的原因之一窟扑。今天我們繼續(xù)探討怎樣生成隨機數(shù)喇颁,既能保證公平,又能讓黑客無法根據(jù)隨機過程提前預測隨機結果嚎货,從而避免項目方利益受損橘霎;同時本文會引出一個目前業(yè)界用的比較成熟的方案(其實仍稍欠完美,本文也會解析)殖属。

我們昨天留了這么個問題:

學過C++的都知道姐叁,向系統(tǒng)請求開辟一塊內存時,該內存的地址是不確定的洗显,那你覺得可以利用這個特點外潜,在智能合約中生成隨機數(shù)嗎?

不知道你有沒有寫個試驗代碼試試呢挠唆?不羈做過實驗橡卤,實驗過程就不在這里演示了。
這個問題的答案是损搬,雖然內存的地址生成我們是不確定的碧库,但對于虛擬機來說是確定的,在它每次實行時巧勤,相應執(zhí)行路徑上的變量的地址都是一樣的嵌灰。這是可以想見的,因為每次執(zhí)行action颅悉,虛擬機都是初始化一個新的運行沙盒環(huán)境沽瞭,相同的action,執(zhí)行過程也必然相同剩瓶,中間沒有任何不確定的因素擾動執(zhí)行過程驹溃,從而執(zhí)行過程也都是可以確定的城丧。這樣黑客把你的代碼完全拿過來,然后打印出相關變量的地址豌鹤,就可以確定了亡哄。而因為每次執(zhí)行都一樣,所以黑客在本地打印的結果也就是你在主網(wǎng)上運行時相關變量的地址布疙。
可見蚊惯,利用隨機開辟的內存地址作為隨機種子也是不可取的。

隨機種子

我剛才用到了隨機種子這個詞灵临,什么是隨機種子呢截型?因為隨機過程是計算機程序,程序分兩種儒溉,一種是無狀態(tài)的宦焦,一種是有狀態(tài)的。
無狀態(tài)的程序顿涣,每次對于相同的輸入總是給出相同的輸出赶诊,也就是說,只要你給我一個輸入园骆,我都可以私下把程序運行一下舔痪,然后給你一個結果,你自己再執(zhí)行一次锌唾,也必要是這個結果锄码。
有狀態(tài)的程序,雖然每次的執(zhí)行結果可能不同晌涕,但只要你告訴我初始狀態(tài)滋捶,我也可以根據(jù)你每次給的輸入,預測出它的輸出余黎。
嚴格來數(shù)重窟,所有的隨機過程都是有狀態(tài)的計算機程序。而隨機種子呢惧财,就相當于它的初始狀態(tài)巡扇,或者可對它的當前狀態(tài)產(chǎn)生一個不可預測的擾動,變成另外一個狀態(tài)垮衷。
所以假如你想讓你的隨機數(shù)是不可預測的厅翔,你必須保證隨機種子是不可預測的。
這樣我們就可以把產(chǎn)生隨機數(shù)的機理分成兩部分了搀突,一部分是隨機種子刀闷,一部分是隨機過程。只要隨機種子不公開,把隨機過程公開甸昏,那么黑客也就無法對產(chǎn)生的隨機數(shù)進行預測了顽分。隨機過程可以寫在智能合約里,隨機種子就需要外界的輸入了施蜜,并且是不可預測的外界輸入卒蘸。只要隨機種子是不可預測的,那么隨機結果也就是不可預測的了花墩。

我前面討論過悬秉,用時間和wasm虛擬機分配的內存地址都是可以預測的澄步,盡管預測的難度有點技術大冰蘑,但還是能預測的,所以都不是良好的隨機種子村缸。
什么是良好的隨機種子呢祠肥?因為虛擬機執(zhí)行過程的確定性,所以這個隨機種子我們不能從虛擬機中來找了梯皿,只能從外界來找了仇箱。

利用區(qū)塊中的數(shù)據(jù)作為隨機種子

昨天有一位同學在留言中提到了這個想法,他是這么說的:


Screen Shot 2018-09-22 at 09.21.43.png

他提到使用當前區(qū)塊的hash值作為隨機種子东羹,這是很好的想法剂桥。
目前EOS的實際使用的tps平均在16左右,一般情況下属提,每個區(qū)塊都不止一個交易权逗,也就是說,黑客發(fā)起的攻擊性交易總會伴隨著其他的交易冤议,而其他的交易數(shù)據(jù)是黑客無法預測的斟薇,所以用當前區(qū)塊的hash值作為隨機種子是比較優(yōu)良的隨機種子

然而恕酸,據(jù)我目前所知堪滨,當前EOS智能合約中還沒有獲得當前區(qū)塊的hash值的接口,如果你發(fā)現(xiàn)了蕊温,歡迎告訴我袱箱。倒是有獲取當前action所在的transaction的數(shù)據(jù),對于dice合約而言义矛,這個東西黑客就是可以預測的了犯眠,因為交易是由黑客主動發(fā)起的,它完全知道自己的數(shù)據(jù)症革。

EOS智能合約中筐咧,還有獲得當前區(qū)塊的blocknumber以及當前交易的ref block的接口,不過這些也不能作為隨機種子,前者是可以預測的量蕊,后者是黑客可以自己指定的铺罢。

一個可能的方案

經(jīng)過我們的分析發(fā)現(xiàn),目前在EOS上残炮,好的隨機種子無法在智能合約內部獲得韭赘,那么只能求助外界了。我們看看外界目前有什么公共的或許可用的不可預測的噪音數(shù)據(jù)势就,我列出了如下幾條:

  • RAM的交易數(shù)據(jù)
  • 某些活躍度比較高的dapps公開的數(shù)據(jù)

這些數(shù)據(jù)的確是不可預測的泉瞻,任何一秒鐘都可能發(fā)生變化,并且變化的方式是極難預測的苞冯,他們可以作為隨機種子的一部分袖牙,但如果單純依靠它們中的任何一個,都是不夠可靠的舅锄。以RAM的交易數(shù)據(jù)為例鞭达,交易往往幾秒鐘才有一次,變化頻次不夠皇忿,黑客完全可以在這個變化的空檔期下手畴蹭。最活躍的賬號,和活躍的dapps公開的數(shù)據(jù)也是如此鳍烁,不過如果把它們結合起來一起用作隨機種子叨襟,可靠性會高很多。

不過這種方式也有缺點:

  1. 太依賴于別人的公開數(shù)據(jù)了幔荒,如果別人的數(shù)據(jù)格式變了糊闽,你的智能合約可能也要跟著更新
  2. 如果這些公開的數(shù)據(jù)變化的頻率,有時高铺峭,有時低墓怀,你必須收集足夠多的頻繁變化公開數(shù)據(jù)才能確保每時每刻的不可預測性
  3. 目前EOS上滿足條件的可作為隨機種子使用的公開數(shù)據(jù)仍然比較少

成熟可靠的方案

我們仍然需要沿著前面的思路,好的隨機種子只能從我們自己的智能合約以外去尋找卫键。我們發(fā)現(xiàn)其他的dapps的智能合約的公開的傀履、并且變化的數(shù)據(jù)可以作為隨機種子,但因為現(xiàn)階段EOS上的生態(tài)還在起步階段莉炉,可以作為隨機種子的數(shù)據(jù)還是太少钓账,可靠性不足。

那怎么辦呢絮宁?讓游戲的參與方提供隨機種子梆暮。

dice游戲為例,雙方同時提供隨機種子绍昂,然后智能合約把這兩個種子一起作運算啦粹,這個運算算法是公開的偿荷。因為雙方是同時提供的,所以任何一方都無法提前預知對方的種子是什么唠椭,自然無法對結果做出預測跳纳。
“可是不行啊,同時提供種子贪嫂,這在實操中很難辦到八伦!”
是的力崇,的確如此斗塘。不過可以用另外一個方法來解決這個問題。
EOSIO提供了一個dice的示例合約亮靴,它是兩個玩家一起玩馍盟,不像EOSbet那種是玩家和項目方玩的。

我們先看看EOSIO提供的dice示例的玩法:

  1. 用戶A和B各有一個自己的種子台猴,分別是seedAseedB朽合,但一開始互相保密的俱两。
  2. A對seedA進行hash運算饱狂,生成seedA_hash,然后把seedA_hash發(fā)給智能合約宪彩。
  3. B對seedB進行hash運算休讳,生成seedB_hash,然后把seedB_hash發(fā)給智能合約尿孔。
  4. 在上面的步驟完成之后俊柔,A把seedA發(fā)送給智能合約
  5. B把seedB發(fā)送給智能合約
  6. 智能合約先驗證A和B的seed,驗證通過后活合,再對兩個seed進行運算雏婶,根據(jù)運算結果判定輸贏。

在1白指,2之后留晚,B雖然先看到了A的seedA_hash,但因為hash運算的性質告嘲,B無法通過seedA_hash計算出seedA错维,而智能合約的運算過程是對雙方的seed進行的,所以B此時無法通過調整自己的seed來影響運算結果的傾向性橄唬。于是B也只能老老實實的生成一個隨機的seedB赋焕,并進行hash運算。

在5步的時候仰楚,B看到了seedA隆判,自己還沒有發(fā)送seedB犬庇,那這個時候他可以調整seedB來影響結果了嗎?不行侨嘀,因為第6步械筛,智能合約會對seed進行有效性驗證,具體是判斷這個等式是否成立:

hash(seed) == seed_hash 

如果不成立飒炎,就代表這個驗證失敗了埋哟。seed_hash是玩家在第2和3步已經(jīng)發(fā)送給智能合約了的。同樣因為hash的性質郎汪,你想生成另外一個seed同時還能滿足上面的等式赤赊,是相當困難對策。

通過這種方式煞赢,dice的玩家雙方就可以不用顧慮誰先出示seed_hash了抛计,也不用擔心誰先出示seed了,這個過程巧妙的利用了hash運算的性質:

  1. 很難根據(jù)hash(seed)的結果倒推出seed
  2. 不同的seed進行hash之后照筑,生成的結果極大概率是不同吹截。這個極大概率無限接近于100%

hash運算在加密領域應用非常廣泛,并且有多種不同的hash算法凝危,這里就不展開了波俄。

改進的版本

上面的方案中,玩家雙方都各生成了一個隨機種子參與運算蛾默,所以任何一方都無法提前預測隨機結果懦铺,對于雙方都是公平的。

我們假設A支鸡、B雙方中冬念,A是用戶,B是項目方牧挣。項目方提供智能合約急前,并開源,然后采用上面的玩法瀑构,可以嗎裆针?

完全可行,B的相關操作可以根據(jù)A的請求自動執(zhí)行检碗,但A的操作就變復雜了据块。
dice合約為例,對于A而言折剃,最好的體驗是像EOSBet那樣另假,用戶只需要進行一次操作,即可得到輸贏的結果怕犁。然而在上面的方案中边篮,A卻需要兩步:第一步是向合約發(fā)送seed_hash己莺,第二步是向合約發(fā)送seed

如何做到用戶A只需要一步合約操作就可以得到結果呢戈轿?
方案是有的凌受,我們再回頭看看上面的過程,第2步和第3步是可以替換的思杯,像下面這樣:

  1. 用戶A和B各有一個自己的種子胜蛉,分別是seedAseedB,但一開始互相保密的色乾。
  2. B對seedB進行hash運算誊册,生成seedB_hash,然后把seedB_hash發(fā)給智能合約暖璧。
  3. A對seedA進行hash運算案怯,生成seedA_hash,然后把seedA_hash發(fā)給智能合約澎办。
  4. 在上面的步驟完成之后嘲碱,A把seedA發(fā)送給智能合約
  5. B把seedB發(fā)送給智能合約
  6. 智能合約先驗證A和B的seed,驗證通過后局蚀,再對兩個seed進行運算麦锯,根據(jù)運算結果判定輸贏。

我們可以看到第3步和第4步是緊挨著的至会,于是我們就可以把它合成一個操作了离咐。變成一個步驟之后谱俭,seedA_hash就不用提供了奉件,因為seedA_hash本身是為了校驗seedA的,現(xiàn)在在這個一次操作已經(jīng)給了seedA昆著,那么seedA_hash就沒有存在的必要的县貌。
如此,改進后的版本就變成下面這樣:

  1. 用戶A和B各有一個自己的種子凑懂,分別是seedAseedB煤痕,但一開始互相保密的。
  2. B對seedB進行hash運算接谨,生成seedB_hash摆碉,然后把seedB_hash發(fā)給智能合約。
  3. A把seedA發(fā)送給智能合約
  4. B把seedB發(fā)送給智能合約
  5. 智能合約先驗證B的seedB是否合法脓豪,驗證通過后巷帝,再對兩個seed進行運算,根據(jù)運算結果判定輸贏扫夜。

如此就實現(xiàn)了用戶只需要一次智能合約交互即可楞泼,但項目方B還是需要做兩次智能合約交互驰徊,能不能再改進呢?

能的堕阔。
項目方B可以把seedB_hash交給A棍厂,并由A在與智能合約的交互中帶上。于是超陆,整個過程就變成這樣了:

  1. 用戶A和B各有一個自己的種子牺弹,分別是seedAseedB,但一開始互相保密的时呀。
  2. B對seedB進行hash運算例驹,生成seedB_hash,然后把seedB_hash交給A退唠。
  3. A把seedA以及seedB_hash發(fā)送給智能合約
  4. B把seedB發(fā)送給智能合約
  5. 智能合約先驗證B的seedB是否合法鹃锈,驗證通過后,再對兩個seed進行運算瞧预,根據(jù)運算結果判定輸贏屎债。

這樣A和B與智能合約就分別只有一次交互了(省了點鏈上的資源消耗),而是在A和B之間增加了一次交互(鏈下的)垢油,很容易看出這次交互是安全的盆驹。
對于dice合約來說,每次的游戲都是玩家發(fā)起的滩愁,也就是A發(fā)起的躯喇,而項目方B則是被動的,所以當A在把seedA發(fā)送給智能合約之前硝枉,本身就需要通知B去生成seedBseedB_hash廉丽,于是B就可以在收到A的通知的時候,順便把seedB_hash返回給A妻味。

EOSBet或許也是這么做的正压,但因為它沒開源,我們不敢定論责球。不過倒是有一個開源的仿EOSBet的dapps: fairdicegame焦履,它的合約源碼在這里。這個項目使用的就是改進后的方案雏逾,不過因為它涉及到需要讓玩家A知道B是預先生成的seedB嘉裤,所以它會把seedB_hash預先發(fā)送給A,由A在與智能合約的交互中栖博,把seedB_hash也帶上屑宠。
首先聲明一下,我和該項目沒有任何關系笛匙,卻無意間替他們做了宣傳侨把,我把他們的合約代碼地址放在這里犀变,主要是因為比較欣賞他們這種把合約開源的態(tài)度,同時也是為了方便智能合約的開發(fā)者們學習秋柄。

還能再改進嗎获枝?

上面方案從用戶使用的角度已經(jīng)能夠滿足需要了,同時也保證了公平公正骇笔,但在自證清白方面不夠徹底省店。因為在玩家操作期間,客戶端除了和智能合約有交互外笨触,客戶端還需要服務端進行一次交互懦傍,主要是為了在為玩家生成seed以前,獲取服務端的seed_hash芦劣,然后把服務
智能合約代碼已經(jīng)公開了粗俱,可以自證清白,但服務端就很難了虚吟。

fairdicegame為例寸认,首先它的服務端沒有開源,其次串慰,即便它開源了也無法自證清白偏塞,因為沒辦法驗證它開源的版本與實際使用的版本是同一個版本。智能合約因為可以進行源碼驗證邦鲫,所以沒有這個問題灸叼。

我看了一下fairdicegame與服務端交互的數(shù)據(jù),從幾次的試驗來看庆捺,客戶端是在收到服務端的seedB_hash之后古今,再把自己的seedAseedB_hash發(fā)送給服務端的,所以服務端在生成seedB的時候疼燥,是不知道seedA的沧卢,從而可以認為fairdicegame對于玩家來說還是比較公平的。不過因為客戶端的代碼和服務端代碼都完全是由項目方控制的醉者,假如項目方不定時的給了用戶另一個不公正的版本,用戶也很難感知到披诗。

你可能會說:“你是不是太嚴格了點兒撬即?”

是的,的確是嚴格了點呈队,我只有不停的嚴格要求自己剥槐,才能做出讓用戶更加可信的dapps。

另一方面宪摧,這種方式產(chǎn)生隨機數(shù)的方式粒竖,嚴格依賴于雙方共同參與隨機數(shù)的生成過程颅崩,盡管某些程序可以對交互邏輯進行優(yōu)化,但還是比較復雜蕊苗,這種復雜性也增加了隨機數(shù)生成場景的通用性沿后,比如區(qū)塊鏈游戲中生成寶物的隨機算法,完全是官方隨機生成的朽砰,整個過程無需用戶參與尖滚,上面適用于dice的隨機數(shù)生成機制在這里就不合適了。

那如何改進呢瞧柔?
我們節(jié)后再探討漆弄。
國慶節(jié)快樂!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末造锅,一起剝皮案震驚了整個濱河市撼唾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哥蔚,老刑警劉巖券坞,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肺素,居然都是意外死亡恨锚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門倍靡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猴伶,“玉大人,你說我怎么就攤上這事塌西∷妫” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵捡需,是天一觀的道長办桨。 經(jīng)常有香客問我,道長站辉,這世上最難降的妖魔是什么呢撞? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮饰剥,結果婚禮上殊霞,老公的妹妹穿的比我還像新娘。我一直安慰自己汰蓉,他們只是感情好绷蹲,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般祝钢。 火紅的嫁衣襯著肌膚如雪比规。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天拦英,我揣著相機與錄音蜒什,去河邊找鬼。 笑死龄章,一個胖子當著我的面吹牛吃谣,可吹牛的內容都是我干的。 我是一名探鬼主播做裙,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼岗憋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锚贱?” 一聲冷哼從身側響起仔戈,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拧廊,沒想到半個月后监徘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡吧碾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年凰盔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倦春。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡户敬,死狀恐怖,靈堂內的尸體忽然破棺而出睁本,到底是詐尸還是另有隱情尿庐,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布呢堰,位于F島的核電站抄瑟,受9級特大地震影響,放射性物質發(fā)生泄漏枉疼。R本人自食惡果不足惜皮假,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望往衷。 院中可真熱鬧钞翔,春花似錦、人聲如沸席舍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽来颤。三九已至汰扭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間福铅,已是汗流浹背萝毛。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留滑黔,地道東北人笆包。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像略荡,于是被迫代替她去往敵國和親庵佣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容