referrerpolicy=no-referrer-when-downgrade

bp_runtime/
chain.rs

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