try_runtime_core/common/empty_block/inherents/custom_idps/
para_parachain.rs1use std::{ops::DerefMut, sync::Arc};
22
23use parity_scale_codec::{Decode, Encode};
24use polkadot_primitives::{BlockNumber, HeadData};
25use sp_consensus_babe::SlotDuration;
26use sp_core::twox_128;
27use sp_inherents::InherentIdentifier;
28use sp_runtime::traits::{Block as BlockT, HashingFor, NumberFor};
29use sp_state_machine::TestExternalities;
30use tokio::sync::Mutex;
31
32pub fn get_para_id<B: BlockT>(ext: &mut TestExternalities<HashingFor<B>>) -> Option<u32> {
34 let para_id_key = [twox_128(b"ParachainInfo"), twox_128(b"ParachainId")].concat();
35
36 ext.execute_with(|| sp_io::storage::get(¶_id_key))
37 .and_then(|b| -> Option<u32> { Decode::decode(&mut &b[..]).ok() })
38}
39
40pub fn get_last_relay_chain_block_number<B: BlockT>(
42 ext: &mut TestExternalities<HashingFor<B>>,
43) -> Option<BlockNumber> {
44 let last_relay_chain_block_number_key = [
45 twox_128(b"ParachainSystem"),
46 twox_128(b"LastRelayChainBlockNumber"),
47 ]
48 .concat();
49
50 ext.execute_with(|| sp_io::storage::get(&last_relay_chain_block_number_key))
51 .and_then(|b| -> Option<NumberFor<B>> { Decode::decode(&mut &b[..]).ok() })
52 .map(|n| match n.try_into() {
53 Ok(block_number) => block_number,
54 Err(_) => {
55 panic!("Failed to convert relay chain block number")
56 }
57 })
58}
59
60pub struct InherentDataProvider<B: BlockT> {
62 pub timestamp: sp_timestamp::Timestamp,
63 pub blocktime_millis: u64,
64 pub parent_header: B::Header,
65 pub ext_mutex: Arc<Mutex<TestExternalities<HashingFor<B>>>>,
66}
67
68#[async_trait::async_trait]
69impl<B: BlockT> sp_inherents::InherentDataProvider for InherentDataProvider<B> {
70 async fn provide_inherent_data(
71 &self,
72 inherent_data: &mut sp_inherents::InherentData,
73 ) -> Result<(), sp_inherents::Error> {
74 let mut ext_guard = self.ext_mutex.lock().await;
75 let ext = ext_guard.deref_mut();
76 let maybe_last_relay_chain_block_number = get_last_relay_chain_block_number::<B>(ext);
77 let maybe_para_id = get_para_id::<B>(ext);
78 let (last_relay_chain_block_number, para_id) =
79 match (maybe_last_relay_chain_block_number, maybe_para_id) {
80 (Some(last_relay_chain_block_number), Some(para_id)) => {
81 (last_relay_chain_block_number, para_id)
82 }
83 _ => {
84 log::debug!("Unable to provide para parachains inherent for this chain.");
85 return Ok(());
86 }
87 };
88
89 let relay_chain_slot = cumulus_primitives_core::relay_chain::Slot::from_timestamp(
90 self.timestamp,
91 SlotDuration::from_millis(self.blocktime_millis),
92 )
93 .encode();
94
95 let additional_key_values: Vec<(Vec<u8>, Vec<u8>)> = vec![
96 (
99 cumulus_primitives_core::relay_chain::well_known_keys::CURRENT_SLOT.to_vec(),
100 relay_chain_slot,
101 ),
102 (
105 cumulus_primitives_core::relay_chain::well_known_keys::para_head(para_id.into()),
106 HeadData(self.parent_header.encode()).encode(),
107 ),
108 ];
109
110 cumulus_client_parachain_inherent::MockValidationDataInherentDataProvider {
111 current_para_block: Default::default(),
112 current_para_block_head: Default::default(),
113 relay_offset: last_relay_chain_block_number + 1u32,
114 relay_blocks_per_para_block: Default::default(),
115 para_blocks_per_relay_epoch: Default::default(),
116 relay_randomness_config: (),
117 xcm_config: cumulus_client_parachain_inherent::MockXcmConfig::default(),
118 raw_downward_messages: Default::default(),
119 raw_horizontal_messages: Default::default(),
120 additional_key_values: Some(additional_key_values),
121 para_id: para_id.into(),
122 }
123 .provide_inherent_data(inherent_data)
124 .await
125 .expect("Failed to provide Para Parachain inherent data.");
126
127 Ok(())
128 }
129
130 async fn try_handle_error(
131 &self,
132 _: &InherentIdentifier,
133 _: &[u8],
134 ) -> Option<Result<(), sp_inherents::Error>> {
135 None
136 }
137}