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

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

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

Solidity隨機數生成

Solidity沒法建立隨機數。實際上,每一個建立隨機數的算法都是僞隨機的——沒有語言可以建立徹底隨機的數字。Solidity的問題在於複雜的算法成本過高,所以使用了更基本的解決方案。除此以外,Solidity代碼應該是肯定性的,由於它將在多個節點上運行。咱們須要一種可以生成一次隨機數的算法,並在多個節點上使用它。像時鐘時間這樣的東西不能用於生成隨機數,所以咱們必須查看其餘選項。做爲開發人員,你應該瞭解此問題,由於攻擊者可以在某些特定狀況下預測結果。node

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

算法自己執行如下步驟:android

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

讓咱們探討使用彩票智能合約示例建立隨機數的不一樣方法。用戶能夠經過向合約發送0.1以太以及0到250之間的整數來加入彩票。程序員

1.Block.timestamp&Block.difficulty

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

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

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

2.彩票輸入任意數據

咱們須要更多任意數據來挑選咱們的贏家。咱們可使用已經進入咱們的彩票智能合約的玩家的地址,可是咱們必須將其隱藏在其餘玩家以外,由於他們能夠濫用它。隱藏此信息是不可能的,由於它所有記錄在區塊鏈上。mongodb

提交給咱們的彩票智能合約的號碼可使用。用戶必須將他們選擇的號碼與他們的以太坊地址一塊兒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陷阱:以太坊的隨機數生成

相關文章
相關標籤/搜索