1use polkadot_sdk::*;
21
22use crate::{client::FullClientFor, with_state, ChainInfo};
23use codec::Encode;
24use cumulus_primitives_parachain_inherent::ParachainInherentData;
25use futures::lock::Mutex;
26use num_traits::AsPrimitive;
27use polkadot_primitives::PersistedValidationData;
28
29use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
30use sp_blockchain::HeaderBackend;
31use sp_runtime::traits::{Block, Header};
32use sp_wasm_interface::{anyhow, anyhow::anyhow};
33use std::{marker::PhantomData, sync::Arc};
34
35pub struct ParachainSproofInherentProvider<T: ChainInfo> {
38 client: Arc<FullClientFor<T>>,
40 sproof_builder: Option<RelayStateSproofBuilder>,
42 slot_duration: u64,
44 _phantom: PhantomData<T>,
46}
47
48pub type SharedParachainSproofInherentProvider<T> = Arc<Mutex<ParachainSproofInherentProvider<T>>>;
50
51impl<T> ParachainSproofInherentProvider<T>
52where
53 T: ChainInfo,
54 T::Runtime: staging_parachain_info::Config,
55 <<T::Block as Block>::Header as Header>::Number: AsPrimitive<u32>,
56{
57 pub fn new(client: Arc<FullClientFor<T>>, slot_duration: u64) -> Self {
59 ParachainSproofInherentProvider {
60 client,
61 slot_duration,
62 sproof_builder: None,
63 _phantom: PhantomData,
64 }
65 }
66
67 pub fn update_sproof_builder(&mut self, sproof: RelayStateSproofBuilder) {
69 self.sproof_builder = Some(sproof);
70 }
71
72 pub fn create_inherent(
75 &mut self,
76 slot: u64,
77 parent: <T::Block as Block>::Hash,
78 ) -> Result<ParachainInherentData, anyhow::Error> {
79 let mut sproof = self.sproof_builder.take().unwrap_or_default();
80 sproof.para_id = with_state::<T, _>(self.client.clone(), None, || {
81 staging_parachain_info::Pallet::<T::Runtime>::parachain_id()
82 });
83 sproof.current_slot = if self.slot_duration == 12_000 {
84 ((slot * 2) + 1).into()
86 } else {
87 slot.into()
89 };
90 sproof.host_config.validation_upgrade_delay = 2;
91 sproof.host_config.max_code_size = 15 * 1024 * 1024;
92 sproof.included_para_head =
93 self.client.header(parent).ok().flatten().map(|h| Into::into(h.encode()));
94 sproof.randomness = rand::random();
97
98 let info = self.client.info();
99 let header = self
100 .client
101 .header(info.best_hash)?
102 .ok_or_else(|| anyhow!("Couldn't fetch best header!"))?
103 .encode();
104
105 let (state_root, proof) = sproof.into_state_root_and_proof();
106
107 Ok(ParachainInherentData {
108 validation_data: PersistedValidationData {
109 parent_head: header.into(),
110 relay_parent_number: info.best_number.as_() + 100,
111 relay_parent_storage_root: state_root,
112 max_pov_size: 15 * 1024 * 1024,
113 },
114 relay_chain_state: proof,
115 downward_messages: Default::default(),
116 horizontal_messages: Default::default(),
117 collator_peer_id: None,
118 relay_parent_descendants: vec![],
119 })
120 }
121}