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