try_runtime_core/common/empty_block/inherents/custom_idps/
para_parachain.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Inherent data provider for the [cumulus parachin inherents](https://github.com/paritytech/polkadot-sdk/blob/master/cumulus/primitives/parachain-inherent/src/lib.rs)
19//! for empty block production on top of an existing externalities.
20
21use std::{ops::DerefMut, sync::Arc};
22
23use parity_scale_codec::{Decode, Encode};
24use polkadot_primitives::HeadData;
25use sp_consensus_babe::SlotDuration;
26use sp_crypto_hashing::twox_128;
27use sp_inherents::InherentIdentifier;
28use sp_runtime::traits::{Block as BlockT, HashingFor};
29use sp_state_machine::TestExternalities;
30use tokio::sync::Mutex;
31
32/// Get the para id if it exists
33pub 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(&para_id_key))
37        .and_then(|b| -> Option<u32> { Decode::decode(&mut &b[..]).ok() })
38}
39
40/// Provides parachain-system pallet inherents.
41pub struct InherentDataProvider<B: BlockT> {
42    pub timestamp: sp_timestamp::Timestamp,
43    pub blocktime_millis: u64,
44    pub parent_header: B::Header,
45    pub ext_mutex: Arc<Mutex<TestExternalities<HashingFor<B>>>>,
46    pub relay_parent_offset: u32,
47}
48
49#[async_trait::async_trait]
50impl<B: BlockT> sp_inherents::InherentDataProvider for InherentDataProvider<B> {
51    async fn provide_inherent_data(
52        &self,
53        inherent_data: &mut sp_inherents::InherentData,
54    ) -> Result<(), sp_inherents::Error> {
55        let mut ext_guard = self.ext_mutex.lock().await;
56        let ext = ext_guard.deref_mut();
57        let Some(para_id) = get_para_id::<B>(ext) else {
58            log::debug!("Unable to provide para parachains inherent for this chain.");
59            return Ok(());
60        };
61
62        let relay_chain_slot = cumulus_primitives_core::relay_chain::Slot::from_timestamp(
63            self.timestamp,
64            SlotDuration::from_millis(self.blocktime_millis),
65        );
66
67        cumulus_client_parachain_inherent::MockValidationDataInherentDataProvider {
68            relay_offset: *relay_chain_slot as u32,
69            current_para_block_head: Some(HeadData(self.parent_header.encode())),
70            relay_parent_offset: self.relay_parent_offset,
71            relay_randomness_config: (),
72            para_id: para_id.into(),
73            ..Default::default()
74        }
75        .provide_inherent_data(inherent_data)
76        .await
77        .expect("Failed to provide Para Parachain inherent data.");
78
79        Ok(())
80    }
81
82    async fn try_handle_error(
83        &self,
84        _: &InherentIdentifier,
85        _: &[u8],
86    ) -> Option<Result<(), sp_inherents::Error>> {
87        None
88    }
89}