Blockchain Randomness

Describes how you can introduce randomness in a Substrate runtime.

Because blockchains require deterministic outcomes—where the same input always produces the same output—finding an appropriate source to produce seemingly random results presents a unique challenge. However, there are many applications where randomness can be essential to performing certain operations. For example, you want to include randomness to select the validator responsible for producing a block to prevent validator selection from being predictable, and thereby vulnerable to be exploited in an attack. You might also use randomness in statistical or scientific analyses, in cryptographic operations, or in applications involving gaming or gambling.

Deterministic randomness

In traditional computer applications, what people call random numbers are actually generated using pseudo-randomness. Pseudo-randomness depends on a sufficiently random seed—provided by the user or by an external source—and an algorithm that manipulates the seed to generate a series of seemingly-random numbers. The result is a pseudo-random number that is difficult to predict because of the algorithm used to generate it, but deterministic because the same seed input always produces the same series of output.

However, applications that run on the blockchain are more tightly constrained because all authorities in the network must agree on any on-chain value, including any randomness data that is injected. Because of this constraint, you can't use real randomness directly in blockchain applications.

For blockchain applications, the most common approach to providing randomness is a cryptographic primitive called averifiable random function. A verifiable random function (VRF) is a mathematical operation that takes input and produces a random number and a proof of authenticity that this random number was generated by the submitter. The proof can be verified by any challenger to ensure that the random number generation is valid.

In the Polkadot ecosystem and Substrate-based chains, verifiable random functions are part of the consensus mechanism provided by the BABE pallet. For more information about the relationship between verifiable random functions and consensus, see Consensus

Generate and consume randomness

Substrate provides a Randomness trait called that defines the interface between the logic that generates randomness and the logic that consumes randomness. This trait allows you to write the logic for generating randomness and consuming randomness independently of each other.

Generating randomness

You can implement the Randomness trait in many different ways, depending on the security guarantees and performance trade-offs that your application requires. Substrate includes two examples of how to implement the Randomness trait in pallets that provide different trade-offs between performance, complexity, and security.

  • The insecure randomness pallet provides a random function that generates pseudo-random values based on the block hashes from the previous 81 blocks.

    This type of randomness performs well but isn't secure. You should only use this pallet in applications with low security requirements or when testing randomness-consuming applications. You shouldn't use this pallet in a production environment.

= The BABE pallet provides randomness by using verifiable random functions.

This pallet provides production-grade randomness, and is used in Polkadot. If you select this pallet as the source of randomness your blockchain must use the blind assignment of blockchain extension (BABE) slot-based consensus for producing blocks.

Consuming randomness

The Randomness trait provides the following methods for consuming randomness:

  • The random_seed method takes no parameters and return a raw random value. If you call this method multiple times in a block, it returns the same value each time. Therefore, in most cases, you shouldn't use this method directly.

  • The random method takes a byte-array as a context identifier and returns a result that is unique to this context and independent from other contexts as allowed by the underlying randomness source.

Pallets that require random values don't need to provide the randomness source but they do need to specify a randomness source that implements the Randomness trait.

Security guarantees

It's important to keep in mind that the Randomness trait provides a convenient abstraction for defining a randomness source in the runtimes, but the trait itself does not make any security guarantees. It's up to you as a runtime developer to ensure that the randomness source you use meets the security requirements for all of the pallets that consume its randomness.

Where to go next

Last updated