Rando

Introduction

Rando aims to be a fast, secure, transparent, verifiable, decentralized source of randomness on the Solana blockchain. Rando provides a base program for other programs to request random number, and fulfill the request in speedy manner. Any application require randomness, such as lottery, in-game mechanic, casinos can be built on top of Rando.

Currently we have a Roulette game deployed on Mainnet using real USDC as a simple demo.

Design

Rando itself is a standalone program written in Anchor on the Solana broadcast network. It has two sets of public keys stored inside the program:

  • Validators: A list (max 16) of public keys responsible for signing seed provided by users, and generates random numbers from the aggregation of signed messages. These keys are distributed among trusted, unrelated third parties.

  • Authority: A multi-sig admin key responsible for maintaining the list of Oracles.

Users or dApp request a new randomness by submitting a transaction. This transaction should provide the two major components:

  • Request Reference: A public key as a random seed, usually generated by using `new web3.Keypair()`

  • Vault: An account (blockspace on Solana blockchain) that can only be written by the Rando program. This "Vault" account is used to store the random result, and accessed by the dApp to read the random result.

If the dApp contains any wagers, the token transfer will also happen in the same transaction for better UX and locking the result of the randomness to the wager.

Once the transaction reaches the chain, all Validators will be notified off-chain. Each Validator then uses its private key to sign the Request Reference via ed25519. The result of the signature is a byte array and it's used as a partial result of the final random number.

The Validator then submit a new transaction to write their partial result onto the chain. All Validator results are aggregated together to generate a new random number in the range of (0, 340282366920938463463374607431768211455). The result is written onto the Vault account as a u128 for dApp to read.

The security of the randomness depends on the Validator keys are securely held among un-collude parties. Anyone with control of all keys can control the result of all randomenss by gaming the Request Reference.

dApp Integration

Thanks to Anchor, Rando should be very simple to integrate with. A coin-flipping app can be written with less than 100 lines, including its own logic (github).

Other than the Vault account owned by Rando, the dApp also needs to create a Bet account themselves to store the user's betting states and the address of the Vault account.

The main flow for the dApp is the following:

  • (Front-end) The dApp creates the Vault account for Rando and Bet Account.

  • (Front-end) The user picks their bet and signs a transaction via web wallet.

  • (On-chain) The dApp's Request instruction records the user's bet onto the Bet Account, and does a Cross Program Invocation to the Rando program, notifying it needs a new random number.

  • (On-chain) Rando writes the random number results into the specific Vault within ~1-3 seconds.

  • (Off-chain) Anyone (dApp operator / the user) can submit another transaction to settle the bet when the result is filled.

  • (On-chain) dApp's on-chain Settle instruction reads the result of the random number in the Vault, and determines who wins the wager, and settles the bet. Since user's token is already transferred into the Bet Account, user has no way to back out of the bet.

Limitation & Possibilities

The project was inspired by a Twitter discussion with Mango's founder Daffy on writing an on-chain poker game. However, although Rando can handle card shuffling or random card drawing, it can not hide players' cards from each other since the blockchain is a transparent space.

This means all games with pre-determined hidden info are not suitable, such as Texas Holdem, Balck Jack (dealer's hidden card).

Any other random number driven games can be easily developed:

  • Satoshi dice

  • Roulette

  • Lottery

  • Baccarat

  • Craps

  • Video Poker

If you are a frontend developer and interested in building any of the above, please feel free to reach out. All support on the Rust side will be provided.

State of Affairs & Improvement Needs

Currently, the Rando base program is deployed on Mainnet and Devnet. You can directly import it into your dApp via crates without knowing the programID.

There are two Validator keys own by me and myself, and I am currently looking for trusted individuals or DAO to add security to the program.

In addition, the on-chain validation of the ed25519 signature is not implemented yet. The validator can write any number onto the chain and claim it as valid. Soon on Anchor's next update, Rando should be able to leverage Solana 1.8's new ed25519 program to verify on-chain the Validator is submitting results signed by their private key and Request Reference (seed).

The final aggregated random number is currently weaved together by each validator providing one u8 from their byte array. This is not a safe design, and should be changed to a chain signature from each validator: vN.sign(...v3.sign(v2.sign((v1.sign(seed))))). An offline aggregation model can be implemented to ensure this is done within seconds.

Lastly, if you visited the Roulette app, you can tell I am not much of a frontend engineer. Any frontend engineer interested in building an on-chain gaming app please reach out. All help will be provided =)

Last updated