use std::{sync::Arc, time::Duration};
use parity_scale_codec::Encode;
use sp_consensus_aura::{Slot, SlotDuration, AURA_ENGINE_ID};
use sp_consensus_babe::{
digests::{PreDigest, SecondaryPlainPreDigest},
BABE_ENGINE_ID,
};
use sp_inherents::InherentData;
use sp_runtime::{
traits::{Block as BlockT, HashingFor},
Digest, DigestItem,
};
use sp_state_machine::TestExternalities;
use sp_std::prelude::*;
use strum_macros::{Display, EnumIter};
use tokio::sync::Mutex;
use crate::common::empty_block::inherents::custom_idps;
const RELAYCHAIN_BLOCKTIME_MS: u64 = 6000u64;
pub trait InherentProvider<B: BlockT> {
type Err;
fn get_inherent_providers_and_pre_digest(
&self,
maybe_parent_info: Option<(InherentData, Digest)>,
parent_header: B::Header,
ext: Arc<Mutex<TestExternalities<HashingFor<B>>>>,
) -> InherentProviderResult<Self::Err>;
}
type InherentProviderResult<Err> =
Result<(Box<dyn sp_inherents::InherentDataProvider>, Vec<DigestItem>), Err>;
#[derive(Debug, Clone, EnumIter, Display, Copy)]
pub enum ProviderVariant {
Smart(core::time::Duration),
}
impl<B: BlockT> InherentProvider<B> for ProviderVariant {
type Err = String;
fn get_inherent_providers_and_pre_digest(
&self,
maybe_parent_info: Option<(InherentData, Digest)>,
parent_header: B::Header,
ext: Arc<Mutex<TestExternalities<HashingFor<B>>>>,
) -> InherentProviderResult<Self::Err> {
match *self {
ProviderVariant::Smart(blocktime) => {
<SmartInherentProvider as InherentProvider<B>>::get_inherent_providers_and_pre_digest(&SmartInherentProvider {
blocktime,
}, maybe_parent_info, parent_header, ext)
}
}
}
}
struct SmartInherentProvider {
blocktime: Duration,
}
impl<B: BlockT> InherentProvider<B> for SmartInherentProvider {
type Err = String;
fn get_inherent_providers_and_pre_digest(
&self,
maybe_parent_info: Option<(InherentData, Digest)>,
parent_header: B::Header,
ext: Arc<Mutex<TestExternalities<HashingFor<B>>>>,
) -> InherentProviderResult<Self::Err> {
let timestamp_idp = custom_idps::timestamp::InherentDataProvider {
blocktime_millis: self.blocktime.as_millis() as u64,
maybe_parent_info,
};
let para_parachain_idp = custom_idps::para_parachain::InherentDataProvider::<B> {
blocktime_millis: RELAYCHAIN_BLOCKTIME_MS,
parent_header: parent_header.clone(),
timestamp: timestamp_idp.timestamp(),
ext_mutex: ext,
};
let relay_parachain_data_idp =
custom_idps::relay_parachains::InherentDataProvider::<B>::new(parent_header);
let slot = Slot::from_timestamp(
timestamp_idp.timestamp(),
SlotDuration::from_millis(self.blocktime.as_millis() as u64),
);
let digest = vec![
DigestItem::PreRuntime(
BABE_ENGINE_ID,
PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
slot,
authority_index: 0,
})
.encode(),
),
DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()),
];
Ok((
Box::new((timestamp_idp, para_parachain_idp, relay_parachain_data_idp)),
digest,
))
}
}