back12 Jan 20247 min read
blog post image

Secure Random Number Generation for Blockchain Applications

Many blockchain applications need access to a secure source of randomly generated numbers.

For example, a profile picture NFT drop needs to select random attribute combinations for each NFT. Alternatively, a video game running on the blockchain may wish to randomly draw the items in a treasure chest when it is opened. In both of these cases, a secure random number generator makes the application provably fair for users. These are just some possible applications for random numbers — in general, randomness is a useful tool to solve many different kinds of algorithmic problems.

Unfortunately, the inherent properties of blockchains make it more difficult to generate random numbers. The state of the blockchain evolves according to a deterministic set of rules, where each transaction generates a specific output state given its inputs. These rules must be deterministic because every validator must be able to verify the processing of every transaction. If the rules were not deterministic, then validators could disagree about the state.

However, there are a variety of random number generation approaches that work on blockchains. This article explains and analyzes some of these approaches.

Participants

A random number generation protocol generally involves multiple different participants. Each participant is a person who either participates in the protocol, or has an interest in the result. Depending on the approach, different subsets of the following participants will be involved. The possible participants are:

Application Developer — The developer writes the software that requests and uses the random number. Although the developer typically does not play an active role in generating the random number, the developer wants the result to be truly random. For example, the developer of an NFT collection wants to be certain that no one can cheat their protocol to mint an NFT with all of the rarest attributes.

User — The user interacts with a protocol to initiate a random number request. For example, the user could be the person minting an NFT.

Validator — Many random number generation protocols use input data from the blockchain. The validator(s) of the blockchain (or miners / sequencers, as the case may be) may have some control over that input data.

Service Provider — Many protocols have a designated off-chain service provider that is responsible for some part of the process. This service provider is supposed to be a neutral third party, but the more sophisticated random number generation approaches will minimize the amount of trust vested in this participant.

Note that a single person could potentially play the role of multiple participants. For example, the user could also run a validator on the network. Many of the attack vectors on these protocols will come from scenarios where multiple participants are secretly working together.

Properties

Before we talk about approaches, we should agree on the desired properties of a random number generator.

Every random number generator runs in two phases. First, the user requests a random number in the request phase. Second, the random number is generated and published to the blockchain in the reveal phase. Each of these phases requires at least one blockchain transaction — it is not possible to securely generate an on-chain random number in a single transaction. The exact computations performed in each phase will differ between the various protocols, however.

There are three security properties that we care about:

Unpredictability — Before the random number is requested, none of the participants should be able to predict the random value with odds better than chance. This property is simply a formal definition of “random”.

Determinism — After the random number is requested, there is exactly one possible value that it can take. This property ensures that participants cannot influence the result after it has been requested.

Liveness — After the random number is requested, the protocol runs through completion. That is, the reveal phase also completes.

The critical question to ask about a random number generation protocol is: under what conditions do these properties hold? For example, a protocol may require the service provider to act honestly. These conditions are the trust assumptions of the protocol. The fewer trust assumptions, the more secure the protocol is.


Approaches to Randomness

Trusted Third Party

The simplest possible protocol is to have a service provider who generates the random number. When a user requests a random number, the service provider simply generates one off-chain and posts it back to the blockchain.

This approach is extremely simple, but requires strong trust assumptions: the participants must trust the honesty of the service provider. The service provider can pick the random number, and also has the ability to halt the protocol. These assumptions can be improved somewhat by having the service provider compute inside a secure enclave, such as Intel SGX, though such enclaves have repeatedly demonstrated that they are imperfect (e.g. SgxPectre Attacks).

Blockhash

One simple random number generation strategy is to use the blockhash of a future block. The request transaction saves the current (or a future) block number. The validators of the network then compute the blockhash for that block. Once the blockhash is available, the reveal transaction simply returns it.

The blockhash approach is simple and easy to use on any blockchain. However, it requires strong assumptions: the participants must trust the honesty of the validator. The validator can reorder or omit transactions to modify the blockhash. Thus, an attack is that the user of the protocol either runs or colludes with a validator to ensure that a favorable random number is chosen.

Verifiable Random Function

