最近考虑一个基于以太坊的去中心化du-场的实现,du-场如果需要实现,那么随机数是必须的。然后研究了一下以太坊里面的随机数生成,发现并不容易。
eth里面生成随机数的几种方式。
oraclize
Oraclize定位为去中心化应用的数据搬运工,他作为Web APIs和DApp的可靠链接。有了Oraclize,
就不需要建立额外的信任链,因为我们的行为已经被强制加密验证。Oraclize是一个可证明的诚实的预言机服务,
可以让智能合约可以访问互联网。Oraclize是平台无关的,为所有主流的智能合约能力平台提供一种虚拟的接口。可以想像,
通过这个投入成千上万的有意义的数据到区块链中,可以使得智能合约产业更繁荣和更多有价值的应用呈现更大的生命力。
Oraclize的使用方式可以参考下面的[代码]
(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
}
}
考虑一个提供打du的智能合约。
用户调用打du的接口,这个接口会把用户的请求存储起来,然后调用Oracle随机数生成服务。
然后通过Oracle回调服务,判断随机数是否大于某个值,如果成立,那么用户成功,否则用户失败。
这就是典型的Oracle的使用案例。
RANDAO: A DAO working as RNG of Ethereum
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.
未完待续欢迎继续关注兄弟连区块链教程分享!
有疑问加站长微信联系(非本文作者)