RSS Amplifier

SHARDLAB · Apr 25, 2025

Randomness in Blockchain

0
Sign in to vote or save

Toby Kim, SHARDLAB · SHARDLAB

At its core, the blockchain system is designed with the philosophy that it must be more transparent and fair than any other system. All data must be verifiable, and anyone should be able to reproduce the same results under the same conditions.

However, this very property ironically becomes an obstacle when we try to generate “true randomness,” which must be unpredictable. Verifiability and unpredictability are, in essence, opposing concepts.

So in this article, we’ll be exploring a few key questions:

  • Why is randomness such a challenging problem in blockchain?

  • How can we produce random numbers that are both unpredictable and tamper-proof?

  • What do the main solutions look like under the hood?

  • Which approach should we choose when implementing real-world applications?

A random number is a value whose outcome cannot be predicted and is statistically uniform in its distribution. In nature, random numbers (e.g., those derived from atmospheric noise or radioactive decay) rely on external physical phenomena, so we can call them “truly random.” However, a computer program fundamentally works in a deterministic manner, making it difficult—if not impossible—to produce “completely random” values purely from internal processes.

There are generally two approaches to generating random numbers on a computer:

  1. True Random Number Generator (TRNG)

    • Relies on physical phenomena (like atmospheric noise or radioactive decay) measured by sensors to generate randomness.

    • It’s very hard to predict, but it often requires specialized hardware or sensors, can be expensive to implement, and may be slow.

  2. Pseudo-Random Number Generator (PRNG)

    • Uses mathematical algorithms to produce sequences that appear random.

    • A given seed will always generate the same sequence of numbers if the algorithm is repeated.

    • This method is fast and convenient, and it’s used in most software-based random number generators. However, if the seed or internal state is leaked, it’s possible for an attacker to predict the future outputs.

In a decentralized system like a blockchain, transparency and verifiability are crucial. Yet we need a random number that’s unpredictable and still verifiable by every participant. Over the years, various solutions have been proposed, and we’ll walk through a few of the major approaches.

Because all nodes in a blockchain network must maintain the same state, it’s not feasible to simply call a function like random() arbitrarily. If one node produces a different random value than another node, the network’s consensus would break.

Any data stored on-chain is ultimately visible to everyone. Even if you try to keep your random seed hidden, at some point it may become public on the chain. As soon as it’s in a predictable state, attackers could exploit it.

Whether a blockchain is PoW (miner-based) or PoS (validator-based), the entity that creates the block can attempt to manipulate certain elements—like re-trying block hashes or rearranging transactions—to get a favorable outcome.

If you rely on block hashes or timestamps alone for randomness, a block producer might simply discard (“orphan”) a block if the resulting hash isn’t what they want. They can keep trying until they get a hash that suits them.

As mentioned, the blockchain is a deterministic and transparent environment, which makes it tough to achieve true randomness. While values like blockhash, difficulty, or timestamp may look “random,” they’re still produced deterministically by block producers and can be manipulated to some degree.

pragma solidity ^0.8.0;
contract RandomContract {
    function getRandom() public view returns (uint256) {
        bytes32 blockHash = blockhash(block.number - 1);
        uint256 randomValue = uint256(
            keccak256(
                abi.encodePacked(blockHash, msg.sender, block.timestamp)
            )
        );
        return (randomValue % 100) + 1;
    }
}

This doesn’t provide secure randomness. For high-stakes use cases—such as games, lotteries, or anything with real monetary value—this approach is strongly discouraged.

Commit & Reveal is a technique where participants first submit (Commit) a hash of a secret value, and then later reveal (Reveal) the original value. By hashing the secret initially, no one can know the actual input until it’s revealed. This can mitigate third-party manipulation (including by block producers) and help ensure fairness.

  • Commit: Each participant chooses a random seed and a secret salt, then submits the hash (e.g., via keccak256) to the blockchain. At this point, nobody knows the actual inputs—only the hash.

  • Reveal: After the commit phase, each participant discloses their original data (seed, salt). Other participants verify that the hash matches the committed value.

Below is a simple Solidity example:

pragma solidity ^0.8.0;
contract SimpleLottery {
    mapping(address => bytes32) public commits;
    mapping(address => uint256) public revealedSeed;
    address[] public players;
    /**
     * @dev Commit phase: submit the hash.
     *  - hash = keccak256(abi.encodePacked(seed, salt))
     */
    function commitHash(bytes32 _commit) external {
        require(commits[msg.sender] == 0, "Already committed");
        commits[msg.sender] = _commit;
        players.push(msg.sender);
    }
    /**
     * @dev Reveal phase: disclose the actual seed and salt.
     */
    function revealSeed(uint256 _seed, string memory _salt) external {
        require(commits[msg.sender] != 0, "No commit found");
        bytes32 checkHash = keccak256(abi.encodePacked(_seed, _salt));
        require(checkHash == commits[msg.sender], "Invalid reveal");
        revealedSeed[msg.sender] = _seed;
    }
    /**
     * @dev A simple example of deriving a final random number
     *      by hashing all revealed seeds together.
     */
    function getFinalRandom() external view returns (uint256) {
        uint256 totalSeed;
        for (uint256 i = 0; i < players.length; i++) {
            totalSeed += revealedSeed[players[i]];
        }
        return uint256(keccak256(abi.encodePacked(totalSeed)));
    }
}

Here, the final random value depends on the combination of everyone’s revealed seeds. Because the original seeds are hashed beforehand, it’s hard to predict them in advance. However, if certain participants collude, they might influence the final value, and if someone doesn’t reveal, the process can stall. Practical implementations usually require additional safeguards like strict reveal deadlines or penalties.

A VRF uses a secret key (sk) to generate an output (β) from an input (α) in such a way that β looks random, while also producing a proof (π) that β indeed came from α. Anyone can verify this proof using the corresponding public key (pk), but only the holder of the secret key can produce a valid β–π pair.

\(VRFsk​(α)→(β,π)\)

  • Input (α)

  • Secret Key (sk)

  • Output (β): Pseudorandom-looking result

  • Proof (π): Cryptographic proof that β was derived from α

The verification step uses:

\(Verifypk​(α,β,π)→{True / False}\)

  • Public Key (pk) corresponding to sk

  • α, β, π

  • Returns True if valid, False if tampered

VRFs stand out because they provide cryptographic assurance that the random output hasn’t been altered. Thanks to this property, VRFs are widely considered one of the most robust ways to generate randomness on-chain. Chainlink, for instance, offers a VRF service that DApps can use without needing deep cryptographic expertise, making it a popular choice in the blockchain ecosystem.

Aavegotchi, PoolTogether, and others are utilizing Chainlink VRFs to ensure the reliability of their random numbers, especially in the NFT/Gaming space. For more examples, check out the Chainlink Case Study.

We've prepared a learning module showcasing how to use Chainlink VRF for generating random numbers in a DApp. Through this module, we hope you'll gain a clear understanding of how randomness can be practically applied in the blockchain (DApp) environment.

In this learning module, we expect you to interact with a contract that interfaces with a VRF deployed on a real on-chain (Bsc Testnet) and gain a better understanding of the real case.

  • In a blockchain environment, the deterministic and transparent nature makes generating random numbers far more difficult than in traditional computing systems.

  • From simpler approaches (like hash-based methods or Commit & Reveal) to cryptographically verifiable techniques (like VRF), each solution has its own strengths and weaknesses. It’s essential to choose the right one based on the dApp’s required level of security, acceptable delay, and implementation complexity.

Read the original on 0xshardlab.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.