Search code examples
randomshufflepolkadot

How does Polkadot's VRF achieve randomness to shuffle validators?


Contrary to Ethereum which uses RANDAO (possibly enhanced with VDF), in Polkadot, a verifiable random function (VRF) is used to shuffle validators and select potential block proposers for certain slots. Where does the randomness come from, i.e. how does the randomness work specifically?


Solution

  • A verifiable random function is a function that, in pseudocode, can be expressed like so:

    (RESULT, PROOF) = VRF(SECRET, INPUT)
    

    That is, for some secret and some input (which can be public), the result is a tuple of RESULT and PROOF, where PROOF can be used by outside observers to verify legitimacy of the VRF RESULT.

    In other words, making a "VRF roll" results in a random number and proof that you got that random number, and didn't just pick it.

    Every slot (approx. every 6 seconds) every validator will run the VRF function. The SECRET will be their VRF key, a special key to be used only for this, generated by the validator and kept secret. The INPUT is either a specific value from the genesis block if fewer than 2 epochs exist in the chain, or a hash of all the VRF results in the past 2 epochs.

    Once a validator has executed the VRF, the RESULT is compared to a THRESHOLD value which is defined by the protocol. If the RESULT is less than THRESHOLD, the validator is a valid block-proposer candidate for that slot. Otherwise, the validator skips that slot.

    This means it is possible for there to be multiple validators who are block producing candidates for a slot, in which case the block that gets picked up by other nodes is the one that prevails, as long as it's on the chain with the most recent finalized block as per the GRANDPA finality gadget. A situation in which no block producers exist for a slot is also possible, in which case the AURA consensus will take over. The AURA consensus is basically a fallback which picks a random validator for each block. It runs in parallel to BABE, and only matters when a slot has no block producers, otherwise it's ignored.