use crate::{ChainId, HeaderIdProvider};
use codec::{Codec, Decode, Encode, MaxEncodedLen};
use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero};
use pezframe_support::{weights::Weight, Parameter};
use pezsp_runtime::{
traits::{
AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay,
MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify,
},
FixedPointOperand, StateVersion,
};
use pezsp_std::{fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec};
#[derive(Debug, Clone, PartialEq)]
pub enum EncodedOrDecodedCall<ChainCall> {
Encoded(Vec<u8>),
Decoded(ChainCall),
}
impl<ChainCall: Clone + Codec> EncodedOrDecodedCall<ChainCall> {
pub fn to_decoded(&self) -> Result<ChainCall, codec::Error> {
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()),
}
}
pub fn into_decoded(self) -> Result<ChainCall, codec::Error> {
match self {
Self::Encoded(encoded_call) => {
ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into)
},
Self::Decoded(decoded_call) => Ok(decoded_call),
}
}
pub fn into_encoded(self) -> Vec<u8> {
match self {
Self::Encoded(encoded_call) => encoded_call,
Self::Decoded(decoded_call) => decoded_call.encode(),
}
}
}
impl<ChainCall> From<ChainCall> for EncodedOrDecodedCall<ChainCall> {
fn from(call: ChainCall) -> EncodedOrDecodedCall<ChainCall> {
EncodedOrDecodedCall::Decoded(call)
}
}
impl<ChainCall: Decode> Decode for EncodedOrDecodedCall<ChainCall> {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
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<ChainCall: Encode> Encode for EncodedOrDecodedCall<ChainCall> {
fn encode(&self) -> Vec<u8> {
match *self {
Self::Encoded(ref encoded_call) => encoded_call.clone(),
Self::Decoded(ref decoded_call) => decoded_call.encode(),
}
}
}
pub trait Chain: Send + Sync + 'static {
const ID: ChainId;
type BlockNumber: Parameter
+ Member
+ MaybeSerializeDeserialize
+ Hash
+ Copy
+ Default
+ MaybeDisplay
+ AtLeast32BitUnsigned
+ FromStr
+ AsPrimitive<usize>
+ Default
+ Saturating
+ MaxEncodedLen;
type Hash: Parameter
+ Member
+ MaybeSerializeDeserialize
+ Hash
+ Ord
+ Copy
+ MaybeDisplay
+ Default
+ SimpleBitOps
+ AsRef<[u8]>
+ AsMut<[u8]>
+ MaxEncodedLen;
type Hasher: HashT<Output = Self::Hash>;
type Header: Parameter
+ HeaderT<Number = Self::BlockNumber, Hash = Self::Hash>
+ HeaderIdProvider<Self::Header>
+ MaybeSerializeDeserialize;
type AccountId: Parameter
+ Member
+ MaybeSerializeDeserialize
+ Debug
+ MaybeDisplay
+ Ord
+ MaxEncodedLen;
type Balance: AtLeast32BitUnsigned
+ FixedPointOperand
+ Parameter
+ Member
+ MaybeSerializeDeserialize
+ Clone
+ Copy
+ Bounded
+ CheckedSub
+ PartialOrd
+ SaturatingAdd
+ Zero
+ TryFrom<pezsp_core::U256>
+ MaxEncodedLen;
type Nonce: Parameter
+ Member
+ MaybeSerialize
+ Debug
+ Default
+ MaybeDisplay
+ MaybeSerializeDeserialize
+ AtLeast32Bit
+ Copy
+ MaxEncodedLen;
type Signature: Parameter + Verify;
const STATE_VERSION: StateVersion;
fn max_extrinsic_size() -> u32;
fn max_extrinsic_weight() -> Weight;
}
pub trait UnderlyingChainProvider: Send + Sync + 'static {
type Chain: Chain;
}
impl<T> Chain for T
where
T: Send + Sync + 'static + UnderlyingChainProvider,
{
const ID: ChainId = <T::Chain as Chain>::ID;
type BlockNumber = <T::Chain as Chain>::BlockNumber;
type Hash = <T::Chain as Chain>::Hash;
type Hasher = <T::Chain as Chain>::Hasher;
type Header = <T::Chain as Chain>::Header;
type AccountId = <T::Chain as Chain>::AccountId;
type Balance = <T::Chain as Chain>::Balance;
type Nonce = <T::Chain as Chain>::Nonce;
type Signature = <T::Chain as Chain>::Signature;
const STATE_VERSION: StateVersion = <T::Chain as Chain>::STATE_VERSION;
fn max_extrinsic_size() -> u32 {
<T::Chain as Chain>::max_extrinsic_size()
}
fn max_extrinsic_weight() -> Weight {
<T::Chain as Chain>::max_extrinsic_weight()
}
}
pub trait Teyrchain: Chain {
const TEYRCHAIN_ID: u32;
const MAX_HEADER_SIZE: u32;
}
impl<T> Teyrchain for T
where
T: Chain + UnderlyingChainProvider,
<T as UnderlyingChainProvider>::Chain: Teyrchain,
{
const TEYRCHAIN_ID: u32 = <<T as UnderlyingChainProvider>::Chain as Teyrchain>::TEYRCHAIN_ID;
const MAX_HEADER_SIZE: u32 =
<<T as UnderlyingChainProvider>::Chain as Teyrchain>::MAX_HEADER_SIZE;
}
pub struct TeyrchainIdOf<Para>(pezsp_std::marker::PhantomData<Para>);
impl<Para: Teyrchain> pezframe_support::traits::Get<u32> for TeyrchainIdOf<Para> {
fn get() -> u32 {
Para::TEYRCHAIN_ID
}
}
pub type UnderlyingChainOf<C> = <C as UnderlyingChainProvider>::Chain;
pub type BlockNumberOf<C> = <C as Chain>::BlockNumber;
pub type HashOf<C> = <C as Chain>::Hash;
pub type HasherOf<C> = <C as Chain>::Hasher;
pub type HeaderOf<C> = <C as Chain>::Header;
pub type AccountIdOf<C> = <C as Chain>::AccountId;
pub type BalanceOf<C> = <C as Chain>::Balance;
pub type NonceOf<C> = <C as Chain>::Nonce;
pub type SignatureOf<C> = <C as Chain>::Signature;
pub type AccountPublicOf<C> = <SignatureOf<C> as Verify>::Signer;
pub type TransactionEraOf<C> = crate::TransactionEra<BlockNumberOf<C>, HashOf<C>>;
#[macro_export]
macro_rules! decl_bridge_finality_runtime_apis {
($chain: ident $(, $consensus: ident => $justification_type: ty)?) => {
pezbp_runtime::paste::item! {
mod [<$chain _finality_api>] {
use super::*;
pub const [<BEST_FINALIZED_ $chain:upper _HEADER_METHOD>]: &str =
stringify!([<$chain:camel FinalityApi_best_finalized>]);
pub const [<FREE_HEADERS_INTERVAL_FOR_ $chain:upper _METHOD>]: &str =
stringify!([<$chain:camel FinalityApi_free_headers_interval>]);
$(
pub const [<$chain:upper _SYNCED_HEADERS_ $consensus:upper _INFO_METHOD>]: &str =
stringify!([<$chain:camel FinalityApi_synced_headers_ $consensus:lower _info>]);
)?
pezsp_api::decl_runtime_apis! {
pub trait [<$chain:camel FinalityApi>] {
fn best_finalized() -> Option<pezbp_runtime::HeaderId<Hash, BlockNumber>>;
fn free_headers_interval() -> Option<BlockNumber>;
$(
fn [<synced_headers_ $consensus:lower _info>](
) -> $crate::private::Vec<$justification_type>;
)?
}
}
}
pub use [<$chain _finality_api>]::*;
}
};
($chain: ident, grandpa) => {
decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_pez_chain::StoredHeaderGrandpaInfo<Header>);
};
}
#[doc(hidden)]
pub mod __private {
pub use codec;
}
#[macro_export]
macro_rules! decl_bridge_messages_runtime_apis {
($chain: ident, $lane_id_type:ty) => {
pezbp_runtime::paste::item! {
mod [<$chain _messages_api>] {
use super::*;
pub const [<TO_ $chain:upper _MESSAGE_DETAILS_METHOD>]: &str =
stringify!([<To $chain:camel OutboundLaneApi_message_details>]);
pub const [<FROM_ $chain:upper _MESSAGE_DETAILS_METHOD>]: &str =
stringify!([<From $chain:camel InboundLaneApi_message_details>]);
pezsp_api::decl_runtime_apis! {
pub trait [<To $chain:camel OutboundLaneApi>] {
fn message_details(
lane: $lane_id_type,
begin: bp_messages::MessageNonce,
end: bp_messages::MessageNonce,
) -> $crate::private::Vec<bp_messages::OutboundMessageDetails>;
}
pub trait [<From $chain:camel InboundLaneApi>] {
fn message_details(
lane: $lane_id_type,
messages: $crate::private::Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>,
) -> $crate::private::Vec<bp_messages::InboundMessageDetails>;
}
}
}
pub use [<$chain _messages_api>]::*;
}
};
}
#[macro_export]
macro_rules! decl_bridge_runtime_apis {
($chain: ident $(, $consensus: ident, $lane_id_type:ident)?) => {
pezbp_runtime::decl_bridge_finality_runtime_apis!($chain $(, $consensus)?);
pezbp_runtime::decl_bridge_messages_runtime_apis!($chain, $lane_id_type);
};
}