Skip to content

Latest commit

 

History

History
143 lines (86 loc) · 12.5 KB

random-number-generator.md

File metadata and controls

143 lines (86 loc) · 12.5 KB

Recently considering the implementation of a decentralized casino based on Ethereum, a random number is necessary if the casino needs to be implemented. Then I studied the random number generation in Ethereum and found that it was not easy. You can refer to Monte Carlo Methods in Practice.

There are several ways to generate random numbers in Ethereum.

oraclize

Oraclize is positioned as a data porter for decentralized applications as a reliable link to Web APIs and DApps. With Oraclize, there is no need to build an extra chain of trust because our behavior has been forced to be encrypted. Oraclize is a provable and honest oracle service that allows smart contracts to access the Internet. Oraclize is platform-independent and provides a virtual interface to all major smart contract platforms. It is conceivable that investing a lot of meaningful data into the blockchain through Oraclize can make the smart contract industry more prosperous and make more valuable applications more vital.

How to use Oraclize can refer to the followingcode

In the update method, call the oraclize_newRandomDSQuery method to call Oracle's smart contract code. Oracle generates the corresponding data according to the request, and then passes the result through the callback __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
		}

}

Consider a smart contract that offers betting. The user invokes the betting interface, which stores the user's request and then invokes the Oracle random number generation service. Then through the Oracle callback service, determine whether the random number is greater than a certain value. If it is established, the user succeeds, otherwise the user fails.

This is a typical Oracle use case.

RANDAO: A DAO working as RNG of Ethereum

randaois a decentralized organization that generates Ethereum random numbers.

Random number in programming is very important!

RNG in a deterministic system is very difficult

Miners can't be trusted!

Random numbers are very important in programming. RNG is very difficult in a deterministic system. Can't believe miners

solution

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:

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.

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.

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.

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.
    

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.

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.

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.

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.

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.

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.

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: 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: 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.

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))))