0

I create a random number starting from block.coinbase, block.number and block.timestamp, then I determine some probabilities. Is it correct or there is a better way?

bytes32 bHash = keccak256(block.coinbase, block.number, block.timestamp);

            if (bHash[30] == 0xFF && bHash[31] >= 0xF4) {
                //one chance on 5000
                //do something
            } else if (bHash[28] == 0xFF && bHash[29] >= 0xD5) {
                //one chance on 1500
                //do something
            } else if (bHash[26] == 0xFF && bHash[27] >= 0x7E) {
                //one chance on 500
                //do something 
            } else if (bHash[25] >= 0xF4) {
                //one chance on 20
                //do something
            }
J.Doe
  • 41
  • 5
  • You should precise your use case, because randomness generation depends on what you want to do exactly. – Distic Sep 05 '17 at 15:12
  • It's for a gambling game, my goal is to obtain a pretty good random number on wich calculate some probabilities. I'd like to know if for you this method to calculate is good or weak – J.Doe Sep 05 '17 at 21:16
  • I don't exactly understand the way you do it, but you derive your randomness from public data so if there is enough to win (say more than the mining reward) it becomes possible to get money from cheating.

    As suggested in the answer, the best way to do is: generate randomness out of ethereum, then commit to it, then reveal when everyone has played/commited.

    – Distic Sep 06 '17 at 07:03
  • I've done in this way to have answer immediately, when someone plays he knows at once if his play is a winning one. – J.Doe Sep 06 '17 at 19:13
  • You can generate randomness outside blockchain, then have a script watching your contract and send to the player the gain if he wins. But then the player has to trust you. I think there is no way to avoid both interactivity and trusted-outside random generation while still being secure for huge rewards. – Distic Sep 07 '17 at 08:26
  • Do you know where I can see something about calling a function or api outside the contract? – J.Doe Sep 07 '17 at 18:50

2 Answers2

2

Randomness is very difficult in Ethereum, but how perfect you need it really depends on your goals. If aren't storing tons of value and 'almost' perfect randomness works, then your code works great. If you want to get better, there are discussions all over the internet on it, but no one solution has really emerged as the standard. Here's one discussion in particular: https://blog.otlw.co/random-in-ethereum-50eefd09d33e

thefett
  • 3,873
  • 5
  • 26
  • 48
  • I know randomness is difficult to obtain but it's enough for me to have a pretty good random number on wich calculate some probabilities in a not too much complicated way – J.Doe Sep 05 '17 at 21:21
2

See this discussion for the issue of using random numbers in general: How can I securely generate a random number in my smart contract? This describes a number of approaches including commit-and-reveal, which is the most secure approach, but has some practical downsides.

There are some circumstances where it may be appropriate to use block.blockhash. It's the simplest way to make a random number, but it can be gamed by miners at a cost: They can mine a block, see if it loses their own bet, and pretend they never mined the losing block. This costs them mining revenue (1 block reward + fees), so if the benefit of cheating your contract is very small, it may be a reasonable strategy. But note that in theory the miner could combine that behaviour with other non-standard behaviour like Selfish Mining, making the cost even lower than the mining reward.

block.timestamp and block.coinbase can both be gamed at no cost by the miner, and block.number is predictable in advance. Combining them makes matters worse, because if you know all the variables, controlling one is sufficient to be able to control the resulting random number. There is no reason to prefer any of these over keccak256(block.blockhash).

Edmund Edgar
  • 16,897
  • 1
  • 29
  • 58