以太坊原始碼分析(54)以太坊隨機數生成方式

尹成發表於2018-05-14
最近考慮一個基於以太坊的去中心化賭場的實現, 賭場如果需要實現,那麼隨機數是必須的。 然後研究了一下以太坊裡面的隨機數生成,
發現並不容易。


以太坊裡面生成隨機數的幾種方式。


# oraclize
Oraclize定位為去中心化應用的資料搬運工,他作為Web APIs和DApp的可靠連結。有了Oraclize,
就不需要建立額外的信任鏈,因為我們的行為已經被強制加密驗證。Oraclize是一個可證明的誠實的預言機服務,
可以讓智慧合約可以訪問網際網路。Oraclize是平臺無關的,為所有主流的智慧合約能力平臺提供一種虛擬的介面。可以想像,
通過這個投入成千上萬的有意義的資料到區塊鏈中,可以使得智慧合約產業更繁榮和更多有價值的應用呈現更大的生命力。

Oraclize的使用方式可以參考下面的[程式碼]
(https://github.com/oraclize/ethereum-examples/blob/master/solidity/random-datasource/randomExample.sol)

在update方法裡面呼叫oraclize_newRandomDSQuery方法來呼叫Oracle的智慧合約的程式碼,
Oracle根據請求來生成對應的資料, 然後把結果通過回撥__callback來傳入。

    /*
     Oraclize random-datasource example
    
     This contract uses the random-datasource to securely generate off-chain N random bytes
    */
    
    pragma solidity ^0.4.11;
    
    import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";
    
    contract RandomExample is usingOraclize {
    
     event newRandomNumber_bytes(bytes);
     event newRandomNumber_uint(uint);
    
     function RandomExample() {
     oraclize_setProof(proofType_Ledger); // sets the Ledger authenticity proof in the constructor
     update(); // let's ask for N random bytes immediately when the contract is created!
     }
    
     // the callback function is called by Oraclize when the result is ready
     // the oraclize_randomDS_proofVerify modifier prevents an invalid proof to execute this function code:
     // the proof validity is fully verified on-chain
     function __callback(bytes32 _queryId, string _result, bytes _proof)
     {
     // if we reach this point successfully, it means that the attached authenticity proof has passed!
     if (msg.sender != oraclize_cbAddress()) throw;
    
     if (oraclize_randomDS_proofVerify__returnCode(_queryId, _result, _proof) != 0) {
     // the proof verification has failed, do we need to take any action here? (depends on the use case)
     } else {
     // the proof verification has passed
     // now that we know that the random number was safely generated, let's use it..
    
     newRandomNumber_bytes(bytes(_result)); // this is the resulting random number (bytes)
    
     // for simplicity of use, let's also convert the random bytes to uint if we need
     uint maxRange = 2**(8* 7); // this is the highest uint we want to get. It should never be greater than 2^(8*N), where N is the number of random bytes we had asked the datasource to return
     uint randomNumber = uint(sha3(_result)) % maxRange; // this is an efficient way to get the uint out in the [0, maxRange] range
    
     newRandomNumber_uint(randomNumber); // this is the resulting random number (uint)
     }
     }
    
     function update() payable {
     uint N = 7; // number of random bytes we want the datasource to return
     uint delay = 0; // number of seconds to wait before the execution takes place
     uint callbackGas = 200000; // amount of gas we want Oraclize to set for the callback function
     bytes32 queryId = oraclize_newRandomDSQuery(delay, N, callbackGas); // this function internally generates the correct oraclize_query and returns its queryId
     }
    
    }

考慮一個提供打賭的智慧合約。
使用者呼叫打賭的介面,這個介面會把使用者的請求儲存起來,然後呼叫Oracle隨機數生成服務。
然後通過Oracle回撥服務,判斷隨機數是否大於某個值,如果成立,那麼使用者成功,否則使用者失敗。

這就是典型的Oracle的使用案例。






# RANDAO: A DAO working as RNG of Ethereum

[randao](https://github.com/randao/randao)是一個生成以太坊隨機數的去中心化組織,

**Random number in programming is very important!**

**RNG in a deterministic system is very difficult**

**Miners can't be trusted!**

隨機數在程式設計中是非常重要的。
RNG 在一個確定性的系統中是非常難的。
不能相信礦工

## 解決方案
Solutions

A DAO (decentralised autonomous organisation) that anyone can participate in, and the random number is generated by all participants together! First of all, we need to create a RANDAO contract in the blockchain, which defines the participation rules. Then the basic process of generating a random number can be divided into three phases:

一個DAO(去中心化的匿名組織)允許任何人加入,隨機數是被所有的參與者一起合作生成的。首先,我們需要在區塊鏈上建立一個RANDAO的智慧合約,合約定義了參與規則。然後生成隨機數的基本過程可以分為下面三個步驟:

**The first phase: collecting valid sha3(s)**

Anyone who want to participate in the random number generation needs to send a transaction to the contract C with m ETH as pledge in a specified time period (e.g, 6 block period, approximately 72s), accompanied by the result of sha3(s), s is the secret number respective picked by participant.

**第一步:收集有效的sha3(s)**
參與隨機數生成的參與者首先需要在一個指定的時間區間(比如,6個區塊的區間,大約72秒)傳送m ETH作為抵押到智慧合約 C,同時傳送一個sha3(s)的值到智慧合約C ,s是一個只有參與者自己知道的數字.

**The second phase: collecting valid s**

After the first phase, anyone who submitted sha3(s) successfully needs to send a transaction with the secret number s in the first stage to contract C within a specified time period. Contract C will check if s is valid by running sha3 against s and comparing the result with previous committed data. Valid s will be saved to the collection of seeds to finally generate the random number.

**第二步:收集有效的s**

在第一步結束後,那些提交了sha3(s)的參與者需要在指定的時間區間內傳送s到智慧合約C. 智慧合約C會檢查sha3(s)和之前提交的值是否相同。 相同的s會被儲存到種子集合用來最終生成隨機數。

**The third phase: calculating a random number, refund pledged ETH and bonus**

- After all secret numbers have been successfully collected, contract C will calculate the random number from the function f(s1,s2,...,sn), the result will be written to the storage of C, and the result will be sent to all other contracts that requested the random number before.
- Contract C will send back the pledge to the participants in the first phase, and the profit is divided into equal parts and sent to all participants as an additional bonus. The profit comes from the fees that is paid by other contracts that consume the random number.

**第三步:計算隨機數,退回抵押和獎金**

- 在所有的祕密數字s被成功收集後,智慧合約C會使用函式f(s1,s2,...,sn)來計算隨機數,隨機數的結果會寫入智慧合約的儲存,而且結果會被髮送到所有之前請求隨機數的其他智慧合約上面。
- 智慧合約C會把第一階段的抵押返回給參與者,然後獎金會被分成同等分傳送給所有的參與者。獎金來源於請求隨機值的其他智慧合約。

## Additional rules

In order to ensure the RNG can't be manipulated, as well as for safety and efficiency, the contract C has the following additional rules:

- The first phase, if two or more of the same sha3(s) are submitted in sequence, only the first one is accepted.

- The first phase, there is a requirement for minimum number of participants, if it fails to collect enough sha3(s) within the time period, then RNG at this block height will fail.

- If a participant submits the sha3(s) and it is accepted by contract C, he must reveal the s in the second phase.

    - If the participant fails to reveal s in the second phase, then the m ETH sent in the first phase will be confiscated without providing a return.

    - If one or more s isn't revealed in the second phase, RNG at this block height will fail. Confiscated ETHs will be divided equally and send to other participants who revealed s at the second phase. The fees paid by other contracts will be refunded.

補充規則

為了確保RNG不能被操控,以及為了安全和效率,智慧合約C有以下的補充規則:

- 在第一步中,如果有兩個或更多個的同樣的sha3(s)被提交上來,那麼只有第一個會被接受。
- 在第一步中,對於參與者有最低要求,如果在指定的時間區間內沒有收集到足夠多的sha3(s)的值,那麼RNG在這個區塊高度會失敗。
- 如果參與者提交了sha3(s),那麼他必須在第二步提交s
    - 如果參與者在第二步沒有提交s,那麼第一階段提供的m ETH會被沒收而且沒有獎勵。
    - 如果一個或者多個s沒有在第二步被提交,RNG在這個區塊高度會失敗。沒收的ETH會被分成同等分傳送給提交了s的其他參與者。
其他申請隨機數的其他合約的費用會被退回。

## Incentive

The RNG cycle is very short, and could be for example 20 cycles in one hour, if one cycle's profit is 0.001% , the monthly rate of return is up to 0.00001 * 20 * 24 * 30 = 0.144. Targeting to 14.4% monthly rate of return, and RNG has n participants on average, the running costs of contract is n * 3 * 500 * gasPrice + Ccost. (Ccost is gas consumed by contract internally, including computing and storage, etc. ) Assuming each random numbers has r time requests on average, the call price is p ETH, the income is r * p. So each participant will get (rp - 1500n * gasPrice - Ccost) / n from one time participation. The current gasPrice is 10 szabo, and estimate of contract consumption is 1500n gas, so estimate of net income is (rp / n - 0.03) ETH. Assuming each RNG has 10 participation, and the pledge is 1000ETH, the minimum required income is 0.4 ETH, which over 0.001% profit in this case. So if the RNG is requested only once, the service price is 0.4 ETH, and if it is requested 10 times, the price is just 0.04 ETH for each request.

激勵

RNG的週期非常短,例如一個小時20個生成周期,如果沒有周期的利潤是0.001%,一個月的盈利會達到0.00001 * 20 * 24 * 30 = 0.144。 為了達到14.4%每個月的盈利,並且RNG平均有n個參與者,執行智慧合約C的費用為 n * 3 * 500 * gasPrice + Ccost.(CCost是合約內部的gas消費,包括計算和儲存)假設每個隨機值平均有r個請求,每個請求的費用是 p ETH, 那麼收入是 r*p. 所以每個參與者每一次參與會收到rp - 1500n * gasPrice - Ccost) / n。當前的gasPrice是10 szabo, 合約的消費大概是1500n gas, 所以大概的淨收入是(rp/n-0.03)ETH. 假設每個RNG有10個參與者,並且抵押是1000ETH,所以如果RNG如果只請求一次,那麼一次的費用是0.4 ETH, 如果請求是10次,那麼一次請求的價格會被降到0.04ETH


The RANDAO acts as an infrastructure in the Ethereum system. It is called by other contracts. Contracts for different purposes require different random numbers: some need high security, such as lottery; some need steady responses and the request should be responded immediately, these contracts are normally low-value; some need a callback, they want to receive a notification with random numbers when numbers are ready.

Obviously it's impossible to meet different requirements in various scenarios with only one RNG contract, so a lot of contracts will be created with different initial parameters, but the basic rules are the same.

RANDAO作為以太坊系統的基礎設施。被其他的合約呼叫。不同的合約因為有不同的目的所以需要不同的隨機值:有些需要高度加密的,比如說抽獎;有些需要穩定的迴應,並且要求立即作出迴應,這些合約本身的價值不高;有些需要回撥函式,當隨機值已經生成的時候需要接收到通知。

很明顯通過單一的RNG合約不可能滿足所有的不同的請求,所以使用了不同的初始值建立了很多智慧合約,不過他們基本的規則是相同的。


For example, if we need high security, we can substantially increase the pledge of the first phase. Thus, the cost of leading to failure of RNG process by not revealing s is greatly increased. And for the contracts without much interest involved, the minimum number of participants and the pledge can be lower.

Let's look at an example of a dApp betting on odd or even numbers, we'll show how to adjust the contract's parameters to meet the desired security level, by making the cost of cheating higher than expected earnings. Assuming the bet is 1000 ETH, the betting contract calls a RNG contract C1, if C1 failed to generate a random number at requested block height, then betting contract waits for the next random number of C1, until there is one generated.

比如,如果你需要高度安全,我們可以大大的增加第一階段的抵押。這樣不提供s的導致失敗的概率會大大降低。對於那麼資金不是很充足的合約,那麼參與者的最小個數和抵押都可以降低。

讓我們看一個dapp的例子,這個例子用來賭數的奇數和偶數,我們會顯示如何調整合約的引數來匹配適合的安全程度,通過讓造假的成本大大高於收益。假設打賭是1000ETH,這個打賭的合約呼叫了RNG的合約C1, 如果C1在請求的區塊高度生成隨機數失敗了,打賭的合約會等待C1的下一個隨機數,直到有一個生成成功。

Let's build the RNG contract C1, and set the pledged ETH of C1 to 2000. The gambler G plays the betting dApp but also participates in the contract. When he finds himself in a disadvantageous position before he reveals his secret number, he can choose not to reveal s, so that the RNG failed and he got another chance. But he will lose the 2000 pledged ETH, so although he can get 1000 ETH expected return, it is still a bad deal. However, G can reduce his losses on C1 by some means, such as participating in C1 using two accounts, sending two sha3(s). if in a disadvantageous position, G will keep only one account's secret, and if only one participant expect G participate to in C1, G will only lose 1000 ETH in C1, but G will get 1000 ETH as expected return, which is a worthy try.

讓我們構建RNG智慧合約C1, 並且設定抵押的值是2000。 賭徒G參與了dApp的賭注,同時參與了RNG的智慧合約。在他提交s之前,發現自己處在不利的狀態。他可以選擇不提交自己的s,這樣RNG會失敗,他會得到下一個機會。 但是他會損失2000ETH的抵押,儘管他可以得到1000ETH的賭注,所以這樣並不是一個好的交易。然而賭徒G可以使用其他的方式來減少損失,比如G可以使用兩個賬號參與RNG,傳送兩個sha3(s).如果在不利的狀態,G會讓一個賬號不提交s,這樣如果除了G之外只有另外一個其他的賬號,G只會在G1上面損失1000ETH,但是G如果賭贏了可以得到1000ETH,所以也值得一試。

This issue can be fixed by confiscating the pledged ETH, and not return them to participants as bonus. so a contract with 1000 pledged ETH will meet the requirement of the betting dApp.

這種情況可以通過沒收所有抵押來修復,不會把他們作為獎勵返回。所以一個1000抵押的合約會符合賭博的要求。

Besides confiscation, another scheme can prevent such attacks by introducing an additional system: RANDAO membership. To become a member you must pay dues, anyone paid their dues is a member. Members have different levels according to the dues they paid. Membership does not belong to a contract, but instead functions like a passport to participate in some RANDAO contracts. If a breach of any contract happens, that person's membership will be ended and the dues will be confiscated. Now we can add an additional agreement to C1, C1 will only accept numbers committed by members whose level of investment is high enough (membership dues over 1000 ETH). This will ensure that nobody has a financial motive to try an attack.

除了沒收,還有一個方案可以阻止這種攻擊,那就是 RANDAO membership。 為了成為成員,你必須繳納成員費用。根據成員繳納的費用的多少把成員分成不同的等級, 成員系統不屬於智慧合約,而是作為一種類似護照的形式來參與一些RANDAO合約。 如果發生違約情況,這個成員的會員資格會被終止,成員會用會被沒收。現在我們可以給智慧合約C1增加一個額外的協議,C1只接受會員會用大於一定值的成員來參與。 這樣來保證沒有任何人會有財務動機來發動攻擊。


## QA: Quest and Answer

Q: Why not let the miners participate in RNG? Why not use tx hash, nonce and other blockchain data? A: Miners have the ability to manipulate these blockchain data, and thus can indirectly affect RNG. If RNG contains blockchain data, it will give the miners capacity to construct random numbers in their favor.

Q: 為什麼不讓礦工來參與到RNG中? 為什麼不使用txhash,nonce或者其他區塊鏈資料? A:礦工有能力才操縱這些區塊鏈資料,而這些會對RNG產生影響。如果RNG包含了區塊鏈資料,會給予礦工按照自己的行為構造隨機數的能力。

Q: the miners can ignore certain transactions that contain random number they dislike, how to deal with that? A: That's why we need a time window period. A reasonable period should be greater than 6 blocks, we believe that nobody can produce 6 blocks in succession. So if the participant is honest, and he send numbers immediately as long as each time window open, he doesn't need to worry about being excluded.

Q: 礦工有能力忽略特定的包含了隨機數的交易,如何處理這種情況? A: 這就是為什麼我們需要時間間隔。 一個合理的時間間隔會大於6個區塊,我們任務沒有人能連續生成6個區塊。 所以如果參與者是忠誠的,而且在時間視窗內傳送了那個數字, 那麼他不同擔心會被礦工排除在外。

Q: Why use all numbers of all participants, rather than a subset? A: The rule to pick a subset is deterministic, so participants will try to take specified position of the collection by various means, if they succeed, they will know in advance what the random number is generating from subsets. If the rule to pick a subset is randomised, then we still have the problem of true randomisation.

Q: 為什麼使用所有的參與者的所有的值,而不是其子集? A: 選擇一個子集的規則是確定性的,所以參與者將嘗試通過各種方式來採集指定的集合位置,如果它們成功,他們將事先知道從子集中產生的隨機數。 如果選擇一個子集的規則是隨機的,那麼我們仍然存在真正的隨機化問題。

Q: Where does pledged dues go? A: It will be donated to a charity, or RANDAO to maintain funding. Q: 沒收的費用去哪了。 會捐獻給慈善機構,或者是RANDAO會維護一個基金。

Note: f(s1, s2, ..., sn) is a function with multiple inputs, for example r = s1 xor s2 xor s3 ... xor sn, or r = sha3(sn + sha3(sn-1 + ... (sha3(s2 + s1))))




網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN




相關文章