Thus far, the problem with previous approaches has been that a single participant can influence the result (thereby rendering it predictable). Verifiable Random Functions eliminate this attack vector by requiring multiple participants to collaborate in order to influence the random number.

A VRF is a function f_s(x) = (y,p) with the property that the output y looks random, but is deterministically computed from the input x and secret key s. Furthermore, the function returns a proof p that anyone can check to verify that y is the correct output. (This explanation is somewhat simplified. See the IETF RFC on VRFs for a more thorough explanation).

On the blockchain, VRFs are typically used as follows. First, the input x is partially provided by the user and partially derived from the blockhash. An off-chain service provider with the secret key s watches the blockchain for requests, and submits on-chain responses (y,p). The reveal transaction checks the proof p to ensure that y is the correct value, then proceeds.

The benefit of VRF is that it improves the trust assumptions over previous approaches: the user, validator, and service provider all must collude in order to predict the random number. The main concern with VRF is liveness: participants must trust the service provider to not censor transactions. The service provider can see the generated random number and choose whether or not to submit it to the blockchain. For example a possible attack could be: the user submits a request to say flip a coin, then colludes with the VRF provider to only complete the request if the outcome is heads. However, these attacks can be mitigated by the application developer — in particular, as long as the user cannot benefit from a failure to reveal, there is no incentive to perform this attack.

A further drawback of VRF is that the cryptography is relatively complicated and computationally intensive. Most blockchains do not provide built-in implementations of all of the necessary cryptographic primitives, so implementations can use a lot of gas or require multiple transactions.

Commit-Reveal

VRFs are not the only way to improve the trust assumptions of random number generation. Another approach is a commit-reveal protocol for random number generation between mutually untrusting parties. The basic version of this protocol works as follows:

  1. In the request phase, both the user and and the service provider generate a secret random number. They both submit the hash of that random number to the blockchain. The hash is called a commitment.
  2. In the reveal phase, both the user and service provider reveal their random numbers. Each participant checks that the other participant’s revealed number hashes to their commitment. Then, the random number is the hash of the two random numbers. For blockchain implementations, the blockhash from the request transactions can also be included in this final hashing step.

The commit-reveal protocol similarly improves the trust assumptions over the initial approaches: the user, validator and service provider must all collude to predict the random number. Additionally, this protocol only uses simple cryptography — it only needs a hash function — so it is simple to implement. This protocol has a similar liveness issue to VRF, however: whichever of the user or service provider reveals their random number second can halt the protocol. As with VRF, this attack vector can be mitigated by the application developer using the same techniques mentioned above for VRF.

Note that a naive implementation of this protocol will require more than two transactions, because both the user and the service provider need to send transactions in each of the two phases. This drawback can be solved through a more sophisticated implementation that allows the service provider to commit to many numbers up-front. Pyth Entropy is just such a sophisticated implementation of a commit-reveal protocol.

Both VRF and commit-reveal allow application developers to gain unpredictability at the cost of liveness. If developers are worried about trusting one service provider, they can simply request random numbers from N service providers instead and combine the results. This approach improves unpredictability — all of the N providers need to collaborate to influence the outcome — but reduces liveness — any one of the N providers can prevent the random number from being revealed. However, note that none of the N providers alone knows what the final random number is, so they cannot use that knowledge to decide when to stop the protocol.

Other Approaches

There are other more advanced approaches to generate secure random numbers. These approaches aim to improve the unpredictability/liveness tradeoff from above, such that > 1 provider is required to halt the protocol. One such approach is a threshold VRF, where the secret key s for the VRF is sharded amongst multiple participants. Another approach is a random beacon. While these approaches do have better security tradeoffs than those above, they are somewhat overkill for most applications, especially since liveness problem can be mitigated through application design.

Conclusion

This article has walked through several approaches to random number generation on the blockchain and analyzed their pros and cons. If you’re developing an application that needs secure random number generation, check out Pyth Entropy and reach out to Pyth contributors via Discord, Telegram or other social channels, on how you can leverage this innovative new product from Pyth.


We can’t wait to hear what you think! You can join the Pyth Discord and Telegram, and follow us on X and LinkedIn.

Stay Updated with Pyth

Stay informed about Pyth network's development and upcoming events!