1#![warn(missing_docs)]
20#![cfg_attr(not(feature = "std"), no_std)]
21
22pub use bp_header_chain::StoredHeaderData;
23pub use call_info::{BridgeParachainCall, SubmitParachainHeadsInfo};
24
25use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaId};
26use bp_runtime::{
27 BlockNumberOf, Chain, HashOf, HeaderOf, Parachain, StorageDoubleMapKeyProvider,
28 StorageMapKeyProvider,
29};
30use codec::{Decode, Encode, MaxEncodedLen};
31use frame_support::{weights::Weight, Blake2_128Concat, Twox64Concat};
32use scale_info::TypeInfo;
33use sp_core::storage::StorageKey;
34use sp_runtime::{traits::Header as HeaderT, RuntimeDebug};
35use sp_std::{marker::PhantomData, prelude::*};
36
37pub type RelayBlockHash = bp_polkadot_core::Hash;
39pub type RelayBlockNumber = bp_polkadot_core::BlockNumber;
41pub type RelayBlockHasher = bp_polkadot_core::Hasher;
43
44mod call_info;
45
46#[derive(Clone, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
48pub struct BestParaHeadHash {
49 pub at_relay_block_number: RelayBlockNumber,
58 pub head_hash: ParaHash,
60}
61
62#[derive(Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
64pub struct ParaInfo {
65 pub best_head_hash: BestParaHeadHash,
67 pub next_imported_hash_position: u32,
69}
70
71pub fn parachain_head_storage_key_at_source(
75 paras_pallet_name: &str,
76 para_id: ParaId,
77) -> StorageKey {
78 bp_runtime::storage_map_final_key::<Twox64Concat>(paras_pallet_name, "Heads", ¶_id.encode())
79}
80
81pub struct ParasInfoKeyProvider;
85impl StorageMapKeyProvider for ParasInfoKeyProvider {
86 const MAP_NAME: &'static str = "ParasInfo";
87
88 type Hasher = Blake2_128Concat;
89 type Key = ParaId;
90 type Value = ParaInfo;
91}
92
93pub struct ImportedParaHeadsKeyProvider;
97impl StorageDoubleMapKeyProvider for ImportedParaHeadsKeyProvider {
98 const MAP_NAME: &'static str = "ImportedParaHeads";
99
100 type Hasher1 = Blake2_128Concat;
101 type Key1 = ParaId;
102 type Hasher2 = Blake2_128Concat;
103 type Key2 = ParaHash;
104 type Value = ParaStoredHeaderData;
105}
106
107#[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)]
113pub struct ParaStoredHeaderData(pub Vec<u8>);
114
115impl ParaStoredHeaderData {
116 pub fn decode_parachain_head_data<C: Chain>(
118 &self,
119 ) -> Result<StoredHeaderData<BlockNumberOf<C>, HashOf<C>>, codec::Error> {
120 StoredHeaderData::<BlockNumberOf<C>, HashOf<C>>::decode(&mut &self.0[..])
121 }
122}
123
124pub trait ParaStoredHeaderDataBuilder {
126 fn max_free_head_size() -> u32;
129
130 fn supported_parachains() -> u32;
132
133 fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData>;
135}
136
137pub struct SingleParaStoredHeaderDataBuilder<C: Parachain>(PhantomData<C>);
139
140impl<C: Parachain> ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBuilder<C> {
141 fn max_free_head_size() -> u32 {
142 C::MAX_HEADER_SIZE
143 }
144
145 fn supported_parachains() -> u32 {
146 1
147 }
148
149 fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData> {
150 if para_id == ParaId(C::PARACHAIN_ID) {
151 let header = HeaderOf::<C>::decode(&mut ¶_head.0[..]).ok()?;
152 return Some(ParaStoredHeaderData(
153 StoredHeaderData { number: *header.number(), state_root: *header.state_root() }
154 .encode(),
155 ))
156 }
157 None
158 }
159}
160
161#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
163#[tuple_types_custom_trait_bound(Parachain)]
164impl ParaStoredHeaderDataBuilder for C {
165 fn max_free_head_size() -> u32 {
166 let mut result = 0_u32;
167 for_tuples!( #(
168 result = sp_std::cmp::max(
169 result,
170 SingleParaStoredHeaderDataBuilder::<C>::max_free_head_size(),
171 );
172 )* );
173 result
174 }
175
176 fn supported_parachains() -> u32 {
177 let mut result = 0;
178 for_tuples!( #(
179 result += SingleParaStoredHeaderDataBuilder::<C>::supported_parachains();
180 )* );
181 result
182 }
183
184 fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData> {
185 for_tuples!( #(
186 let maybe_para_head = SingleParaStoredHeaderDataBuilder::<C>::try_build(para_id, para_head);
187 if let Some(maybe_para_head) = maybe_para_head {
188 return Some(maybe_para_head);
189 }
190 )* );
191
192 None
193 }
194}
195
196pub trait OnNewHead {
198 fn on_new_head(id: ParaId, head: &ParaHead) -> Weight;
201}
202
203#[impl_trait_for_tuples::impl_for_tuples(8)]
204impl OnNewHead for Tuple {
205 fn on_new_head(id: ParaId, head: &ParaHead) -> Weight {
206 let mut weight: Weight = Default::default();
207 for_tuples!( #( weight.saturating_accrue(Tuple::on_new_head(id, head)); )* );
208 weight
209 }
210}