Solidity陷阱:以太坊的隨機數生成

title: Solidity陷阱:以太坊的隨機數生成

Solidity是一種相當新的語言,因爲沒有代碼是完美的,它包含與代碼相關的問題以及你希望用它完成的任務。本文將指導你使用隨機數作爲以太坊智能合約的輸入時的最佳實踐和陷阱。

Solidity隨機數生成

Solidity無法創建隨機數。實際上,每個創建隨機數的算法都是僞隨機的——沒有語言能夠創建完全隨機的數字。Solidity的問題在於複雜的算法成本太高,因此使用了更基本的解決方案。除此之外,Solidity代碼應該是確定性的,因爲它將在多個節點上運行。我們需要一種能夠生成一次隨機數的算法,並在多個節點上使用它。像時鐘時間這樣的東西不能用於生成隨機數,因此我們必須查看其他選項。作爲開發人員,你應該瞭解此問題,因爲攻擊者能夠在某些特定情況下預測結果。

最常用的算法之一是“線性同餘發生器”(LCG)。它是最古老的算法之一,快速且易於理解。LCG是嵌入式系統的一個很好的選擇,因爲它們的內存有限。但是,它不適合加密安全應用程序。雖然,這仍然在智能合約中使用,因爲快速算法在氣體成本方面實施起來便宜得多。

算法本身執行以下步驟:

  • 接受輸入。
  • 在輸入上執行算法。
  • 取輸出模數(除以你需要的範圍內的最大數量)。
  • 在你需要的範圍內輸出0到最大數字。

讓我們探討使用彩票智能合約示例創建隨機數的不同方法。用戶可以通過向合約發送0.1以太以及0到250之間的整數來加入彩票。

1.Block.timestamp&Block.difficulty

每當他確認交易時,礦工就會分配一個block.timestamp。我們的彩票合約的任何玩家都無法控制它。讓我們看看這段代碼來創建一個隨機數。

function random() private view returns (uint8) {
       return uint8(uint256(keccak256(block.timestamp, block.difficulty))%251);
   }

這段代碼首先hash了一個塊時間戳和難度。接下來,我們將hash轉換爲整數並將其除以251以獲得0到250之間的整數。但是,這段代碼的問題在於我們不應該信任礦工來挑選勝利者。

2.彩票輸入任意數據

我們需要更多任意數據來挑選我們的贏家。我們可以使用已經進入我們的彩票智能合約的玩家的地址,但是我們必須將其隱藏在其他玩家之外,因爲他們可以濫用它。隱藏此信息是不可能的,因爲它全部記錄在區塊鏈上。

提交給我們的彩票智能合約的號碼可以使用。用戶必須將他們選擇的號碼與他們的以太坊地址一起hash。這給了我們一個相當隨機的數字。

3.其他機制

3.1以太坊鬧鐘

開發人員需要考慮何時選擇勝利者。時間之類的東西在以太坊虛擬機中不可用,因爲代碼將在不同的時間在多個節點上運行。這使得挑選勝利者變得更加困難。實現這一目標的一種方法是在智能合約中實施一項功能,該功能將關閉彩票並選擇獲勝者。這不像我們希望的那樣去中心化。合約的所有者在確定他們的朋友將獲勝時可以關閉彩票。我們想避免這種作弊行爲。

更好的選擇是使用以太坊鬧鐘。它是一種允許稍後在以太坊區塊鏈上執行調度事務的服務。這項服務完全沒有信任,這意味着整個服務作爲智能合約運作。基本上,以太坊鬧鐘使用塊號來安排交易。注意,這並不意味着合約本身就會被喚醒。它依賴於有興趣的用戶(以太獎勵)來調用“挑選獲勝者”功能。當然,如果沒有人打電話給你的功能,你的彩票就會失敗。

3.2隨機數據輸入

