# Randomness

Random numbers are widely used in Vite. One good case is the process to reach consensus, where a random number is chosen in each round in the purpose of determining which SBP is responsible for producing the next snapshot block, thus avoid being predicted in advance. Another scenario is in gambling games the results are generated depending on unpredictable random numbers to avoid manipulation.

When we design the random number, it should meet the following criteria:

  1. Must NOT be manipulable
  2. Must NOT be predictable

# Random Numbers on Vite

The design comes from the common dicing game in real world. Basically, a simple dicing game will go through the following 3 steps:

  1. Dealer shakes the dice box
  2. Player guesses the dice number and makes bet
  3. Dealer uncovers dice box and shows result

In this game, dealer can have two ways to cheat:

  1. Changes the result after player bets
  2. Reveals the result to another player in conspiracy

In real world, we can take the following precautions to reduce the probability of cheating, but none of them has 100% guarantees.

  1. Perform careful dicing equipments inspection
  2. Supervise the dicing process
  3. Rely on dealer's reputation

Luckily, in the blockchain world, a more secure and efficient way can be used to prevent a dealer from manipulating results - the random numbers.

This is equivalent to the following steps in the dicing example:

  1. Add multiple dealers. The dicing results from each dealer will be submitted to calculation of the final result. As long as one dealer is honest, the final result is safe. A dealer must conspire with all rest dealers in order to cheat.
  2. When the dicing result is generated, the result hash is calculated and shown in public for verification purpose before the player makes bet. The dicing result, when it is finally published, should match the hash. This effectively prevents the result from being tampered with.

Figure 1 shows how above idea is implemented in Vite

figure

Figure 1

Each random number goes through three steps in the lifecycle:

  1. hashNhash_N is published when randomNrandom_N is generated
  2. randomNrandom_N is published
  3. randomNrandom_N is safely used

In the figure, block NN to N+5N+5 are six consecutive snapshot blocks produced by 3 SBPs (we assume the network has only 3 SBPs).

In each round of producing a snapshot block, an SBP should publish both:

  1. The hash of random number in the current round.
  2. The random number that was generated by this SBP in the last round.

For example, SBP1 published hashN+3hash_{N+3} (the hash of random number in BlockN+3Block_{N+3}) and randomNrandom_N (the random number generated in BlockNBlock_{N}) in BlockN+3Block_{N+3}. The network will test if Hash(randomN)=hashNHash(random_N)=hash_N, meaning the hash of randomNrandom_N must be equal to hashNhash_N, otherwise randomNrandom_N is invalid.

At this time, we can calculate a random seed based on the random numbers published by the SBPs in previous rounds. When BlockN+5Block_{N+5} is produced, the random seed at this block is $$Seed_{N+5} = Sum(random_{N+2}, random_{N+1}, random_{N})$$ This result is unpredictable, and not a single SBP is able to manipulate the result.

In actual implementation, in order to save storage, randomNrandom_N is in uint64, and hashNhash_N is limited to 32-byte length.

In addition, for security reason such as preventing from brute-force attack, the hash function is defined as following:

hashN=Hash(randomN+BlockN.PrevHash+BlockN.Timestamp)hash_N = Hash(random_N + Block_N.PrevHash + Block_N.Timestamp)

See VEP-12: The Implementation of Random Numbers in Vite (opens new window) for more details.

# Using Random Seed in Contract

On Vite, contract execution is split into a pair of request and response. If random numbers are used in the contract, in order to obtain a random seed, the contract must wait at least until a given number x of snapshot blocks that contain published random numbers are produced. x is called Random Degree.

When deploying a contract that uses the global function random64() or nextrandom(), you need specify a positive Random Degree and Response Latency, otherwise the deployment will fail.

See here for more details about Random Degree and Response Latency.