[Ethereum] Honest lottery winner generation – pseudo random number obtaining

contract-designrandomnessSecuritysolidity

Suppose I would like to organize a honest lottery and prevent cheating when we need to find a winner. I known problem of random number in the known network arises.

I would like to try the following algorithm to prevent cheating.

The idea is to use hash of a block but the block number is not known for miners/participants and organizers to prevent cheating.

  1. On start organizer defines a random uint64 – key number to be used in the winner random number calculation. The uint number is big enough and known to organizer only on start.
  2. Organizer fixes the key number by providing hash of sum – the number plus current block hash (as a salt).
    The key hash is stored in the Lottery contract and available for all the participants. Then key hash is used to prevent organizers cheating and fixes the key number.
  3. Participants buy tickets and the Lottery contract stores all the participant addresses. The addresses are used on winner calculation as well.
  4. When conditions are fulfilled (e.g. all the tickets are sold or necessary amount of blocks are generated or just after some time) organizer starts winner calculations.
  5. Organizer provides the stored key number and confirms the number is exactly the same by calculating the key hash (entered on init).
  6. The key number is added to the sum of addresses and we got mod 255 of the sum to detect number of block which hash is used to detect winner.
    Key number + address1 + address2 … + addressN % 255 = number of winner block (the block hash is used to get winner number)

To person who want to guess winning number it is not possible to get the number – in the contract we have just hash of the number. The number is rather big uint64 (or could be even bigger) to prevent "unhashing" the number.
For organizers the number is fixed and is futile because all the tickets owners addresses must be known to calculate the winner.

Opinions? Any holes in the logic?

UPDATE:
After discussing the suggested algorithm there is an improvement.

  1. When a participant buys a ticket it is allowed to pass additional has for participant key number which is also used in the winner calculation.
  2. Suppose ticket price is 100%.
  3. When participant want to provide own participant key number he pays more e.g. 300%.
  4. When the participant key number is provided during the winner detection round 210% of ticket price is returned.
  5. If the participant key number is not provided the sum is added to the lottery prize.

Thus everybody who has doubts about organizer honesty can add own random part. Not providing the key means such a person lost the deposit.
Such honesty providers can have cheaper (in fact) tickets.

Best Answer

The organizer can cheat the system by attempting many different addresses, which, when added to your formula Key number + address1 + address2 ... + addressN % 255 as the last address and getting the hash of the block, make this address the winner.

You can think about it this way:

  • If your system is secure, there is no way to cheat the system.
  • If there is no way to cheat the system, the organizer also cannot cheat the system.
  • If there is no way for organizer to cheat the system, then knowing the key number doesn't give you any way to cheat the system. (Otherwise the organizer would cheat the system because he knows the key number)
  • If knowing the key number doesn't give you any way to cheat the system, the system is as secure with the key number as without the key number.
  • You can get rid of the key number. The formula Key number + address1 + address2 ... + addressN % 255 is as secure as this one address1 + address2 ... + addressN % 255.
  • However, the above formula without the key number is insecure as it's subject to the same attack I described in the beginning. Right before the time when the winner is decided someone can atempt a bunch of addresses and find one that makes him the winner.
  • This means that the formula with the key number is insecure also.

As a result we came to a contradiction - we made the assumption that our system is secure in the beginning and at the end concluded that it's insecure. Thus our assumption is not correct.


What you should do instead is split the lottery into 2 phases:

  1. When buying a ticket participants must include with the transaction:

    • hash of some random number.
    • cost of the ticket.
    • some fairly large deposit.
  2. When all tickets are sold (or after some expiration) everyone who bought a ticket in the 1st phase must reveal the secret number.

    • When you reveal your secret number you get your deposit back.
    • After everyone revealed their secret number, those secret numbers together are used as source of randomness to determine the winner, e.g. concat them and hash.
    • If anyone didn't reveal their secret number (or after some expiration), the lottery is cancelled: everyone who revealed their secret numbers can withdraw the price they paid for tickets. Everyone who didn't reveal the secret number loses their deposit and the cost of ticket.
    • The deposit provides the incentive to reveal the secret number. The reason why lottery must be cancelled if anyone didn't reveal their secret number is there is a way to cheat the system by not exposing the secret number if it's favorable for the attacker.

In a similar way RANDAO is implemented. Check out the section Additional Rules and Incentives for other things you need to make sure to prevent the possibility of cheating.

In particular, the deposit size summed with the ticket price has to be not lesser than the maximum reward (normally, total amount in the lottery). Any deposit smaller than this will give an opportunity for cheating as explained by lungj here

Related Topic