1

How can I form a random group of 5 people from an array of 100 people?

1

It will be very difficult.

I'll break it down into a few separate concerns. The first is just general programming. You need need numbers in the range of 0-99 to to pick people out of the array.

Let us set the "randomness" concern aside for now and focus on scaling a uint. Let us suppose the uint to start with could be anything, so somewhere in the range of 0 to 2^256, 0b111 ... x256 ..111. We want to use that as a seed to make a number in range, so we have to divide it by something.

You could:

uint seed = uint(0) - uint(1); // Underflow is your friend. 
uint divisor = seed / uint(99); // a really big number
uint inRange = random / divisor; // this should be in the range of 0-99.

Okay. Great. Now, we just need a "random" uint to start with.

This is a challenge, because Ethereum is a deterministic system, meaning all nodes need to be able verify transactions now and in the future. How would that be possible with random numbers in the mix? It's an active area of research, https://www.coindesk.com/ethereum-foundation-weighs-15-million-bid-to-build-randomness-tech.

A few techniques exist.

  1. An Oracle like Oraclize can be relied upon to supply the random number.
  2. You can make the number deterministic but hard to guess.
  3. Probably others.

I feel that the second approach deserves a word of caution. Unless you are very careful, a number that seems hard to guess may, in fact, be easy to guess. By extension, that can lead to exploits.

For example, you might use the next block hash to generate the pseudo-random number.

contract Guess {
  function guessMe(uint guess) public returns(bool success) {
    return uint(blockhash(block.number)) == guess;
  }
}

A miner has the latitude select transactions for a block and reorder transactions without a block. This means a miner can fiddle with the block to make it land on a given number if there is financial incentive to do so. With only 100 possibilities, brute force could potentially work. Even if one is not a miner, one can still seem to know the number, in advance.

It may look hard to guess because one would have to know, in advance, the hash of the block when the transaction is mined, and that's in the future. It's trivial to attack that if there is any financial incentive to do so (lottery?). The trick is to call from another contract because surely both functions will run in the same block context.

contract Attack {
    Guess g;
    event LogSuccess(address sender, bool success);
    constructor(address guessIt) public {
        g = Guess(guessIt);
    }
    function notSoHardAfterAll() public {
        if(g.guessMe(uint(blockhash(block.number)))) {
            emit LogSuccess(msg.sender, true);
        }
    }
}

So, not only is it not a random number, but it also isn't hard to gain an advantage and know the number before deciding what to do. That's usually a problem if your first idea was a random number.

There are ways to add randomness (entropy) by very deliberately weaving it into the overall design. I won't get into it because it wills stray too far, I think, from the original question. Extreme caution here. You will want to get lots of opinions about your technique to ensure there is no opportunity to "front run" your contract.

In practice, it may be sufficient if the number is not "random" but is equitably distributed and convincingly unknowable until all participants are locked into positions.

Hope it helps.

  • does this also apply if the catch is that the same people of a group should just not be able to be picked for the next group, but perfectly fine for the third? – NowsyMe Jul 10 at 21:41
  • 1
    Making a group ineligible adds a little complication to it, not insurmountable but I don't this it moves the needle on the basic problem of choosing a few in a pseudo-random and unpredictable way. – Rob Hitchens - B9lab Jul 10 at 21:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.