Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Mock epoch index and randomness in SproofBuilder (for testing) #1594

Merged
merged 18 commits into from
Sep 8, 2022
Merged
2 changes: 1 addition & 1 deletion primitives/parachain-inherent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub use client_side::*;
#[cfg(feature = "std")]
mod mock;
#[cfg(feature = "std")]
pub use mock::{MockValidationDataInherentDataProvider, MockXcmConfig};
pub use mock::{MockRandomnessConfig, MockValidationDataInherentDataProvider, MockXcmConfig};

/// The identifier for the parachain inherent.
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"sysi1337";
Expand Down
48 changes: 46 additions & 2 deletions primitives/parachain-inherent/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
/// in addition to the messages themselves, you must provide some information about
/// your parachain's configuration in order to mock the MQC heads properly.
/// See [`MockXcmConfig`] for more information
pub struct MockValidationDataInherentDataProvider {
pub struct MockValidationDataInherentDataProvider<R = ()> {
/// The current block number of the local block chain (the parachain)
pub current_para_block: u32,
/// The relay block in which this parachain appeared to start. This will be the relay block
Expand All @@ -51,6 +51,8 @@ pub struct MockValidationDataInherentDataProvider {
/// The number of relay blocks that elapses between each parablock. Probably set this to 1 or 2
/// to simulate optimistic or realistic relay chain behavior.
pub relay_blocks_per_para_block: u32,
/// Relay epoch index and babe one epoch ago randomness
pub randomness_config: MockRandomnessConfig<R>,
/// XCM messages and associated configuration information.
pub xcm_config: MockXcmConfig,
/// Inbound downward XCM messages to be injected into the block.
Expand All @@ -59,6 +61,30 @@ pub struct MockValidationDataInherentDataProvider {
pub raw_horizontal_messages: Vec<(ParaId, Vec<u8>)>,
}

pub trait GenerateRandomness<I> {
fn generate_randomness(&self, input: I) -> relay_chain::Hash;
}

impl GenerateRandomness<u64> for () {
/// Default implementation uses relay epoch as randomness value
/// A more seemingly random implementation may hash the relay epoch instead
fn generate_randomness(&self, input: u64) -> relay_chain::Hash {
let mut mock_randomness: [u8; 32] = [0u8; 32];
mock_randomness[..8].copy_from_slice(&input.to_be_bytes());
mock_randomness.into()
}
}

/// Parameters for how the Mock inherent data provider should inject the relay
/// epoch index and BABE one epoch ago randomness.
pub struct MockRandomnessConfig<R> {
/// Number of parachain blocks per relay chain epoch
/// Mock epoch is computed by dividing `current_para_block` by this value.
pub para_blocks_per_epoch: u32,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that part of the RandomnessConfig?

Copy link
Contributor Author

@4meta5 4meta5 Sep 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default configuration updates the randomness whenever the epoch changes so I put them together, but now rethinking it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll move the fields into MockValidationDataInherentDataProvider and get rid of this struct as that is preferred.

/// Function to mock BABE one epoch ago randomness using input current epoch
pub generator: R,
}

/// Parameters for how the Mock inherent data provider should inject XCM messages.
/// In addition to the messages themselves, some information about the parachain's
/// configuration is also required so that the MQC heads can be read out of the
Expand Down Expand Up @@ -130,7 +156,9 @@ impl MockXcmConfig {
}

#[async_trait::async_trait]
impl InherentDataProvider for MockValidationDataInherentDataProvider {
impl<R: Send + Sync + GenerateRandomness<u64>> InherentDataProvider
for MockValidationDataInherentDataProvider<R>
{
fn provide_inherent_data(
&self,
inherent_data: &mut InherentData,
Expand Down Expand Up @@ -178,6 +206,22 @@ impl InherentDataProvider for MockValidationDataInherentDataProvider {
sproof_builder.upsert_inbound_channel(*para_id).mqc_head = Some(channel_mqc.head());
}

// Epoch is set equal to current para block / blocks per epoch
sproof_builder.current_epoch =
if self.current_para_block < self.randomness_config.para_blocks_per_epoch {
0u64
} else if self.randomness_config.para_blocks_per_epoch == 0u32 {
// do not divide by 0 => set epoch to para block number
self.current_para_block.into()
} else {
(self.current_para_block / self.randomness_config.para_blocks_per_epoch).into()
};
// Randomness is set by randomness generator
sproof_builder.randomness = self
.randomness_config
.generator
.generate_randomness(sproof_builder.current_epoch);

let (relay_parent_storage_root, proof) = sproof_builder.into_state_root_and_proof();

inherent_data.put_data(
Expand Down
6 changes: 6 additions & 0 deletions test/relay-sproof-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub struct RelayStateSproofBuilder {
pub hrmp_channels: BTreeMap<relay_chain::v2::HrmpChannelId, AbridgedHrmpChannel>,
pub current_slot: relay_chain::v2::Slot,
pub current_epoch: u64,
pub randomness: relay_chain::Hash,
}

impl Default for RelayStateSproofBuilder {
Expand All @@ -69,6 +70,7 @@ impl Default for RelayStateSproofBuilder {
hrmp_channels: BTreeMap::new(),
current_slot: 0.into(),
current_epoch: 0u64,
randomness: relay_chain::Hash::default(),
}
}
}
Expand Down Expand Up @@ -156,6 +158,10 @@ impl RelayStateSproofBuilder {
insert(relay_chain::well_known_keys::hrmp_channels(channel), metadata.encode());
}
insert(relay_chain::well_known_keys::EPOCH_INDEX.to_vec(), self.current_epoch.encode());
insert(
relay_chain::well_known_keys::ONE_EPOCH_AGO_RANDOMNESS.to_vec(),
self.randomness.encode(),
);
insert(relay_chain::well_known_keys::CURRENT_SLOT.to_vec(), self.current_slot.encode());
}

Expand Down