Generating on-chain randomness
Useful in instances to generate unique values or select things without bias.
#
GoalImplement randomness for a pallet.
#
Use cases- NFT applications
- Casino gaming type applications
#
OverviewRandomness is useful in computer programs for everything from gaming applications to selecting block authors. True randomness is hard to come by in deterministic computers. This is particularly true in the context of a blockchain when all the nodes in the network must agree on the state of the chain. FRAME provides runtime engineers with a source of randomness, using the Randomness trait.
This guide would step you through making use of FRAME's Randomness trait by using it's random
method and a nonce as a subject.
For additional entropy to the randomness value, the last step shows how to assign the RandomnessCollectiveFlip
pallet
to the configuration trait of a pallet exposing some "random" type.
#
StepsRandomness
#
1. Import From frame_support
, import the Randomness
trait:
Now you'll have to include it in your pallet's configuration trait:
Notice that the Randomness
trait specifies a generic return of type Output
. Use sp_core::H256
in your pallet
to satisfy that trait requirement.
A warning on using this trait:
From the documentation: "This gives you something that approximates [real randomness]. At best, this will be randomness which was hard to predict a long time ago, but that has become easy to predict recently."
#
2. Create a nonceUse a nonce to use as a subject for the frame_support::traits::Randomness::random(subject: &[u8])
method.
There's two steps to including a nonce in your pallet:
- Create a
Nonce
storage item. This could be of typeu32
oru64
(no need for it to be larger). - Create a private nonce function. This will be used to increment the nonce each time it's used.
The increment_nonce()
private function could be implemented in such a way that it returns the nonce as well as
updates it. Using this approach it would look like this:
note
Learn more about wrapping_add
and encode()
in the Rust documentation.
#
3. Use Randomness in a dispatchableUsing the nonce, you can call the random()
method that Randomness
exposes. The code snippet below is a made up example
that assumes relevant events and storage items have been implemented:
#
4. Updating your pallet's runtime implementationHaving added a type to your pallet's configuration trait Config
opens up the opportunity to further enhance the
randomness derived by the Randomness
trait, by using the Randomness Collective Flip pallet.
Using this pallet alongside the Randomness
trait will significantly improve the entropy being processed by random()
.
In runtime/lib.rs
, assuming pallet_random_collective_flip
is instantiated at RandomnessCollectiveFlip
, specify your exposed
type: