use polkadot_sdk::*;
use crate::{client::FullClientFor, with_state, ChainInfo};
use codec::Encode;
use cumulus_primitives_parachain_inherent::ParachainInherentData;
use futures::lock::Mutex;
use num_traits::AsPrimitive;
use polkadot_primitives::PersistedValidationData;
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::{Block, Header};
use sp_wasm_interface::{anyhow, anyhow::anyhow};
use std::{marker::PhantomData, sync::Arc};
pub struct ParachainSproofInherentProvider<T: ChainInfo> {
client: Arc<FullClientFor<T>>,
sproof_builder: Option<RelayStateSproofBuilder>,
slot_duration: u64,
_phantom: PhantomData<T>,
}
pub type SharedParachainSproofInherentProvider<T> = Arc<Mutex<ParachainSproofInherentProvider<T>>>;
impl<T> ParachainSproofInherentProvider<T>
where
T: ChainInfo,
T::Runtime: staging_parachain_info::Config,
<<T::Block as Block>::Header as Header>::Number: AsPrimitive<u32>,
{
pub fn new(client: Arc<FullClientFor<T>>, slot_duration: u64) -> Self {
ParachainSproofInherentProvider {
client,
slot_duration,
sproof_builder: None,
_phantom: PhantomData,
}
}
pub fn update_sproof_builder(&mut self, sproof: RelayStateSproofBuilder) {
self.sproof_builder = Some(sproof);
}
pub fn create_inherent(
&mut self,
slot: u64,
parent: <T::Block as Block>::Hash,
) -> Result<ParachainInherentData, anyhow::Error> {
let mut sproof = self.sproof_builder.take().unwrap_or_default();
sproof.para_id = with_state::<T, _>(self.client.clone(), None, || {
staging_parachain_info::Pallet::<T::Runtime>::parachain_id()
});
sproof.current_slot = if self.slot_duration == 12_000 {
((slot * 2) + 1).into()
} else {
slot.into()
};
sproof.host_config.validation_upgrade_delay = 2;
sproof.host_config.max_code_size = 15 * 1024 * 1024;
sproof.included_para_head =
self.client.header(parent).ok().flatten().map(|h| Into::into(h.encode()));
sproof.randomness = rand::random();
let info = self.client.info();
let header = self
.client
.header(info.best_hash)?
.ok_or_else(|| anyhow!("Couldn't fetch best header!"))?
.encode();
let (state_root, proof) = sproof.into_state_root_and_proof();
Ok(ParachainInherentData {
validation_data: PersistedValidationData {
parent_head: header.into(),
relay_parent_number: info.best_number.as_() + 100,
relay_parent_storage_root: state_root,
max_pov_size: 15 * 1024 * 1024,
},
relay_chain_state: proof,
downward_messages: Default::default(),
horizontal_messages: Default::default(),
collator_peer_id: None,
relay_parent_descendants: vec![],
})
}
}