// Copyright (C) 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 . use crate::{ChainId, HeaderIdProvider}; use codec::{Codec, Decode, Encode, MaxEncodedLen}; use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ traits::{ AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify, }, FixedPointOperand, }; use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec}; /// Chain call, that is either SCALE-encoded, or decoded. #[derive(Debug, Clone, PartialEq)] pub enum EncodedOrDecodedCall { /// The call that is SCALE-encoded. /// /// This variant is used when we the chain runtime is not bundled with the relay, but /// we still need the represent call in some RPC calls or transactions. Encoded(Vec), /// The decoded call. Decoded(ChainCall), } impl EncodedOrDecodedCall { /// Returns decoded call. pub fn to_decoded(&self) -> Result { match self { Self::Encoded(ref encoded_call) => ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), Self::Decoded(ref decoded_call) => Ok(decoded_call.clone()), } } /// Converts self to decoded call. pub fn into_decoded(self) -> Result { match self { Self::Encoded(encoded_call) => ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), Self::Decoded(decoded_call) => Ok(decoded_call), } } /// Converts self to encoded call. pub fn into_encoded(self) -> Vec { match self { Self::Encoded(encoded_call) => encoded_call, Self::Decoded(decoded_call) => decoded_call.encode(), } } } impl From for EncodedOrDecodedCall { fn from(call: ChainCall) -> EncodedOrDecodedCall { EncodedOrDecodedCall::Decoded(call) } } impl Decode for EncodedOrDecodedCall { fn decode(input: &mut I) -> Result { // having encoded version is better than decoded, because decoding isn't required // everywhere and for mocked calls it may lead to **unneeded** errors match input.remaining_len()? { Some(remaining_len) => { let mut encoded_call = vec![0u8; remaining_len]; input.read(&mut encoded_call)?; Ok(EncodedOrDecodedCall::Encoded(encoded_call)) }, None => Ok(EncodedOrDecodedCall::Decoded(ChainCall::decode(input)?)), } } } impl Encode for EncodedOrDecodedCall { fn encode(&self) -> Vec { match *self { Self::Encoded(ref encoded_call) => encoded_call.clone(), Self::Decoded(ref decoded_call) => decoded_call.encode(), } } } /// Minimal Substrate-based chain representation that may be used from no_std environment. pub trait Chain: Send + Sync + 'static { /// Chain id. const ID: ChainId; /// A type that fulfills the abstract idea of what a Substrate block number is. // Constraints come from the associated Number type of `sp_runtime::traits::Header` // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Number // // Note that the `AsPrimitive` trait is required by the GRANDPA justification // verifier, and is not usually part of a Substrate Header's Number type. type BlockNumber: Parameter + Member + MaybeSerializeDeserialize + Hash + Copy + Default + MaybeDisplay + AtLeast32BitUnsigned + FromStr + AsPrimitive + Default + Saturating + MaxEncodedLen; /// A type that fulfills the abstract idea of what a Substrate hash is. // Constraints come from the associated Hash type of `sp_runtime::traits::Header` // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hash type Hash: Parameter + Member + MaybeSerializeDeserialize + Hash + Ord + Copy + MaybeDisplay + Default + SimpleBitOps + AsRef<[u8]> + AsMut<[u8]> + MaxEncodedLen; /// A type that fulfills the abstract idea of what a Substrate hasher (a type /// that produces hashes) is. // Constraints come from the associated Hashing type of `sp_runtime::traits::Header` // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hashing type Hasher: HashT; /// A type that fulfills the abstract idea of what a Substrate header is. // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html type Header: Parameter + HeaderT + HeaderIdProvider + MaybeSerializeDeserialize; /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + MaxEncodedLen; /// Balance of an account in native tokens. /// /// The chain may support multiple tokens, but this particular type is for token that is used /// to pay for transaction dispatch, to reward different relayers (headers, messages), etc. type Balance: AtLeast32BitUnsigned + FixedPointOperand + Parameter + Member + MaybeSerializeDeserialize + Clone + Copy + Bounded + CheckedSub + PartialOrd + SaturatingAdd + Zero + TryFrom + MaxEncodedLen; /// Nonce of a transaction used by the chain. type Nonce: Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + MaybeSerializeDeserialize + AtLeast32Bit + Copy + MaxEncodedLen; /// Signature type, used on this chain. type Signature: Parameter + Verify; /// Get the maximum size (in bytes) of a Normal extrinsic at this chain. fn max_extrinsic_size() -> u32; /// Get the maximum weight (compute time) that a Normal extrinsic at this chain can use. fn max_extrinsic_weight() -> Weight; } /// A trait that provides the type of the underlying chain. pub trait UnderlyingChainProvider: Send + Sync + 'static { /// Underlying chain type. type Chain: Chain; } impl Chain for T where T: Send + Sync + 'static + UnderlyingChainProvider, { const ID: ChainId = ::ID; type BlockNumber = ::BlockNumber; type Hash = ::Hash; type Hasher = ::Hasher; type Header = ::Header; type AccountId = ::AccountId; type Balance = ::Balance; type Nonce = ::Nonce; type Signature = ::Signature; fn max_extrinsic_size() -> u32 { ::max_extrinsic_size() } fn max_extrinsic_weight() -> Weight { ::max_extrinsic_weight() } } /// Minimal parachain representation that may be used from no_std environment. pub trait Parachain: Chain { /// Parachain identifier. const PARACHAIN_ID: u32; /// Maximal size of the parachain header. /// /// This isn't a strict limit. The relayer may submit larger headers and the /// pallet will accept the call. The limit is only used to compute whether /// the refund can be made. const MAX_HEADER_SIZE: u32; } impl Parachain for T where T: Chain + UnderlyingChainProvider, ::Chain: Parachain, { const PARACHAIN_ID: u32 = <::Chain as Parachain>::PARACHAIN_ID; const MAX_HEADER_SIZE: u32 = <::Chain as Parachain>::MAX_HEADER_SIZE; } /// Adapter for `Get` to access `PARACHAIN_ID` from `trait Parachain` pub struct ParachainIdOf(sp_std::marker::PhantomData); impl frame_support::traits::Get for ParachainIdOf { fn get() -> u32 { Para::PARACHAIN_ID } } /// Underlying chain type. pub type UnderlyingChainOf = ::Chain; /// Block number used by the chain. pub type BlockNumberOf = ::BlockNumber; /// Hash type used by the chain. pub type HashOf = ::Hash; /// Hasher type used by the chain. pub type HasherOf = ::Hasher; /// Header type used by the chain. pub type HeaderOf = ::Header; /// Account id type used by the chain. pub type AccountIdOf = ::AccountId; /// Balance type used by the chain. pub type BalanceOf = ::Balance; /// Transaction nonce type used by the chain. pub type NonceOf = ::Nonce; /// Signature type used by the chain. pub type SignatureOf = ::Signature; /// Account public type used by the chain. pub type AccountPublicOf = as Verify>::Signer; /// Transaction era used by the chain. pub type TransactionEraOf = crate::TransactionEra, HashOf>; /// Convenience macro that declares bridge finality runtime apis and related constants for a chain. /// This includes: /// - chain-specific bridge runtime APIs: /// - `FinalityApi` /// - constants that are stringified names of runtime API methods: /// - `BEST_FINALIZED__HEADER_METHOD` /// - `_ACCEPTED__FINALITY_PROOFS_METHOD` /// The name of the chain has to be specified in snake case (e.g. `bridge_hub_polkadot`). #[macro_export] macro_rules! decl_bridge_finality_runtime_apis { ($chain: ident $(, $consensus: ident => $justification_type: ty)?) => { bp_runtime::paste::item! { mod [<$chain _finality_api>] { use super::*; /// Name of the `FinalityApi::best_finalized` runtime method. pub const []: &str = stringify!([<$chain:camel FinalityApi_best_finalized>]); /// Name of the `FinalityApi::free_headers_interval` runtime method. pub const []: &str = stringify!([<$chain:camel FinalityApi_free_headers_interval>]); $( /// Name of the `FinalityApi::accepted__finality_proofs` /// runtime method. pub const [<$chain:upper _SYNCED_HEADERS_ $consensus:upper _INFO_METHOD>]: &str = stringify!([<$chain:camel FinalityApi_synced_headers_ $consensus:lower _info>]); )? sp_api::decl_runtime_apis! { /// API for querying information about the finalized chain headers. /// /// This API is implemented by runtimes that are receiving messages from this chain, not by this /// chain's runtime itself. pub trait [<$chain:camel FinalityApi>] { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> Option>; /// Returns free headers interval, if it is configured in the runtime. /// The caller expects that if his transaction improves best known header /// at least by the free_headers_interval`, it will be fee-free. /// /// See [`pallet_bridge_grandpa::Config::FreeHeadersInterval`] for details. fn free_headers_interval() -> Option; $( /// Returns the justifications accepted in the current block. fn []( ) -> sp_std::vec::Vec<$justification_type>; )? } } } pub use [<$chain _finality_api>]::*; } }; ($chain: ident, grandpa) => { decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::StoredHeaderGrandpaInfo
); }; } /// Convenience macro that declares bridge messages runtime apis and related constants for a chain. /// This includes: /// - chain-specific bridge runtime APIs: /// - `ToOutboundLaneApi` /// - `FromInboundLaneApi` /// - constants that are stringified names of runtime API methods: /// - `FROM__MESSAGE_DETAILS_METHOD`, /// The name of the chain has to be specified in snake case (e.g. `bridge_hub_polkadot`). #[macro_export] macro_rules! decl_bridge_messages_runtime_apis { ($chain: ident) => { bp_runtime::paste::item! { mod [<$chain _messages_api>] { use super::*; /// Name of the `ToOutboundLaneApi::message_details` runtime method. pub const []: &str = stringify!([]); /// Name of the `FromInboundLaneApi::message_details` runtime method. pub const []: &str = stringify!([]); sp_api::decl_runtime_apis! { /// Outbound message lane API for messages that are sent to this chain. /// /// This API is implemented by runtimes that are receiving messages from this chain, not by this /// chain's runtime itself. pub trait [] { /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. fn message_details( lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, ) -> sp_std::vec::Vec; } /// Inbound message lane API for messages sent by this chain. /// /// This API is implemented by runtimes that are receiving messages from this chain, not by this /// chain's runtime itself. /// /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. pub trait [] { /// Return details of given inbound messages. fn message_details( lane: bp_messages::LaneId, messages: sp_std::vec::Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, ) -> sp_std::vec::Vec; } } } pub use [<$chain _messages_api>]::*; } }; } /// Convenience macro that declares bridge finality runtime apis, bridge messages runtime apis /// and related constants for a chain. /// The name of the chain has to be specified in snake case (e.g. `bridge_hub_polkadot`). #[macro_export] macro_rules! decl_bridge_runtime_apis { ($chain: ident $(, $consensus: ident)?) => { bp_runtime::decl_bridge_finality_runtime_apis!($chain $(, $consensus)?); bp_runtime::decl_bridge_messages_runtime_apis!($chain); }; }