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
Prev Previous commit
Next Next commit
make more configurable but keep defaults
4meta5 committed Sep 6, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 9b73ca44604a991f3fee4caf7b0e3d7606add43c
54 changes: 45 additions & 9 deletions primitives/parachain-inherent/src/mock.rs
Original file line number Diff line number Diff line change
@@ -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
@@ -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.
@@ -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 takes first 4 bytes of relay epoch as randomness
/// A more random appearing 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[..4].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
@@ -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,
@@ -178,13 +206,21 @@ 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
sproof_builder.current_epoch = self.current_para_block.into();
// Randomness is set equal to current relay block
// could improve mock randomness by XOR with [u8::MAX; 32]
let mut mock_randomness: [u8; 32] = [0u8; 32];
mock_randomness[..4].copy_from_slice(&relay_parent_number.to_be_bytes());
sproof_builder.randomness = mock_randomness.into();
// 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();