pezbp_runtime/
chain.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
17use crate::{ChainId, HeaderIdProvider};
18
19use codec::{Codec, Decode, Encode, MaxEncodedLen};
20use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero};
21use pezframe_support::{weights::Weight, Parameter};
22use pezsp_runtime::{
23	traits::{
24		AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay,
25		MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify,
26	},
27	FixedPointOperand, StateVersion,
28};
29use pezsp_std::{fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec};
30
31/// Chain call, that is either SCALE-encoded, or decoded.
32#[derive(Debug, Clone, PartialEq)]
33pub enum EncodedOrDecodedCall<ChainCall> {
34	/// The call that is SCALE-encoded.
35	///
36	/// This variant is used when we the chain runtime is not bundled with the relay, but
37	/// we still need the represent call in some RPC calls or transactions.
38	Encoded(Vec<u8>),
39	/// The decoded call.
40	Decoded(ChainCall),
41}
42
43impl<ChainCall: Clone + Codec> EncodedOrDecodedCall<ChainCall> {
44	/// Returns decoded call.
45	pub fn to_decoded(&self) -> Result<ChainCall, codec::Error> {
46		match self {
47			Self::Encoded(ref encoded_call) => {
48				ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into)
49			},
50			Self::Decoded(ref decoded_call) => Ok(decoded_call.clone()),
51		}
52	}
53
54	/// Converts self to decoded call.
55	pub fn into_decoded(self) -> Result<ChainCall, codec::Error> {
56		match self {
57			Self::Encoded(encoded_call) => {
58				ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into)
59			},
60			Self::Decoded(decoded_call) => Ok(decoded_call),
61		}
62	}
63
64	/// Converts self to encoded call.
65	pub fn into_encoded(self) -> Vec<u8> {
66		match self {
67			Self::Encoded(encoded_call) => encoded_call,
68			Self::Decoded(decoded_call) => decoded_call.encode(),
69		}
70	}
71}
72
73impl<ChainCall> From<ChainCall> for EncodedOrDecodedCall<ChainCall> {
74	fn from(call: ChainCall) -> EncodedOrDecodedCall<ChainCall> {
75		EncodedOrDecodedCall::Decoded(call)
76	}
77}
78
79impl<ChainCall: Decode> Decode for EncodedOrDecodedCall<ChainCall> {
80	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
81		// having encoded version is better than decoded, because decoding isn't required
82		// everywhere and for mocked calls it may lead to **unneeded** errors
83		match input.remaining_len()? {
84			Some(remaining_len) => {
85				let mut encoded_call = vec![0u8; remaining_len];
86				input.read(&mut encoded_call)?;
87				Ok(EncodedOrDecodedCall::Encoded(encoded_call))
88			},
89			None => Ok(EncodedOrDecodedCall::Decoded(ChainCall::decode(input)?)),
90		}
91	}
92}
93
94impl<ChainCall: Encode> Encode for EncodedOrDecodedCall<ChainCall> {
95	fn encode(&self) -> Vec<u8> {
96		match *self {
97			Self::Encoded(ref encoded_call) => encoded_call.clone(),
98			Self::Decoded(ref decoded_call) => decoded_call.encode(),
99		}
100	}
101}
102
103/// Minimal Bizinikiwi-based chain representation that may be used from no_std environment.
104pub trait Chain: Send + Sync + 'static {
105	/// Chain id.
106	const ID: ChainId;
107
108	/// A type that fulfills the abstract idea of what a Bizinikiwi block number is.
109	// Constraints come from the associated Number type of `pezsp_runtime::traits::Header`
110	// See here for more info:
111	// https://docs.rs/sp-runtime/latest/sp_runtime/traits/trait.Header.html#associatedtype.Number
112	//
113	// Note that the `AsPrimitive<usize>` trait is required by the GRANDPA justification
114	// verifier, and is not usually part of a Bizinikiwi Header's Number type.
115	type BlockNumber: Parameter
116		+ Member
117		+ MaybeSerializeDeserialize
118		+ Hash
119		+ Copy
120		+ Default
121		+ MaybeDisplay
122		+ AtLeast32BitUnsigned
123		+ FromStr
124		+ AsPrimitive<usize>
125		+ Default
126		+ Saturating
127		+ MaxEncodedLen;
128
129	/// A type that fulfills the abstract idea of what a Bizinikiwi hash is.
130	// Constraints come from the associated Hash type of `pezsp_runtime::traits::Header`
131	// See here for more info:
132	// https://docs.rs/sp-runtime/latest/sp_runtime/traits/trait.Header.html#associatedtype.Hash
133	type Hash: Parameter
134		+ Member
135		+ MaybeSerializeDeserialize
136		+ Hash
137		+ Ord
138		+ Copy
139		+ MaybeDisplay
140		+ Default
141		+ SimpleBitOps
142		+ AsRef<[u8]>
143		+ AsMut<[u8]>
144		+ MaxEncodedLen;
145
146	/// A type that fulfills the abstract idea of what a Bizinikiwi hasher (a type
147	/// that produces hashes) is.
148	// Constraints come from the associated Hashing type of `pezsp_runtime::traits::Header`
149	// See here for more info:
150	// https://docs.rs/sp-runtime/latest/sp_runtime/traits/trait.Header.html#associatedtype.Hashing
151	type Hasher: HashT<Output = Self::Hash>;
152
153	/// A type that fulfills the abstract idea of what a Bizinikiwi header is.
154	// See here for more info:
155	// https://docs.rs/sp-runtime/latest/sp_runtime/traits/trait.Header.html
156	type Header: Parameter
157		+ HeaderT<Number = Self::BlockNumber, Hash = Self::Hash>
158		+ HeaderIdProvider<Self::Header>
159		+ MaybeSerializeDeserialize;
160
161	/// The user account identifier type for the runtime.
162	type AccountId: Parameter
163		+ Member
164		+ MaybeSerializeDeserialize
165		+ Debug
166		+ MaybeDisplay
167		+ Ord
168		+ MaxEncodedLen;
169	/// Balance of an account in native tokens.
170	///
171	/// The chain may support multiple tokens, but this particular type is for token that is used
172	/// to pay for transaction dispatch, to reward different relayers (headers, messages), etc.
173	type Balance: AtLeast32BitUnsigned
174		+ FixedPointOperand
175		+ Parameter
176		+ Member
177		+ MaybeSerializeDeserialize
178		+ Clone
179		+ Copy
180		+ Bounded
181		+ CheckedSub
182		+ PartialOrd
183		+ SaturatingAdd
184		+ Zero
185		+ TryFrom<pezsp_core::U256>
186		+ MaxEncodedLen;
187	/// Nonce of a transaction used by the chain.
188	type Nonce: Parameter
189		+ Member
190		+ MaybeSerialize
191		+ Debug
192		+ Default
193		+ MaybeDisplay
194		+ MaybeSerializeDeserialize
195		+ AtLeast32Bit
196		+ Copy
197		+ MaxEncodedLen;
198	/// Signature type, used on this chain.
199	type Signature: Parameter + Verify;
200
201	/// Version of the state implementation used by this chain. This is directly related with the
202	/// `TrieLayout` configuration used by the storage.
203	const STATE_VERSION: StateVersion;
204
205	/// Get the maximum size (in bytes) of a Normal extrinsic at this chain.
206	fn max_extrinsic_size() -> u32;
207	/// Get the maximum weight (compute time) that a Normal extrinsic at this chain can use.
208	fn max_extrinsic_weight() -> Weight;
209}
210
211/// A trait that provides the type of the underlying chain.
212pub trait UnderlyingChainProvider: Send + Sync + 'static {
213	/// Underlying chain type.
214	type Chain: Chain;
215}
216
217impl<T> Chain for T
218where
219	T: Send + Sync + 'static + UnderlyingChainProvider,
220{
221	const ID: ChainId = <T::Chain as Chain>::ID;
222
223	type BlockNumber = <T::Chain as Chain>::BlockNumber;
224	type Hash = <T::Chain as Chain>::Hash;
225	type Hasher = <T::Chain as Chain>::Hasher;
226	type Header = <T::Chain as Chain>::Header;
227	type AccountId = <T::Chain as Chain>::AccountId;
228	type Balance = <T::Chain as Chain>::Balance;
229	type Nonce = <T::Chain as Chain>::Nonce;
230	type Signature = <T::Chain as Chain>::Signature;
231
232	const STATE_VERSION: StateVersion = <T::Chain as Chain>::STATE_VERSION;
233
234	fn max_extrinsic_size() -> u32 {
235		<T::Chain as Chain>::max_extrinsic_size()
236	}
237
238	fn max_extrinsic_weight() -> Weight {
239		<T::Chain as Chain>::max_extrinsic_weight()
240	}
241}
242
243/// Minimal teyrchain representation that may be used from no_std environment.
244pub trait Teyrchain: Chain {
245	/// Teyrchain identifier.
246	const TEYRCHAIN_ID: u32;
247	/// Maximal size of the teyrchain header.
248	///
249	/// This isn't a strict limit. The relayer may submit larger headers and the
250	/// pezpallet will accept the call. The limit is only used to compute whether
251	/// the refund can be made.
252	const MAX_HEADER_SIZE: u32;
253}
254
255impl<T> Teyrchain for T
256where
257	T: Chain + UnderlyingChainProvider,
258	<T as UnderlyingChainProvider>::Chain: Teyrchain,
259{
260	const TEYRCHAIN_ID: u32 = <<T as UnderlyingChainProvider>::Chain as Teyrchain>::TEYRCHAIN_ID;
261	const MAX_HEADER_SIZE: u32 =
262		<<T as UnderlyingChainProvider>::Chain as Teyrchain>::MAX_HEADER_SIZE;
263}
264
265/// Adapter for `Get<u32>` to access `TEYRCHAIN_ID` from `trait Teyrchain`
266pub struct TeyrchainIdOf<Para>(pezsp_std::marker::PhantomData<Para>);
267impl<Para: Teyrchain> pezframe_support::traits::Get<u32> for TeyrchainIdOf<Para> {
268	fn get() -> u32 {
269		Para::TEYRCHAIN_ID
270	}
271}
272
273/// Underlying chain type.
274pub type UnderlyingChainOf<C> = <C as UnderlyingChainProvider>::Chain;
275
276/// Block number used by the chain.
277pub type BlockNumberOf<C> = <C as Chain>::BlockNumber;
278
279/// Hash type used by the chain.
280pub type HashOf<C> = <C as Chain>::Hash;
281
282/// Hasher type used by the chain.
283pub type HasherOf<C> = <C as Chain>::Hasher;
284
285/// Header type used by the chain.
286pub type HeaderOf<C> = <C as Chain>::Header;
287
288/// Account id type used by the chain.
289pub type AccountIdOf<C> = <C as Chain>::AccountId;
290
291/// Balance type used by the chain.
292pub type BalanceOf<C> = <C as Chain>::Balance;
293
294/// Transaction nonce type used by the chain.
295pub type NonceOf<C> = <C as Chain>::Nonce;
296
297/// Signature type used by the chain.
298pub type SignatureOf<C> = <C as Chain>::Signature;
299
300/// Account public type used by the chain.
301pub type AccountPublicOf<C> = <SignatureOf<C> as Verify>::Signer;
302
303/// Transaction era used by the chain.
304pub type TransactionEraOf<C> = crate::TransactionEra<BlockNumberOf<C>, HashOf<C>>;
305
306/// Convenience macro that declares bridge finality runtime apis and related constants for a chain.
307/// This includes:
308/// - chain-specific bridge runtime APIs:
309///     - `<ThisChain>FinalityApi`
310/// - constants that are stringified names of runtime API methods:
311///     - `BEST_FINALIZED_<THIS_CHAIN>_HEADER_METHOD`
312///     - `<THIS_CHAIN>_ACCEPTED_<CONSENSUS>_FINALITY_PROOFS_METHOD`
313/// The name of the chain has to be specified in snake case (e.g. `bridge_hub_pezkuwi`).
314#[macro_export]
315macro_rules! decl_bridge_finality_runtime_apis {
316	($chain: ident $(, $consensus: ident => $justification_type: ty)?) => {
317		pezbp_runtime::paste::item! {
318			mod [<$chain _finality_api>] {
319				use super::*;
320
321				/// Name of the `<ThisChain>FinalityApi::best_finalized` runtime method.
322				pub const [<BEST_FINALIZED_ $chain:upper _HEADER_METHOD>]: &str =
323					stringify!([<$chain:camel FinalityApi_best_finalized>]);
324
325				/// Name of the `<ThisChain>FinalityApi::free_headers_interval` runtime method.
326				pub const [<FREE_HEADERS_INTERVAL_FOR_ $chain:upper _METHOD>]: &str =
327					stringify!([<$chain:camel FinalityApi_free_headers_interval>]);
328
329
330				$(
331					/// Name of the `<ThisChain>FinalityApi::accepted_<consensus>_finality_proofs`
332					/// runtime method.
333					pub const [<$chain:upper _SYNCED_HEADERS_ $consensus:upper _INFO_METHOD>]: &str =
334						stringify!([<$chain:camel FinalityApi_synced_headers_ $consensus:lower _info>]);
335				)?
336
337				pezsp_api::decl_runtime_apis! {
338					/// API for querying information about the finalized chain headers.
339					///
340					/// This API is implemented by runtimes that are receiving messages from this chain, not by this
341					/// chain's runtime itself.
342					pub trait [<$chain:camel FinalityApi>] {
343						/// Returns number and hash of the best finalized header known to the bridge module.
344						fn best_finalized() -> Option<pezbp_runtime::HeaderId<Hash, BlockNumber>>;
345
346						/// Returns free headers interval, if it is configured in the runtime.
347						/// The caller expects that if his transaction improves best known header
348						/// at least by the free_headers_interval`, it will be fee-free.
349						///
350						/// See [`pezpallet_bridge_grandpa::Config::FreeHeadersInterval`] for details.
351						fn free_headers_interval() -> Option<BlockNumber>;
352
353						$(
354							/// Returns the justifications accepted in the current block.
355							fn [<synced_headers_ $consensus:lower _info>](
356							) -> $crate::private::Vec<$justification_type>;
357						)?
358					}
359				}
360			}
361
362			pub use [<$chain _finality_api>]::*;
363		}
364	};
365	($chain: ident, grandpa) => {
366		decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_pez_chain::StoredHeaderGrandpaInfo<Header>);
367	};
368}
369
370// Re-export to avoid include tuplex dependency everywhere.
371#[doc(hidden)]
372pub mod __private {
373	pub use codec;
374}
375
376/// Convenience macro that declares bridge messages runtime apis and related constants for a chain.
377/// This includes:
378/// - chain-specific bridge runtime APIs:
379///     - `To<ThisChain>OutboundLaneApi<LaneIdType>`
380///     - `From<ThisChain>InboundLaneApi<LaneIdType>`
381/// - constants that are stringified names of runtime API methods:
382///     - `FROM_<THIS_CHAIN>_MESSAGE_DETAILS_METHOD`,
383/// The name of the chain has to be specified in snake case (e.g. `bridge_hub_pezkuwi`).
384#[macro_export]
385macro_rules! decl_bridge_messages_runtime_apis {
386	($chain: ident, $lane_id_type:ty) => {
387		pezbp_runtime::paste::item! {
388			mod [<$chain _messages_api>] {
389				use super::*;
390
391				/// Name of the `To<ThisChain>OutboundLaneApi::message_details` runtime method.
392				pub const [<TO_ $chain:upper _MESSAGE_DETAILS_METHOD>]: &str =
393					stringify!([<To $chain:camel OutboundLaneApi_message_details>]);
394
395				/// Name of the `From<ThisChain>InboundLaneApi::message_details` runtime method.
396				pub const [<FROM_ $chain:upper _MESSAGE_DETAILS_METHOD>]: &str =
397					stringify!([<From $chain:camel InboundLaneApi_message_details>]);
398
399				pezsp_api::decl_runtime_apis! {
400					/// Outbound message lane API for messages that are sent to this chain.
401					///
402					/// This API is implemented by runtimes that are receiving messages from this chain, not by this
403					/// chain's runtime itself.
404					pub trait [<To $chain:camel OutboundLaneApi>] {
405						/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
406						/// messages in given inclusive range.
407						///
408						/// If some (or all) messages are missing from the storage, they'll also will
409						/// be missing from the resulting vector. The vector is ordered by the nonce.
410						fn message_details(
411							lane: $lane_id_type,
412							begin: bp_messages::MessageNonce,
413							end: bp_messages::MessageNonce,
414						) -> $crate::private::Vec<bp_messages::OutboundMessageDetails>;
415					}
416
417					/// Inbound message lane API for messages sent by this chain.
418					///
419					/// This API is implemented by runtimes that are receiving messages from this chain, not by this
420					/// chain's runtime itself.
421					///
422					/// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the
423					/// `messages` vector may (and need to) be read using `To<ThisChain>OutboundLaneApi::message_details`.
424					pub trait [<From $chain:camel InboundLaneApi>] {
425						/// Return details of given inbound messages.
426						fn message_details(
427							lane: $lane_id_type,
428							messages: $crate::private::Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>,
429						) -> $crate::private::Vec<bp_messages::InboundMessageDetails>;
430					}
431				}
432			}
433
434			pub use [<$chain _messages_api>]::*;
435		}
436	};
437}
438
439/// Convenience macro that declares bridge finality runtime apis, bridge messages runtime apis
440/// and related constants for a chain.
441/// The name of the chain has to be specified in snake case (e.g. `bridge_hub_pezkuwi`).
442#[macro_export]
443macro_rules! decl_bridge_runtime_apis {
444	($chain: ident $(, $consensus: ident, $lane_id_type:ident)?) => {
445		pezbp_runtime::decl_bridge_finality_runtime_apis!($chain $(, $consensus)?);
446		pezbp_runtime::decl_bridge_messages_runtime_apis!($chain, $lane_id_type);
447	};
448}