referrerpolicy=no-referrer-when-downgrade

relay_substrate_client/
chain.rs

1// Copyright 2019-2021 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::calls::UtilityCall;
18
19use crate::SimpleRuntimeVersion;
20use bp_header_chain::ChainWithGrandpa as ChainWithGrandpaBase;
21use bp_messages::ChainWithMessages as ChainWithMessagesBase;
22use bp_runtime::{
23	Chain as ChainBase, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, TransactionEra,
24	TransactionEraOf, UnderlyingChainProvider,
25};
26use codec::{Codec, Decode, Encode, MaxEncodedLen};
27use frame_support::Parameter;
28use jsonrpsee::core::{DeserializeOwned, Serialize};
29use num_traits::Zero;
30use sc_transaction_pool_api::TransactionStatus;
31use scale_info::TypeInfo;
32use sp_core::{storage::StorageKey, Pair};
33use sp_runtime::{
34	generic::SignedBlock,
35	traits::{AtLeast32BitUnsigned, Block as BlockT, Member},
36	ConsensusEngineId, EncodedJustification,
37};
38use std::{fmt::Debug, time::Duration};
39
40/// Signed block type of given chain.
41pub type SignedBlockOf<C> = <C as Chain>::SignedBlock;
42
43/// Substrate-based chain from minimal relay-client point of view.
44pub trait Chain: ChainBase + Clone {
45	/// Chain name.
46	const NAME: &'static str;
47	/// Name of the runtime API method that is returning best known finalized header number
48	/// and hash (as tuple).
49	///
50	/// Keep in mind that this method is normally provided by the other chain, which is
51	/// bridged with this chain.
52	const BEST_FINALIZED_HEADER_ID_METHOD: &'static str;
53	/// Name of the runtime API method that is returning interval between source chain
54	/// headers that may be submitted for free to the target chain.
55	///
56	/// Keep in mind that this method is normally provided by the other chain, which is
57	/// bridged with this chain.
58	const FREE_HEADERS_INTERVAL_METHOD: &'static str;
59
60	/// Average block interval.
61	///
62	/// How often blocks are produced on that chain. It's suggested to set this value
63	/// to match the block time of the chain.
64	const AVERAGE_BLOCK_INTERVAL: Duration;
65
66	/// Block type.
67	type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification<Self::Header>;
68	/// The aggregated `Call` type.
69	type Call: Clone + Codec + Debug + Send + Sync;
70}
71
72/// Bridge-supported network definition.
73///
74/// Used to abstract away CLI commands.
75pub trait ChainWithRuntimeVersion: Chain {
76	/// Current version of the chain runtime, known to relay.
77	///
78	/// can be `None` if relay is not going to submit transactions to that chain.
79	const RUNTIME_VERSION: Option<SimpleRuntimeVersion>;
80}
81
82/// Substrate-based relay chain that supports parachains.
83///
84/// We assume that the parachains are supported using `runtime_parachains::paras` pallet.
85pub trait RelayChain: Chain {
86	/// Name of the `runtime_parachains::paras` pallet in the runtime of this chain.
87	const PARAS_PALLET_NAME: &'static str;
88	/// Name of the `pallet-bridge-parachains`, deployed at the **bridged** chain to sync
89	/// parachains of **this** chain.
90	const WITH_CHAIN_BRIDGE_PARACHAINS_PALLET_NAME: &'static str;
91}
92
93/// Substrate-based chain that is using direct GRANDPA finality from minimal relay-client point of
94/// view.
95///
96/// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement
97/// this trait.
98pub trait ChainWithGrandpa: Chain + ChainWithGrandpaBase {
99	/// Name of the runtime API method that is returning the GRANDPA info associated with the
100	/// headers accepted by the `submit_finality_proofs` extrinsic in the queried block.
101	///
102	/// Keep in mind that this method is normally provided by the other chain, which is
103	/// bridged with this chain.
104	const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str;
105
106	/// The type of the key owner proof used by the grandpa engine.
107	type KeyOwnerProof: Decode + TypeInfo + Send;
108}
109
110/// Substrate-based parachain from minimal relay-client point of view.
111pub trait Parachain: Chain + ParachainBase {}
112
113impl<T> Parachain for T where T: UnderlyingChainProvider + Chain + ParachainBase {}
114
115/// Substrate-based chain with messaging support from minimal relay-client point of view.
116pub trait ChainWithMessages: Chain + ChainWithMessagesBase {
117	/// Name of the `To<ChainWithMessages>OutboundLaneApi::message_details` runtime API method.
118	/// The method is provided by the runtime that is bridged with this `ChainWithMessages`.
119	const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str;
120
121	/// Name of the `From<ChainWithMessages>InboundLaneApi::message_details` runtime API method.
122	/// The method is provided by the runtime that is bridged with this `ChainWithMessages`.
123	const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str;
124}
125
126/// Call type used by the chain.
127pub type CallOf<C> = <C as Chain>::Call;
128/// Transaction status of the chain.
129pub type TransactionStatusOf<C> = TransactionStatus<HashOf<C>, HashOf<C>>;
130
131/// Substrate-based chain with `AccountData` generic argument of `frame_system::AccountInfo` set to
132/// the `pallet_balances::AccountData<Balance>`.
133pub trait ChainWithBalances: Chain {
134	/// Return runtime storage key for getting `frame_system::AccountInfo` of given account.
135	fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey;
136}
137
138/// Substrate-based chain with bridge relayers pallet as a reward ledger.
139pub trait ChainWithRewards: Chain {
140	/// Name of the bridge relayers pallet (used in `construct_runtime` macro call).
141	const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str>;
142	/// Type of relayer reward balance.
143	type RewardBalance: AtLeast32BitUnsigned + Copy + Member + Parameter + MaxEncodedLen;
144	/// Reward discriminator type.
145	type Reward: Parameter + MaxEncodedLen + Send + Sync + Copy + Clone;
146
147	/// Return runtime storage key for getting `reward_kind` of given account.
148	fn account_reward_storage_key(
149		account_id: &Self::AccountId,
150		reward: impl Into<Self::Reward>,
151	) -> StorageKey;
152}
153
154/// SCALE-encoded extrinsic.
155pub type EncodedExtrinsic = Vec<u8>;
156
157/// Block with justification.
158pub trait BlockWithJustification<Header> {
159	/// Return block header.
160	fn header(&self) -> Header;
161	/// Return encoded block extrinsics.
162	fn extrinsics(&self) -> Vec<EncodedExtrinsic>;
163	/// Return block justification, if known.
164	fn justification(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification>;
165}
166
167/// Transaction before it is signed.
168#[derive(Clone, Debug, PartialEq)]
169pub struct UnsignedTransaction<C: Chain> {
170	/// Runtime call of this transaction.
171	pub call: EncodedOrDecodedCall<C::Call>,
172	/// Transaction nonce.
173	pub nonce: C::Nonce,
174	/// Tip included into transaction.
175	pub tip: C::Balance,
176	/// Transaction era used by the chain.
177	pub era: TransactionEraOf<C>,
178}
179
180impl<C: Chain> UnsignedTransaction<C> {
181	/// Create new unsigned transaction with given call, nonce, era and zero tip.
182	pub fn new(call: EncodedOrDecodedCall<C::Call>, nonce: C::Nonce) -> Self {
183		Self { call, nonce, era: TransactionEra::Immortal, tip: Zero::zero() }
184	}
185
186	/// Convert to the transaction of the other compatible chain.
187	pub fn switch_chain<Other>(self) -> UnsignedTransaction<Other>
188	where
189		Other: Chain<
190			Nonce = C::Nonce,
191			Balance = C::Balance,
192			BlockNumber = C::BlockNumber,
193			Hash = C::Hash,
194		>,
195	{
196		UnsignedTransaction {
197			call: EncodedOrDecodedCall::Encoded(self.call.into_encoded()),
198			nonce: self.nonce,
199			tip: self.tip,
200			era: self.era,
201		}
202	}
203
204	/// Set transaction tip.
205	#[must_use]
206	pub fn tip(mut self, tip: C::Balance) -> Self {
207		self.tip = tip;
208		self
209	}
210
211	/// Set transaction era.
212	#[must_use]
213	pub fn era(mut self, era: TransactionEraOf<C>) -> Self {
214		self.era = era;
215		self
216	}
217}
218
219/// Account key pair used by transactions signing scheme.
220pub type AccountKeyPairOf<S> = <S as ChainWithTransactions>::AccountKeyPair;
221
222/// Substrate-based chain transactions signing scheme.
223pub trait ChainWithTransactions: Chain {
224	/// Type of key pairs used to sign transactions.
225	type AccountKeyPair: Pair + Clone + Send + Sync;
226	/// Signed transaction.
227	type SignedTransaction: Clone + Debug + Encode + Send + 'static;
228
229	/// Create transaction for given runtime call, signed by given account.
230	fn sign_transaction(
231		param: SignParam<Self>,
232		unsigned: UnsignedTransaction<Self>,
233	) -> Result<Self::SignedTransaction, crate::Error>
234	where
235		Self: Sized;
236}
237
238/// Sign transaction parameters
239pub struct SignParam<C: ChainWithTransactions> {
240	/// Version of the runtime specification.
241	pub spec_version: u32,
242	/// Transaction version
243	pub transaction_version: u32,
244	/// Hash of the genesis block.
245	pub genesis_hash: HashOf<C>,
246	/// Signer account
247	pub signer: AccountKeyPairOf<C>,
248}
249
250impl<Block: BlockT> BlockWithJustification<Block::Header> for SignedBlock<Block> {
251	fn header(&self) -> Block::Header {
252		self.block.header().clone()
253	}
254
255	fn extrinsics(&self) -> Vec<EncodedExtrinsic> {
256		self.block.extrinsics().iter().map(Encode::encode).collect()
257	}
258
259	fn justification(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification> {
260		self.justifications.as_ref().and_then(|j| j.get(engine_id))
261	}
262}
263
264/// Trait that provides functionality defined inside `pallet-utility`
265pub trait UtilityPallet<C: Chain> {
266	/// Create batch call from given calls vector.
267	fn build_batch_call(calls: Vec<C::Call>) -> C::Call;
268}
269
270/// Structure that implements `UtilityPalletProvider` based on a full runtime.
271pub struct FullRuntimeUtilityPallet<R> {
272	_phantom: std::marker::PhantomData<R>,
273}
274
275impl<C, R> UtilityPallet<C> for FullRuntimeUtilityPallet<R>
276where
277	C: Chain,
278	R: pallet_utility::Config<RuntimeCall = C::Call>,
279	<R as pallet_utility::Config>::RuntimeCall: From<pallet_utility::Call<R>>,
280{
281	fn build_batch_call(calls: Vec<C::Call>) -> C::Call {
282		pallet_utility::Call::batch_all { calls }.into()
283	}
284}
285
286/// Structure that implements `UtilityPalletProvider` based on a call conversion.
287pub struct MockedRuntimeUtilityPallet<Call> {
288	_phantom: std::marker::PhantomData<Call>,
289}
290
291impl<C, Call> UtilityPallet<C> for MockedRuntimeUtilityPallet<Call>
292where
293	C: Chain,
294	C::Call: From<UtilityCall<C::Call>>,
295{
296	fn build_batch_call(calls: Vec<C::Call>) -> C::Call {
297		UtilityCall::batch_all(calls).into()
298	}
299}
300
301/// Substrate-based chain that uses `pallet-utility`.
302pub trait ChainWithUtilityPallet: Chain {
303	/// The utility pallet provider.
304	type UtilityPallet: UtilityPallet<Self>;
305}