4

I would like to use BABE's randomness for some on-chain logic. IIUC using BABE inside a parachain's runtime is not recommended good practice because there's no fallback for producing blocks if no collator is found, so parachain runtime developers must use Aura.

Is there a way for me to benefit from BABE's randomness in my parachain's runtime, perhaps from the relay chain?

2 Answers 2

4

Yes, you can use the randomness from the relay chain. It is currently not that easy, but you should be able to do it in the following way:

In your runtime:

impl cumulus_parachain_system::Config for Runtime {
    type OnSystemEvent = MySystemEventHandler;
    ...
}

Wherever MySystemEventHandler is implemented:

impl OnSystemEvent for MySystemEventHandler {
    fn on_validation_data(data: &PersistedValidationData) {
        let proof = cumulus_parachain_system::RelayChainStateProof::new(my_para_id, data.relay_parent_storage_root, cumulus_parachain_system::Pallet::relay_state_proof()).expect("Invalid relay chain proof");

       use cumulus_primitives_core::relay_chain::well_known_keys as relay_well_known_keys;
       let randomness = proof.read_entry::<schnorrkel::Randomness>(relay_well_known_keys::CURRENT_BLOCK_RANDOMNESS);
    }
    ..
}

There exists three different types of randomness that BABE can provide to you. See here for a description of each of them.

3
  • Can you give a working example how to put the randomness source inside a custom pallet? Can you give examples how all of these github.com/paritytech/substrate/blob/… are used?
    – Chralt
    Mar 3, 2023 at 9:41
  • How can I include schnorrkel in my runtime?
    – Chralt
    Mar 3, 2023 at 10:15
  • 1
    Check the answer below by Sacha.
    – bkchr
    Mar 3, 2023 at 19:44
2

It seems like Moonbeam/Moonriver has a way to do this using a runtime API for client side VRF verification (see: full code snip and original PR):

pub struct BabeDataGetter;
impl pallet_randomness::GetBabeData<u64, Option<Hash>> for BabeDataGetter {
    // Tolerate panic here because only ever called in inherent (so can be omitted)
    fn get_epoch_index() -> u64 {
        relay_chain_state_proof()
            .read_optional_entry(relay_chain::well_known_keys::EPOCH_INDEX)
            .ok()
            .flatten()
            .expect("expected to be able to read epoch index from relay chain state proof")
    }
    fn get_epoch_randomness() -> Option<Hash> {
        relay_chain_state_proof()
            .read_optional_entry(relay_chain::well_known_keys::ONE_EPOCH_AGO_RANDOMNESS)
            .ok()
            .flatten()
    }
}

impl pallet_randomness::Config for Runtime {
    type Event = Event;
    type AddressMapping = moonbeam_runtime_common::IntoAddressMapping;
    type Currency = Balances;
    type BabeDataGetter = BabeDataGetter; // <--- used here
    ...
 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.