Suppose your contract has a function which generates a random treasure, as illustrated below:
function generateTreasure() returns (Treasure) {
if (msg.value < 1 ether) return; // cost of calling the message
uint8 rnd = randomUint8();
if (rnd == 0) return rareTreasure;
if (rnd <= 4) return averageTreasure;
if (rnd <= 16) return commonTreasure;
return garbage;
};
I want to guarantee that an user calling generateTreasure will not be able to cheat the result by any external means - i.e., I want it to cost, in average, 256 ether for any user to acquire a rareTreasure. That wouldn't be true if an attacker found a way to get a rareTreasure more than 1/256 times in average per generateTreasure call.
I am aware an miner could cheat it by discarding a mined block - but, on this case, the situation is different. A single user could call generateTreasure many times in a single block, and multiple users could call it. Of course I don't want to give the same treasure for all users, so, that would need some form of stateful nonce (lastRandom) so each caller gets a different number. But, then, that would mean an user could create a contract that reads that nonce and only calls generateTreasure if it provides a good treasure with said block hash! Is that correct?
So, all things considered, what is the most appropriate randomization for that function?