pezbp_teyrchains/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Primitives of teyrchains module.
18
19#![warn(missing_docs)]
20#![cfg_attr(not(feature = "std"), no_std)]
21
22pub use pezbp_header_pez_chain::StoredHeaderData;
23pub use call_info::{BridgeTeyrchainCall, SubmitTeyrchainHeadsInfo};
24
25use pezbp_pezkuwi_core::teyrchains::{ParaHash, ParaHead, ParaId};
26use codec::{Decode, Encode, MaxEncodedLen};
27use pezbp_runtime::{
28	BlockNumberOf, Chain, HashOf, HeaderOf, StorageDoubleMapKeyProvider, StorageMapKeyProvider,
29	Teyrchain,
30};
31use pezframe_support::{weights::Weight, Blake2_128Concat, Twox64Concat};
32use pezsp_core::storage::StorageKey;
33use pezsp_runtime::{traits::Header as HeaderT, RuntimeDebug};
34use pezsp_std::{marker::PhantomData, prelude::*};
35use scale_info::TypeInfo;
36
37/// Block hash of the bridged relay chain.
38pub type RelayBlockHash = pezbp_pezkuwi_core::Hash;
39/// Block number of the bridged relay chain.
40pub type RelayBlockNumber = pezbp_pezkuwi_core::BlockNumber;
41/// Hasher of the bridged relay chain.
42pub type RelayBlockHasher = pezbp_pezkuwi_core::Hasher;
43
44mod call_info;
45
46/// Best known teyrchain head hash.
47#[derive(Clone, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
48pub struct BestParaHeadHash {
49	/// Number of relay block where this head has been read.
50	///
51	/// Teyrchain head is opaque to relay chain. So we can't simply decode it as a header of
52	/// teyrchains and call `block_number()` on it. Instead, we're using the fact that teyrchain
53	/// head is always built on top of previous head (because it is blockchain) and relay chain
54	/// always imports teyrchain heads in order. What it means for us is that at any given
55	/// **finalized** relay block `B`, head of teyrchain will be ancestor (or the same) of all
56	/// teyrchain heads available at descendants of `B`.
57	pub at_relay_block_number: RelayBlockNumber,
58	/// Hash of teyrchain head.
59	pub head_hash: ParaHash,
60}
61
62/// Best known teyrchain head as it is stored in the runtime storage.
63#[derive(Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
64pub struct ParaInfo {
65	/// Best known teyrchain head hash.
66	pub best_head_hash: BestParaHeadHash,
67	/// Current ring buffer position for this teyrchain.
68	pub next_imported_hash_position: u32,
69}
70
71/// Returns runtime storage key of given teyrchain head at the source chain.
72///
73/// The head is stored by the `paras` pezpallet in the `Heads` map.
74pub fn teyrchain_head_storage_key_at_source(
75	paras_pallet_name: &str,
76	para_id: ParaId,
77) -> StorageKey {
78	pezbp_runtime::storage_map_final_key::<Twox64Concat>(
79		paras_pallet_name,
80		"Heads",
81		&para_id.encode(),
82	)
83}
84
85/// Can be use to access the runtime storage key of the teyrchains info at the target chain.
86///
87/// The info is stored by the `pezpallet-bridge-teyrchains` pezpallet in the `ParasInfo` map.
88pub struct ParasInfoKeyProvider;
89impl StorageMapKeyProvider for ParasInfoKeyProvider {
90	const MAP_NAME: &'static str = "ParasInfo";
91
92	type Hasher = Blake2_128Concat;
93	type Key = ParaId;
94	type Value = ParaInfo;
95}
96
97/// Can be use to access the runtime storage key of the teyrchain head at the target chain.
98///
99/// The head is stored by the `pezpallet-bridge-teyrchains` pezpallet in the `ImportedParaHeads`
100/// map.
101pub struct ImportedParaHeadsKeyProvider;
102impl StorageDoubleMapKeyProvider for ImportedParaHeadsKeyProvider {
103	const MAP_NAME: &'static str = "ImportedParaHeads";
104
105	type Hasher1 = Blake2_128Concat;
106	type Key1 = ParaId;
107	type Hasher2 = Blake2_128Concat;
108	type Key2 = ParaHash;
109	type Value = ParaStoredHeaderData;
110}
111
112/// Stored data of the teyrchain head. It is encoded version of the
113/// `pezbp_runtime::StoredHeaderData` structure.
114///
115/// We do not know exact structure of the teyrchain head, so we always store encoded version
116/// of the `pezbp_runtime::StoredHeaderData`. It is only decoded when we talk about specific
117/// teyrchain.
118#[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)]
119pub struct ParaStoredHeaderData(pub Vec<u8>);
120
121impl ParaStoredHeaderData {
122	/// Decode stored teyrchain head data.
123	pub fn decode_teyrchain_head_data<C: Chain>(
124		&self,
125	) -> Result<StoredHeaderData<BlockNumberOf<C>, HashOf<C>>, codec::Error> {
126		StoredHeaderData::<BlockNumberOf<C>, HashOf<C>>::decode(&mut &self.0[..])
127	}
128}
129
130/// Stored teyrchain head data builder.
131pub trait ParaStoredHeaderDataBuilder {
132	/// Maximal teyrchain head size that we may accept for free. All heads above
133	/// this limit are submitted for a regular fee.
134	fn max_free_head_size() -> u32;
135
136	/// Return number of teyrchains that are supported by this builder.
137	fn supported_teyrchains() -> u32;
138
139	/// Try to build head data from encoded head of teyrchain with given id.
140	fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData>;
141}
142
143/// Helper for using single teyrchain as `ParaStoredHeaderDataBuilder`.
144pub struct SingleParaStoredHeaderDataBuilder<C: Teyrchain>(PhantomData<C>);
145
146impl<C: Teyrchain> ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBuilder<C> {
147	fn max_free_head_size() -> u32 {
148		C::MAX_HEADER_SIZE
149	}
150
151	fn supported_teyrchains() -> u32 {
152		1
153	}
154
155	fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData> {
156		if para_id == ParaId(C::TEYRCHAIN_ID) {
157			let header = HeaderOf::<C>::decode(&mut &para_head.0[..]).ok()?;
158			return Some(ParaStoredHeaderData(
159				StoredHeaderData { number: *header.number(), state_root: *header.state_root() }
160					.encode(),
161			));
162		}
163		None
164	}
165}
166
167// Tries to build header data from each tuple member, short-circuiting on first successful one.
168#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
169#[tuple_types_custom_trait_bound(Teyrchain)]
170impl ParaStoredHeaderDataBuilder for C {
171	fn max_free_head_size() -> u32 {
172		let mut result = 0_u32;
173		for_tuples!( #(
174			result = pezsp_std::cmp::max(
175				result,
176				SingleParaStoredHeaderDataBuilder::<C>::max_free_head_size(),
177			);
178		)* );
179		result
180	}
181
182	fn supported_teyrchains() -> u32 {
183		let mut result = 0;
184		for_tuples!( #(
185			result += SingleParaStoredHeaderDataBuilder::<C>::supported_teyrchains();
186		)* );
187		result
188	}
189
190	fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData> {
191		for_tuples!( #(
192			let maybe_para_head = SingleParaStoredHeaderDataBuilder::<C>::try_build(para_id, para_head);
193			if let Some(maybe_para_head) = maybe_para_head {
194				return Some(maybe_para_head);
195			}
196		)* );
197
198		None
199	}
200}
201
202/// Runtime hook for when a teyrchain head is updated.
203pub trait OnNewHead {
204	/// Called when a teyrchain head is updated.
205	/// Returns the weight consumed by this function.
206	fn on_new_head(id: ParaId, head: &ParaHead) -> Weight;
207}
208
209#[impl_trait_for_tuples::impl_for_tuples(8)]
210impl OnNewHead for Tuple {
211	fn on_new_head(id: ParaId, head: &ParaHead) -> Weight {
212		let mut weight: Weight = Default::default();
213		for_tuples!( #( weight.saturating_accrue(Tuple::on_new_head(id, head)); )* );
214		weight
215	}
216}