Random.org提供了一個API,通過JSON爲你提供隨機數據源。以太坊智能合約可以使用此數據源來提供選擇隨機數的算法。由於安全性很重要,因此可以使用數字簽名。隨機數據將由Random.org簽署。你可以驗證數據的完整性,以便證明它確實來自Random.org並且數據未被篡改。

RANDAO是區塊鏈領域的一個新項目,專注於提供隨機數。他們使用oracles和智能合約的組合爲你提供隨機數字。但是,RANDAO服務目前相當緩慢。如果你擁有經常使用的應用程序,這並不理想。

3.3 Blocknumber Watcher

你還可以在代碼中使用觀察程序,它會檢查程序段編號,直到它與你設置的目標編號相匹配。

function f( blocknumber, to_address, value_) { 
  var filter = web3.eth.filter('latest').watch(
    function(err, blockHash) { 

      var target=blocknumber; 

      if(web3.eth.blockNumber==target) { 
        filter.stopWatching(); // your function here 
        web3.eth.sendTransaction({to:to_address, from:web3.eth.coinbase, value: web3.toWei(value_,"ether")});
        filter = null; 

        console.warn('Block reached'); 

        if (callback) return callback(false);
        else return false;

      } else { 
        console.log('Waiting the block'); 
      } 
  }); 
};

3.4 iOlite智能合約創建

iOlite正在創建一種接受自然語言來創建智能合約的產品。它使用稱爲快速自適應引擎(FAE)的斯坦福自然語言處理(NLP)引擎。iOlite依靠Solidity專家的社區培訓。Solidity專家(貢獻者)可以定義包含一個或多個句子的結構,並將其附加到相應的智能合約代碼。

斯坦福NLP引擎的創建是爲了理解複雜的語言。語言複雜程度取決於機器培訓的數量。經過適當的培訓,引擎將能夠創建複雜的智能合約。FAE能夠創建此類合約,因爲複雜的合約實際上並不複雜。專家可以將請求拆分爲多個較小的代碼並將其附加到一個句子中。

當有人輸入多個句子時,它會尋找相應的結構/句子來建立“複雜”的合約。貢獻者將通過新結構的挖掘過程獲得iOlite代幣獎勵。

使用iOlite的好處是智能合約專家可以像生成隨機數一樣爲你解決難題。你可以在iOlite.io上找到更多信息。

結論

如你所見,生成真正的隨機輸入並非易事。不要依賴block.timestamp,現在和block.blockhash作爲隨機源。一個好的解決方案包括幾個僞隨機數據輸入的組合以及使用oracles或智能合約來使其更可靠。你需要100%確定沒有人可以篡改輸入智能合約的數據。

在實現隨機數生成邏輯之前要小心並三思而後行。

======================================================================

分享一些以太坊、EOS、比特幣等區塊鏈相關的交互式在線編程實戰教程:

  • java以太坊開發教程,主要是針對java和android程序員進行區塊鏈以太坊開發的web3j詳解。
  • python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
  • php以太坊,主要是介紹使用php進行智能合約開發交互,進行賬號創建、交易、轉賬、代幣開發以及過濾器和交易等內容。
  • 以太坊入門教程,主要介紹智能合約與dapp應用開發,適合入門。
  • 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
  • C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括賬戶管理、狀態與交易、智能合約開發與交互、過濾器和交易等。
  • EOS教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智能合約開發與部署、使用代碼與智能合約交互等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
  • java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Java代碼中集成比特幣支持功能,例如創建地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
  • php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Php代碼中集成比特幣支持功能,例如創建地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
  • tendermint區塊鏈開發詳解,本課程適合希望使用tendermint進行區塊鏈開發的工程師,課程內容即包括tendermint應用開發模型中的核心概念,例如ABCI接口、默克爾樹、多版本狀態庫等,也包括代幣發行等豐富的實操代碼,是go語言工程師快速入門區塊鏈開發的最佳選擇。

匯智網原創翻譯,轉載請標明出處。這裏是原文Solidity陷阱:以太坊的隨機數生成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章